From 4705b5469b2d2b4b391ba0747cc2355bfb08db9c Mon Sep 17 00:00:00 2001 From: Alexander Lisovik Date: Tue, 27 Jun 2023 10:10:15 +0200 Subject: [PATCH 01/19] Expose sessionProperties and requiredNamespaces to Session --- .../ConnectionDetailsView.swift | 35 +++++++++++++++++++ .../SessionProposalInteractor.swift | 2 +- .../Wallet/WalletRequestSubscriber.swift | 4 +-- .../Engine/Common/ApproveEngine.swift | 26 ++++++++++---- Sources/WalletConnectSign/Session.swift | 2 ++ .../WalletConnectSign/Sign/SignClient.swift | 4 +-- .../Sign/SignClientProtocol.swift | 2 +- .../Types/Session/SessionType.swift | 1 + .../Types/Session/WCSession.swift | 13 +++++-- Sources/Web3Wallet/Web3WalletClient.swift | 6 ++-- 10 files changed, 77 insertions(+), 18 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/ConnectionDetails/ConnectionDetailsView.swift b/Example/WalletApp/PresentationLayer/Wallet/ConnectionDetails/ConnectionDetailsView.swift index 91f2f6f57..65a838b11 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/ConnectionDetails/ConnectionDetailsView.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/ConnectionDetails/ConnectionDetailsView.swift @@ -110,6 +110,41 @@ struct ConnectionDetailsView: View { .padding(.top, 30) } + if let sessionProperties = presenter.session.sessionProperties { + VStack(alignment: .leading) { + Text("sessionProperties") + .font(.system(size: 15, weight: .semibold, design: .rounded)) + .foregroundColor(.whiteBackground) + .padding(.horizontal, 8) + .padding(.vertical, 5) + .background(Color.grey70) + .cornerRadius(28, corners: .allCorners) + .padding(.leading, 15) + .padding(.top, 9) + + VStack(spacing: 0) { + TagsView(items: sessionProperties.map { "\($0): \($1)" }) { + Text($0) + .foregroundColor(.cyanBackround) + .font(.system(size: 13, weight: .semibold, design: .rounded)) + .padding(.horizontal, 8) + .padding(.vertical, 3) + .background(Color.cyanBackround.opacity(0.2)) + .cornerRadius(10, corners: .allCorners) + } + .padding(10) + } + .background(Color.whiteBackground) + .cornerRadius(20, corners: .allCorners) + .padding(.horizontal, 5) + .padding(.bottom, 5) + } + .background(Color("grey95")) + .cornerRadius(25, corners: .allCorners) + .padding(.horizontal, 20) + .padding(.top, 30) + } + Button { presenter.onDelete() } label: { diff --git a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift index 0055364f4..3df2dece3 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift @@ -28,7 +28,7 @@ final class SessionProposalInteractor { events: Array(supportedEvents), accounts: supportedAccounts ) - try await Web3Wallet.instance.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await Web3Wallet.instance.approve(proposalId: proposal.id, namespaces: sessionNamespaces, sessionProperties: proposal.sessionProperties) } catch { print(error) } diff --git a/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift b/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift index 18cda08d3..2b8164eb7 100644 --- a/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift +++ b/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift @@ -38,7 +38,7 @@ class WalletRequestSubscriber { peerMetadata: payload.request.requester.metadata ) - let request = AuthRequest(id: payload.id, payload: payload.request.payloadParams) + let request = AuthRequest(id: payload.id, payload: payload.request.payloadParams, appMetadata: payload.request.requester.metadata) guard let verifyClient else { onRequest?((request, nil)) @@ -51,7 +51,7 @@ class WalletRequestSubscriber { origin: origin, domain: payload.request.payloadParams.domain ) - onRequest?((request, verifyContext)) + onRequest?((request, verifyContext, payload.request.requester.metadata)) } }.store(in: &publishers) } diff --git a/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift b/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift index acb93af8b..7594c3a9f 100644 --- a/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift +++ b/Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift @@ -56,8 +56,7 @@ final class ApproveEngine { setupResponseErrorSubscriptions() } - func approveProposal(proposerPubKey: String, validating sessionNamespaces: [String: SessionNamespace]) async throws { - + func approveProposal(proposerPubKey: String, validating sessionNamespaces: [String: SessionNamespace], sessionProperties: [String: String]? = nil) async throws { guard let payload = try proposalPayloadsStore.get(key: proposerPubKey) else { throw Errors.wrongRequestParams } @@ -87,9 +86,19 @@ final class ApproveEngine { let result = SessionType.ProposeResponse(relay: relay, responderPublicKey: selfPublicKey.hexRepresentation) let response = RPCResponse(id: payload.id, result: result) - async let proposeResponse: () = networkingInteractor.respond(topic: payload.topic, response: response, protocolMethod: SessionProposeProtocolMethod()) + async let proposeResponse: () = networkingInteractor.respond( + topic: payload.topic, + response: response, + protocolMethod: SessionProposeProtocolMethod() + ) - async let settleRequest: () = settle(topic: sessionTopic, proposal: proposal, namespaces: sessionNamespaces, pairingTopic: pairingTopic) + async let settleRequest: () = settle( + topic: sessionTopic, + proposal: proposal, + namespaces: sessionNamespaces, + sessionProperties: sessionProperties, + pairingTopic: pairingTopic + ) _ = try await [proposeResponse, settleRequest] @@ -108,7 +117,7 @@ final class ApproveEngine { // TODO: Delete pairing if inactive } - func settle(topic: String, proposal: SessionProposal, namespaces: [String: SessionNamespace], pairingTopic: String) async throws { + func settle(topic: String, proposal: SessionProposal, namespaces: [String: SessionNamespace], sessionProperties: [String: String]? = nil, pairingTopic: String) async throws { guard let agreementKeys = kms.getAgreementSecret(for: topic) else { throw Errors.agreementMissingOrInvalid } @@ -129,7 +138,9 @@ final class ApproveEngine { relay: relay, controller: selfParticipant, namespaces: namespaces, - expiry: Int64(expiry)) + sessionProperties: sessionProperties, + expiry: Int64(expiry) + ) let session = WCSession( topic: topic, @@ -139,7 +150,8 @@ final class ApproveEngine { peerParticipant: proposal.proposer, settleParams: settleParams, requiredNamespaces: proposal.requiredNamespaces, - acknowledged: false) + acknowledged: false + ) logger.debug("Sending session settle request") diff --git a/Sources/WalletConnectSign/Session.swift b/Sources/WalletConnectSign/Session.swift index ef3a2205f..0d6ca96a8 100644 --- a/Sources/WalletConnectSign/Session.swift +++ b/Sources/WalletConnectSign/Session.swift @@ -7,7 +7,9 @@ public struct Session { public let topic: String public let pairingTopic: String public let peer: AppMetadata + public let requiredNamespaces: [String: ProposalNamespace] public let namespaces: [String: SessionNamespace] + public let sessionProperties: [String: String]? public let expiryDate: Date public static var defaultTimeToLive: Int64 { WCSession.defaultTimeToLive diff --git a/Sources/WalletConnectSign/Sign/SignClient.swift b/Sources/WalletConnectSign/Sign/SignClient.swift index 7d18d08ed..11830442c 100644 --- a/Sources/WalletConnectSign/Sign/SignClient.swift +++ b/Sources/WalletConnectSign/Sign/SignClient.swift @@ -239,8 +239,8 @@ public final class SignClient: SignClientProtocol { /// - Parameters: /// - proposalId: Session Proposal id /// - namespaces: namespaces for given session, needs to contain at least required namespaces proposed by dApp. - public func approve(proposalId: String, namespaces: [String: SessionNamespace]) async throws { - try await approveEngine.approveProposal(proposerPubKey: proposalId, validating: namespaces) + public func approve(proposalId: String, namespaces: [String: SessionNamespace], sessionProperties: [String: String]? = nil) async throws { + try await approveEngine.approveProposal(proposerPubKey: proposalId, validating: namespaces, sessionProperties: sessionProperties) } /// For the wallet to reject a session proposal. diff --git a/Sources/WalletConnectSign/Sign/SignClientProtocol.swift b/Sources/WalletConnectSign/Sign/SignClientProtocol.swift index 397a59bf4..f23857f04 100644 --- a/Sources/WalletConnectSign/Sign/SignClientProtocol.swift +++ b/Sources/WalletConnectSign/Sign/SignClientProtocol.swift @@ -13,7 +13,7 @@ public protocol SignClientProtocol { func connect(requiredNamespaces: [String: ProposalNamespace], optionalNamespaces: [String: ProposalNamespace]?, sessionProperties: [String: String]?, topic: String) async throws func request(params: Request) async throws - func approve(proposalId: String, namespaces: [String: SessionNamespace]) async throws + func approve(proposalId: String, namespaces: [String: SessionNamespace], sessionProperties: [String: String]?) async throws func reject(proposalId: String, reason: RejectionReason) async throws func update(topic: String, namespaces: [String: SessionNamespace]) async throws func extend(topic: String) async throws diff --git a/Sources/WalletConnectSign/Types/Session/SessionType.swift b/Sources/WalletConnectSign/Types/Session/SessionType.swift index 2731e448c..cc838f084 100644 --- a/Sources/WalletConnectSign/Types/Session/SessionType.swift +++ b/Sources/WalletConnectSign/Types/Session/SessionType.swift @@ -16,6 +16,7 @@ internal enum SessionType { let relay: RelayProtocolOptions let controller: Participant let namespaces: [String: SessionNamespace] + let sessionProperties: [String: String]? let expiry: Int64 } diff --git a/Sources/WalletConnectSign/Types/Session/WCSession.swift b/Sources/WalletConnectSign/Types/Session/WCSession.swift index 6778f66b5..6d4d2fa7a 100644 --- a/Sources/WalletConnectSign/Types/Session/WCSession.swift +++ b/Sources/WalletConnectSign/Types/Session/WCSession.swift @@ -18,6 +18,7 @@ struct WCSession: SequenceObject, Equatable { private(set) var timestamp: Date private(set) var namespaces: [String: SessionNamespace] private(set) var requiredNamespaces: [String: ProposalNamespace] + private(set) var sessionProperties: [String: String]? static var defaultTimeToLive: Int64 { Int64(7*Time.day) @@ -43,6 +44,7 @@ struct WCSession: SequenceObject, Equatable { self.selfParticipant = selfParticipant self.peerParticipant = peerParticipant self.namespaces = settleParams.namespaces + self.sessionProperties = settleParams.sessionProperties self.requiredNamespaces = requiredNamespaces self.acknowledged = acknowledged self.expiryDate = Date(timeIntervalSince1970: TimeInterval(settleParams.expiry)) @@ -58,6 +60,7 @@ struct WCSession: SequenceObject, Equatable { selfParticipant: Participant, peerParticipant: Participant, namespaces: [String: SessionNamespace], + sessionProperties: [String: String], requiredNamespaces: [String: ProposalNamespace], events: Set, accounts: Set, @@ -72,6 +75,7 @@ struct WCSession: SequenceObject, Equatable { self.selfParticipant = selfParticipant self.peerParticipant = peerParticipant self.namespaces = namespaces + self.sessionProperties = sessionProperties self.requiredNamespaces = requiredNamespaces self.acknowledged = acknowledged self.expiryDate = Date(timeIntervalSince1970: TimeInterval(expiry)) @@ -165,8 +169,11 @@ struct WCSession: SequenceObject, Equatable { topic: topic, pairingTopic: pairingTopic, peer: peerParticipant.metadata, + requiredNamespaces: requiredNamespaces, namespaces: namespaces, - expiryDate: expiryDate) + sessionProperties: sessionProperties, + expiryDate: expiryDate + ) } } @@ -175,7 +182,7 @@ struct WCSession: SequenceObject, Equatable { extension WCSession { enum CodingKeys: String, CodingKey { - case topic, pairingTopic, relay, selfParticipant, peerParticipant, expiryDate, acknowledged, controller, namespaces, timestamp, requiredNamespaces + case topic, pairingTopic, relay, selfParticipant, peerParticipant, expiryDate, acknowledged, controller, namespaces, timestamp, requiredNamespaces, sessionProperties } init(from decoder: Decoder) throws { @@ -186,6 +193,7 @@ extension WCSession { self.selfParticipant = try container.decode(Participant.self, forKey: .selfParticipant) self.peerParticipant = try container.decode(Participant.self, forKey: .peerParticipant) self.namespaces = try container.decode([String: SessionNamespace].self, forKey: .namespaces) + self.sessionProperties = try container.decode([String: String]?.self, forKey: .sessionProperties) self.acknowledged = try container.decode(Bool.self, forKey: .acknowledged) self.expiryDate = try container.decode(Date.self, forKey: .expiryDate) self.timestamp = try container.decode(Date.self, forKey: .timestamp) @@ -202,6 +210,7 @@ extension WCSession { try container.encode(selfParticipant, forKey: .selfParticipant) try container.encode(peerParticipant, forKey: .peerParticipant) try container.encode(namespaces, forKey: .namespaces) + try container.encode(sessionProperties, forKey: .sessionProperties) try container.encode(acknowledged, forKey: .acknowledged) try container.encode(expiryDate, forKey: .expiryDate) try container.encode(timestamp, forKey: .timestamp) diff --git a/Sources/Web3Wallet/Web3WalletClient.swift b/Sources/Web3Wallet/Web3WalletClient.swift index 0f117f0a8..4b96b692b 100644 --- a/Sources/Web3Wallet/Web3WalletClient.swift +++ b/Sources/Web3Wallet/Web3WalletClient.swift @@ -26,7 +26,7 @@ public class Web3WalletClient { /// Publisher that sends authentication requests /// /// Wallet should subscribe on events in order to receive auth requests. - public var authRequestPublisher: AnyPublisher<(request: AuthRequest, context: VerifyContext?), Never> { + public var authRequestPublisher: AnyPublisher<(request: AuthRequest, context: VerifyContext?, appMetadata: payload.request.requester.metadata), Never> { authClient.authRequestPublisher.eraseToAnyPublisher() } @@ -87,8 +87,8 @@ public class Web3WalletClient { /// - Parameters: /// - proposalId: Session Proposal id /// - namespaces: namespaces for given session, needs to contain at least required namespaces proposed by dApp. - public func approve(proposalId: String, namespaces: [String: SessionNamespace]) async throws { - try await signClient.approve(proposalId: proposalId, namespaces: namespaces) + public func approve(proposalId: String, namespaces: [String: SessionNamespace], sessionProperties: [String: String]? = nil) async throws { + try await signClient.approve(proposalId: proposalId, namespaces: namespaces, sessionProperties: sessionProperties) } /// For the wallet to reject a session proposal. From 8de9e2ff3e0d878758c13d3f2df3c5cf41e1c0c1 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 28 Jun 2023 14:25:07 +0200 Subject: [PATCH 02/19] add relay client factory --- Example/IntegrationTests/Auth/AuthTests.swift | 9 ++- Example/IntegrationTests/Chat/ChatTests.swift | 11 ++- Sources/WalletConnectRelay/RelayClient.swift | 39 +---------- .../RelayClientFactory.swift | 70 +++++++++++++++++++ 4 files changed, 89 insertions(+), 40 deletions(-) create mode 100644 Sources/WalletConnectRelay/RelayClientFactory.swift diff --git a/Example/IntegrationTests/Auth/AuthTests.swift b/Example/IntegrationTests/Auth/AuthTests.swift index 6fda1d84a..14c88b746 100644 --- a/Example/IntegrationTests/Auth/AuthTests.swift +++ b/Example/IntegrationTests/Auth/AuthTests.swift @@ -32,8 +32,15 @@ final class AuthTests: XCTestCase { func makeClients(prefix: String, iatProvider: IATProvider) -> (PairingClient, AuthClient) { let logger = ConsoleLogger(suffix: prefix, loggingLevel: .debug) + let keyValueStorage = RuntimeKeyValueStorage() let keychain = KeychainStorageMock() - let relayClient = RelayClient(relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keychainStorage: keychain, socketFactory: DefaultSocketFactory(), logger: logger) + let relayClient = RelayClientFactory.create( + relayHost: InputConfig.relayHost, + projectId: InputConfig.projectId, + keyValueStorage: keyValueStorage, + keychainStorage: keychain, + socketFactory: DefaultSocketFactory(), + logger: logger) let keyValueStorage = RuntimeKeyValueStorage() let networkingClient = NetworkingClientFactory.create( diff --git a/Example/IntegrationTests/Chat/ChatTests.swift b/Example/IntegrationTests/Chat/ChatTests.swift index c2aaab6c5..69f013444 100644 --- a/Example/IntegrationTests/Chat/ChatTests.swift +++ b/Example/IntegrationTests/Chat/ChatTests.swift @@ -48,9 +48,16 @@ final class ChatTests: XCTestCase { func makeClient(prefix: String, account: Account) -> ChatClient { let keyserverURL = URL(string: "https://keys.walletconnect.com")! let logger = ConsoleLogger(suffix: prefix, loggingLevel: .debug) - let keychain = KeychainStorageMock() - let relayClient = RelayClient(relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keychainStorage: keychain, socketFactory: DefaultSocketFactory(), logger: logger) let keyValueStorage = RuntimeKeyValueStorage() + let keychain = KeychainStorageMock() + let relayClient = RelayClientFactory.create( + relayHost: InputConfig.relayHost, + projectId: InputConfig.projectId, + keyValueStorage: keyValueStorage, + keychainStorage: keychain, + socketFactory: DefaultSocketFactory(), + logger: logger) + let networkingInteractor = NetworkingClientFactory.create( relayClient: relayClient, logger: logger, diff --git a/Sources/WalletConnectRelay/RelayClient.swift b/Sources/WalletConnectRelay/RelayClient.swift index a84c4c264..ddb9cf91b 100644 --- a/Sources/WalletConnectRelay/RelayClient.swift +++ b/Sources/WalletConnectRelay/RelayClient.swift @@ -47,12 +47,12 @@ public final class RelayClient { init( dispatcher: Dispatching, logger: ConsoleLogging, - keyValueStorage: KeyValueStorage, + rpcHistory: RPCHistory, clientIdStorage: ClientIdStoring ) { self.logger = logger self.dispatcher = dispatcher - self.rpcHistory = RPCHistoryFactory.createForRelay(keyValueStorage: keyValueStorage) + self.rpcHistory = rpcHistory self.clientIdStorage = clientIdStorage setUpBindings() } @@ -63,41 +63,6 @@ public final class RelayClient { } } - /// Instantiates Relay Client - /// - Parameters: - /// - relayHost: proxy server host that your application will use to connect to Relay Network. If you register your project at `www.walletconnect.com` you can use `relay.walletconnect.com` - /// - projectId: an optional parameter used to access the public WalletConnect infrastructure. Go to `www.walletconnect.com` for info. - /// - keyValueStorage: by default WalletConnect SDK will store sequences in UserDefaults - /// - socketConnectionType: socket connection type - /// - logger: logger instance - public convenience init( - relayHost: String, - projectId: String, - keyValueStorage: KeyValueStorage = UserDefaults.standard, - keychainStorage: KeychainStorageProtocol = KeychainStorage(serviceIdentifier: "com.walletconnect.sdk"), - socketFactory: WebSocketFactory, - socketConnectionType: SocketConnectionType = .automatic, - logger: ConsoleLogging = ConsoleLogger(loggingLevel: .debug) - ) { - let clientIdStorage = ClientIdStorage(keychain: keychainStorage) - let socketAuthenticator = ClientIdAuthenticator( - clientIdStorage: clientIdStorage, - url: "wss://\(relayHost)" - ) - let relayUrlFactory = RelayUrlFactory( - relayHost: relayHost, - projectId: projectId, - socketAuthenticator: socketAuthenticator - ) - let dispatcher = Dispatcher( - socketFactory: socketFactory, - relayUrlFactory: relayUrlFactory, - socketConnectionType: socketConnectionType, - logger: logger - ) - self.init(dispatcher: dispatcher, logger: logger, keyValueStorage: keyValueStorage, clientIdStorage: clientIdStorage) - } - /// Connects web socket /// /// Use this method for manual socket connection only diff --git a/Sources/WalletConnectRelay/RelayClientFactory.swift b/Sources/WalletConnectRelay/RelayClientFactory.swift new file mode 100644 index 000000000..450179669 --- /dev/null +++ b/Sources/WalletConnectRelay/RelayClientFactory.swift @@ -0,0 +1,70 @@ +// +import Foundation + + +public struct RelayClientFactory { + + public static func create( + relayHost: String, + projectId: String, + socketFactory: WebSocketFactory, + socketConnectionType: SocketConnectionType + ) -> RelayClient { + + let keyValueStorage = UserDefaults.standard + + let serviceIdentifier = "com.walletconnect.sdk" + + let keychainStorage = KeychainStorage(serviceIdentifier: serviceIdentifier, attrAccessible: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly) + + let logger = ConsoleLogger(suffix: "🚄" ,loggingLevel: .debug) + + let clientIdMigrationController = ClientIdMigrationController(serviceIdentifier: serviceIdentifier, keyValueStorage: keyValueStorage, logger: logger) + + return RelayClientFactory.create( + relayHost: relayHost, + projectId: projectId, + keyValueStorage: keyValueStorage, + keychainStorage: keychainStorage, + socketFactory: socketFactory, + socketConnectionType: socketConnectionType, + logger: logger, + clientIdMigrationController: clientIdMigrationController + ) + } + + + public static func create( + relayHost: String, + projectId: String, + keyValueStorage: KeyValueStorage, + keychainStorage: KeychainStorageProtocol, + socketFactory: WebSocketFactory, + socketConnectionType: SocketConnectionType = .automatic, + logger: ConsoleLogging, + clientIdMigrationController: ClientIdMigrationController? = nil + ) -> RelayClient { + + let clientIdStorage = ClientIdStorage(keychain: keychainStorage, clientIdMigrationController: clientIdMigrationController) + + let socketAuthenticator = SocketAuthenticator( + clientIdStorage: clientIdStorage, + relayHost: relayHost + ) + let relayUrlFactory = RelayUrlFactory( + relayHost: relayHost, + projectId: projectId, + socketAuthenticator: socketAuthenticator + ) + let dispatcher = Dispatcher( + socketFactory: socketFactory, + relayUrlFactory: relayUrlFactory, + socketConnectionType: socketConnectionType, + logger: logger + ) + + let rpcHistory = RPCHistoryFactory.createForRelay(keyValueStorage: keyValueStorage) + + return RelayClient(dispatcher: dispatcher, logger: logger, rpcHistory: rpcHistory, clientIdStorage: clientIdStorage) + } +} From e52e345ec5177e841ded1691406ef57aeb336c9f Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 28 Jun 2023 14:49:15 +0200 Subject: [PATCH 03/19] fix integration tests --- Example/IntegrationTests/Auth/AuthTests.swift | 1 - .../History/HistoryTests.swift | 2 +- .../Pairing/PairingTests.swift | 2 +- Example/IntegrationTests/Push/PushTests.swift | 4 ++-- .../Sign/SignClientTests.swift | 5 ++--- Example/IntegrationTests/Sync/SyncTests.swift | 8 +++++++- Sources/WalletConnectRelay/Relay.swift | 2 +- .../RelayClientFactory.swift | 18 ++++++------------ 8 files changed, 20 insertions(+), 22 deletions(-) diff --git a/Example/IntegrationTests/Auth/AuthTests.swift b/Example/IntegrationTests/Auth/AuthTests.swift index 14c88b746..a90de5067 100644 --- a/Example/IntegrationTests/Auth/AuthTests.swift +++ b/Example/IntegrationTests/Auth/AuthTests.swift @@ -41,7 +41,6 @@ final class AuthTests: XCTestCase { keychainStorage: keychain, socketFactory: DefaultSocketFactory(), logger: logger) - let keyValueStorage = RuntimeKeyValueStorage() let networkingClient = NetworkingClientFactory.create( relayClient: relayClient, diff --git a/Example/IntegrationTests/History/HistoryTests.swift b/Example/IntegrationTests/History/HistoryTests.swift index ebd8f202e..8667a9224 100644 --- a/Example/IntegrationTests/History/HistoryTests.swift +++ b/Example/IntegrationTests/History/HistoryTests.swift @@ -24,7 +24,7 @@ final class HistoryTests: XCTestCase { } private func makeRelayClient(prefix: String, keychain: KeychainStorageProtocol) -> RelayClient { - return RelayClient( + return RelayClientFactory.create( relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keyValueStorage: RuntimeKeyValueStorage(), diff --git a/Example/IntegrationTests/Pairing/PairingTests.swift b/Example/IntegrationTests/Pairing/PairingTests.swift index 267ed68d8..990868594 100644 --- a/Example/IntegrationTests/Pairing/PairingTests.swift +++ b/Example/IntegrationTests/Pairing/PairingTests.swift @@ -29,7 +29,7 @@ final class PairingTests: XCTestCase { let pairingLogger = ConsoleLogger(suffix: prefix + " [Pairing]", loggingLevel: .debug) let networkingLogger = ConsoleLogger(suffix: prefix + " [Networking]", loggingLevel: .debug) - let relayClient = RelayClient( + let relayClient = RelayClientFactory.create( relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keyValueStorage: RuntimeKeyValueStorage(), diff --git a/Example/IntegrationTests/Push/PushTests.swift b/Example/IntegrationTests/Push/PushTests.swift index 328ea02b3..52ee05a29 100644 --- a/Example/IntegrationTests/Push/PushTests.swift +++ b/Example/IntegrationTests/Push/PushTests.swift @@ -32,10 +32,10 @@ final class PushTests: XCTestCase { let pairingLogger = ConsoleLogger(suffix: prefix + " [Pairing]", loggingLevel: .debug) let networkingLogger = ConsoleLogger(suffix: prefix + " [Networking]", loggingLevel: .debug) - let relayClient = RelayClient( + let relayClient = RelayClientFactory.create( relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, - keyValueStorage: RuntimeKeyValueStorage(), + keyValueStorage: keyValueStorage, keychainStorage: keychain, socketFactory: DefaultSocketFactory(), logger: relayLogger) diff --git a/Example/IntegrationTests/Sign/SignClientTests.swift b/Example/IntegrationTests/Sign/SignClientTests.swift index 583cd886a..62aaf4065 100644 --- a/Example/IntegrationTests/Sign/SignClientTests.swift +++ b/Example/IntegrationTests/Sign/SignClientTests.swift @@ -14,16 +14,15 @@ final class SignClientTests: XCTestCase { static private func makeClientDelegate(name: String) -> ClientDelegate { let logger = ConsoleLogger(suffix: name, loggingLevel: .debug) let keychain = KeychainStorageMock() - let relayClient = RelayClient( + let keyValueStorage = RuntimeKeyValueStorage() + let relayClient = RelayClientFactory.create( relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keyValueStorage: RuntimeKeyValueStorage(), keychainStorage: keychain, socketFactory: DefaultSocketFactory(), - socketConnectionType: .automatic, logger: logger ) - let keyValueStorage = RuntimeKeyValueStorage() let networkingClient = NetworkingClientFactory.create( relayClient: relayClient, diff --git a/Example/IntegrationTests/Sync/SyncTests.swift b/Example/IntegrationTests/Sync/SyncTests.swift index 595052dd0..3f6464da4 100644 --- a/Example/IntegrationTests/Sync/SyncTests.swift +++ b/Example/IntegrationTests/Sync/SyncTests.swift @@ -57,7 +57,13 @@ final class SyncTests: XCTestCase { let kms = KeyManagementService(keychain: keychain) let derivationService = SyncDerivationService(syncStorage: syncSignatureStore, bip44: DefaultBIP44Provider(), kms: kms) let logger = ConsoleLogger(suffix: suffix, loggingLevel: .debug) - let relayClient = RelayClient(relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keychainStorage: keychain, socketFactory: DefaultSocketFactory(), logger: logger) + let relayClient = RelayClientFactory.create( + relayHost: InputConfig.relayHost, + projectId: InputConfig.projectId, + keyValueStorage: RuntimeKeyValueStorage(), + keychainStorage: keychain, + socketFactory: DefaultSocketFactory(), + logger: logger) let networkingInteractor = NetworkingClientFactory.create( relayClient: relayClient, logger: logger, diff --git a/Sources/WalletConnectRelay/Relay.swift b/Sources/WalletConnectRelay/Relay.swift index 9e118558e..38390fbbe 100644 --- a/Sources/WalletConnectRelay/Relay.swift +++ b/Sources/WalletConnectRelay/Relay.swift @@ -12,7 +12,7 @@ public class Relay { guard let config = Relay.config else { fatalError("Error - you must call Relay.configure(_:) before accessing the shared instance.") } - return RelayClient( + return RelayClientFactory.create( relayHost: config.relayHost, projectId: config.projectId, socketFactory: config.socketFactory, diff --git a/Sources/WalletConnectRelay/RelayClientFactory.swift b/Sources/WalletConnectRelay/RelayClientFactory.swift index 450179669..0d6ce5a2c 100644 --- a/Sources/WalletConnectRelay/RelayClientFactory.swift +++ b/Sources/WalletConnectRelay/RelayClientFactory.swift @@ -13,14 +13,10 @@ public struct RelayClientFactory { let keyValueStorage = UserDefaults.standard - let serviceIdentifier = "com.walletconnect.sdk" - - let keychainStorage = KeychainStorage(serviceIdentifier: serviceIdentifier, attrAccessible: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly) + let keychainStorage = KeychainStorage(serviceIdentifier: "com.walletconnect.sdk") let logger = ConsoleLogger(suffix: "🚄" ,loggingLevel: .debug) - let clientIdMigrationController = ClientIdMigrationController(serviceIdentifier: serviceIdentifier, keyValueStorage: keyValueStorage, logger: logger) - return RelayClientFactory.create( relayHost: relayHost, projectId: projectId, @@ -28,8 +24,7 @@ public struct RelayClientFactory { keychainStorage: keychainStorage, socketFactory: socketFactory, socketConnectionType: socketConnectionType, - logger: logger, - clientIdMigrationController: clientIdMigrationController + logger: logger ) } @@ -41,15 +36,14 @@ public struct RelayClientFactory { keychainStorage: KeychainStorageProtocol, socketFactory: WebSocketFactory, socketConnectionType: SocketConnectionType = .automatic, - logger: ConsoleLogging, - clientIdMigrationController: ClientIdMigrationController? = nil + logger: ConsoleLogging ) -> RelayClient { - let clientIdStorage = ClientIdStorage(keychain: keychainStorage, clientIdMigrationController: clientIdMigrationController) + let clientIdStorage = ClientIdStorage(keychain: keychainStorage) - let socketAuthenticator = SocketAuthenticator( + let socketAuthenticator = ClientIdAuthenticator( clientIdStorage: clientIdStorage, - relayHost: relayHost + url: "wss://\(relayHost)" ) let relayUrlFactory = RelayUrlFactory( relayHost: relayHost, From 122df5078f4773a2b4783189bcf5f1ed13dfaed5 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 28 Jun 2023 14:55:49 +0200 Subject: [PATCH 04/19] fix unit tests --- Tests/RelayerTests/RelayClientTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/RelayerTests/RelayClientTests.swift b/Tests/RelayerTests/RelayClientTests.swift index 7a6841a84..5905e6e70 100644 --- a/Tests/RelayerTests/RelayClientTests.swift +++ b/Tests/RelayerTests/RelayClientTests.swift @@ -15,7 +15,8 @@ final class RelayClientTests: XCTestCase { dispatcher = DispatcherMock() let logger = ConsoleLogger() let clientIdStorage = ClientIdStorageMock() - sut = RelayClient(dispatcher: dispatcher, logger: logger, keyValueStorage: RuntimeKeyValueStorage(), clientIdStorage: clientIdStorage) + let rpcHistory = RPCHistoryFactory.createForRelay(keyValueStorage: RuntimeKeyValueStorage()) + sut = RelayClient(dispatcher: dispatcher, logger: logger, rpcHistory: rpcHistory, clientIdStorage: clientIdStorage) } override func tearDown() { From 788eaf45592bedc50817ea7a0b1305438c750548 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 16 Jun 2023 07:28:31 +0300 Subject: [PATCH 05/19] CodableStore to SyncStore --- Package.swift | 2 +- .../Client/Common/DeletePushSubscriptionService.swift | 6 +++--- .../Common/DeletePushSubscriptionSubscriber.swift | 4 ++-- .../Client/Common/PushResubscribeService.swift | 4 ++-- .../Client/Common/SubscriptionsProvider.swift | 4 ++-- .../Client/Dapp/DappPushClientFactory.swift | 2 +- .../wc_notifyUpdate/NotifyUpdateRequester.swift | 7 +++---- .../NotifyUpdateResponseSubscriber.swift | 4 ++-- .../PushSubscribeResponseSubscriber.swift | 4 ++-- .../Client/Wallet/PushSubscriptionsObserver.swift | 4 ++-- .../Client/Wallet/WalletPushClientFactory.swift | 2 +- Sources/WalletConnectPush/PushImports.swift | 3 ++- .../WalletConnectPush/Types/PushSubscription.swift | 6 +++++- Sources/WalletConnectSync/Stores/SyncStore.swift | 11 +++++++++++ 14 files changed, 39 insertions(+), 24 deletions(-) diff --git a/Package.swift b/Package.swift index 23d31ae0f..bd74fd149 100644 --- a/Package.swift +++ b/Package.swift @@ -76,7 +76,7 @@ let package = Package( path: "Sources/Web3Wallet"), .target( name: "WalletConnectPush", - dependencies: ["WalletConnectPairing", "WalletConnectEcho", "WalletConnectNetworking", "WalletConnectIdentity", "WalletConnectSigner"], + dependencies: ["WalletConnectPairing", "WalletConnectEcho", "WalletConnectIdentity", "WalletConnectSync"], path: "Sources/WalletConnectPush"), .target( name: "WalletConnectEcho", diff --git a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift index 3f32e75df..0693de806 100644 --- a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift +++ b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift @@ -9,12 +9,12 @@ class DeletePushSubscriptionService { private let networkingInteractor: NetworkInteracting private let kms: KeyManagementServiceProtocol private let logger: ConsoleLogging - private let pushSubscriptionStore: CodableStore + private let pushSubscriptionStore: SyncStore private let pushMessagesDatabase: PushMessagesDatabase? init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, - pushSubscriptionStore: CodableStore, + pushSubscriptionStore: SyncStore, pushMessagesDatabase: PushMessagesDatabase?) { self.networkingInteractor = networkingInteractor self.kms = kms @@ -26,7 +26,7 @@ class DeletePushSubscriptionService { func delete(topic: String) async throws { let params = PushDeleteParams.userDisconnected logger.debug("Will delete push subscription for reason: message: \(params.message) code: \(params.code), topic: \(topic)") - guard let _ = try? pushSubscriptionStore.get(key: topic) + guard let _ = pushSubscriptionStore.get(for: topic) else { throw Errors.pushSubscriptionNotFound} let protocolMethod = PushDeleteProtocolMethod() pushSubscriptionStore.delete(forKey: topic) diff --git a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift index bab7a8afa..071080eff 100644 --- a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift @@ -8,7 +8,7 @@ class DeletePushSubscriptionSubscriber { private let kms: KeyManagementServiceProtocol private let logger: ConsoleLogging private var publishers = [AnyCancellable]() - private let pushSubscriptionStore: CodableStore + private let pushSubscriptionStore: SyncStore private let deleteSubscriptionPublisherSubject = PassthroughSubject() @@ -19,7 +19,7 @@ class DeletePushSubscriptionSubscriber { init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, - pushSubscriptionStore: CodableStore + pushSubscriptionStore: SyncStore ) { self.networkingInteractor = networkingInteractor self.kms = kms diff --git a/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift b/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift index 227d8d2cb..cee996e2d 100644 --- a/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift +++ b/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift @@ -7,9 +7,9 @@ final class PushResubscribeService { private var publishers = Set() private let networkInteractor: NetworkInteracting - private let subscriptionsStorage: CodableStore + private let subscriptionsStorage: SyncStore - init(networkInteractor: NetworkInteracting, subscriptionsStorage: CodableStore) { + init(networkInteractor: NetworkInteracting, subscriptionsStorage: SyncStore) { self.networkInteractor = networkInteractor self.subscriptionsStorage = subscriptionsStorage setUpResubscription() diff --git a/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift b/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift index 7db605eaf..b10390cdc 100644 --- a/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift +++ b/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift @@ -1,9 +1,9 @@ import Foundation class SubscriptionsProvider { - let store: CodableStore + let store: SyncStore - init(store: CodableStore) { + init(store: SyncStore) { self.store = store } diff --git a/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift b/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift index 8764901a3..5cf6c025f 100644 --- a/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift @@ -18,7 +18,7 @@ public struct DappPushClientFactory { static func create(metadata: AppMetadata, logger: ConsoleLogging, keyValueStorage: KeyValueStorage, keychainStorage: KeychainStorageProtocol, networkInteractor: NetworkInteracting) -> DappPushClient { let kms = KeyManagementService(keychain: keychainStorage) - let subscriptionStore = CodableStore(defaults: keyValueStorage, identifier: PushStorageIdntifiers.pushSubscription) + let subscriptionStore = SyncStore(defaults: keyValueStorage, identifier: PushStorageIdntifiers.pushSubscription) let subscriptionProvider = SubscriptionsProvider(store: subscriptionStore) let deletePushSubscriptionSubscriber = DeletePushSubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushSubscriptionStore: subscriptionStore) let resubscribeService = PushResubscribeService(networkInteractor: networkInteractor, subscriptionsStorage: subscriptionStore) diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift index 814a08d2e..f893bc8f9 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift @@ -1,4 +1,3 @@ - import Foundation class NotifyUpdateRequester { @@ -10,13 +9,13 @@ class NotifyUpdateRequester { private let identityClient: IdentityClient private let networkingInteractor: NetworkInteracting private let logger: ConsoleLogging - private let subscriptionsStore: CodableStore + private let subscriptionsStore: SyncStore init(keyserverURL: URL, identityClient: IdentityClient, networkingInteractor: NetworkInteracting, logger: ConsoleLogging, - subscriptionsStore: CodableStore + subscriptionsStore: SyncStore ) { self.keyserverURL = keyserverURL self.identityClient = identityClient @@ -28,7 +27,7 @@ class NotifyUpdateRequester { func update(topic: String, scope: Set) async throws { logger.debug("NotifyUpdateRequester: updating subscription for topic: \(topic)") - guard let subscription = try subscriptionsStore.get(key: topic) else { throw Errors.noSubscriptionForGivenTopic } + guard let subscription = subscriptionsStore.get(for: topic) else { throw Errors.noSubscriptionForGivenTopic } let request = try createJWTRequest(subscriptionAccount: subscription.account, dappUrl: subscription.metadata.url, scope: scope) diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift index ef7e24ea0..a80653402 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift @@ -10,7 +10,7 @@ class NotifyUpdateResponseSubscriber { private let networkingInteractor: NetworkInteracting private var publishers = [AnyCancellable]() private let logger: ConsoleLogging - private let subscriptionsStore: CodableStore + private let subscriptionsStore: SyncStore private let subscriptionScopeProvider: SubscriptionScopeProvider private var subscriptionPublisherSubject = PassthroughSubject, Never>() var updateSubscriptionPublisher: AnyPublisher, Never> { @@ -20,7 +20,7 @@ class NotifyUpdateResponseSubscriber { init(networkingInteractor: NetworkInteracting, logger: ConsoleLogging, subscriptionScopeProvider: SubscriptionScopeProvider, - subscriptionsStore: CodableStore + subscriptionsStore: SyncStore ) { self.networkingInteractor = networkingInteractor self.logger = logger diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift index b5aa6af71..3bfd9a069 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift @@ -11,7 +11,7 @@ class PushSubscribeResponseSubscriber { private let kms: KeyManagementServiceProtocol private var publishers = [AnyCancellable]() private let logger: ConsoleLogging - private let subscriptionsStore: CodableStore + private let subscriptionsStore: SyncStore private let groupKeychainStorage: KeychainStorageProtocol private let dappsMetadataStore: CodableStore private let subscriptionScopeProvider: SubscriptionScopeProvider @@ -24,7 +24,7 @@ class PushSubscribeResponseSubscriber { kms: KeyManagementServiceProtocol, logger: ConsoleLogging, groupKeychainStorage: KeychainStorageProtocol, - subscriptionsStore: CodableStore, + subscriptionsStore: SyncStore, dappsMetadataStore: CodableStore, subscriptionScopeProvider: SubscriptionScopeProvider ) { diff --git a/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift b/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift index a4e330ec3..f32c57e2f 100644 --- a/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift +++ b/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift @@ -9,9 +9,9 @@ class PushSubscriptionsObserver { } private let subscriptionsPublisherSubject = PassthroughSubject<[PushSubscription], Never>() - private let store: CodableStore + private let store: SyncStore - init(store: CodableStore) { + init(store: SyncStore) { self.store = store setUpSubscription() } diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift index 667e28311..fa9039aef 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift @@ -38,7 +38,7 @@ public struct WalletPushClientFactory { let history = RPCHistoryFactory.createForNetwork(keyValueStorage: keyValueStorage) - let subscriptionStore = CodableStore(defaults: keyValueStorage, identifier: PushStorageIdntifiers.pushSubscription) + let subscriptionStore = SyncStore(defaults: keyValueStorage, identifier: PushStorageIdntifiers.pushSubscription) let identityClient = IdentityClientFactory.create(keyserver: keyserverURL, keychain: keychainStorage, logger: logger) diff --git a/Sources/WalletConnectPush/PushImports.swift b/Sources/WalletConnectPush/PushImports.swift index 98325f10c..44b2c7e9c 100644 --- a/Sources/WalletConnectPush/PushImports.swift +++ b/Sources/WalletConnectPush/PushImports.swift @@ -1,5 +1,6 @@ #if !CocoaPods @_exported import WalletConnectPairing -@_exported import WalletConnectSigner +@_exported import WalletConnectEcho @_exported import WalletConnectIdentity +@_exported import WalletConnectSync #endif diff --git a/Sources/WalletConnectPush/Types/PushSubscription.swift b/Sources/WalletConnectPush/Types/PushSubscription.swift index bfd1fd1eb..bf69e8732 100644 --- a/Sources/WalletConnectPush/Types/PushSubscription.swift +++ b/Sources/WalletConnectPush/Types/PushSubscription.swift @@ -2,13 +2,17 @@ import Foundation import WalletConnectUtils import WalletConnectPairing -public struct PushSubscription: Codable, Equatable { +public struct PushSubscription: DatabaseObject { public let topic: String public let account: Account public let relay: RelayProtocolOptions public let metadata: AppMetadata public let scope: [String: ScopeValue] public let expiry: Date + + public var databaseId: String { + return topic + } } public struct ScopeValue: Codable, Equatable { diff --git a/Sources/WalletConnectSync/Stores/SyncStore.swift b/Sources/WalletConnectSync/Stores/SyncStore.swift index 57b5320b4..70d2d50b8 100644 --- a/Sources/WalletConnectSync/Stores/SyncStore.swift +++ b/Sources/WalletConnectSync/Stores/SyncStore.swift @@ -60,6 +60,10 @@ public final class SyncStore { return objectStore.getAll() } + public func get(for id: String) -> Object? { + return getAll().first(where: { $0.databaseId == id }) + } + public func set(object: Object, for account: Account) async throws { let record = try indexStore.getRecord(account: account, name: name) @@ -75,6 +79,13 @@ public final class SyncStore { try await syncClient.delete(account: account, store: record.store, key: id) } } + + public func delete(id: String) { + guard let object = get(for: id) else { return } + + // TODO: How to get store topic by object id ??? + // TODO: Let's try to add account + } } private extension SyncStore { From f7fe1c356c4747630f137cf3e7ec28240d6db4d7 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 16 Jun 2023 08:17:06 +0300 Subject: [PATCH 06/19] Sync store integrated --- .../Common/DeletePushSubscriptionService.swift | 2 +- .../Common/DeletePushSubscriptionSubscriber.swift | 4 +++- .../Client/Dapp/DappPushClientFactory.swift | 9 +++++---- .../NotifyUpdateResponseSubscriber.swift | 4 ++-- .../PushSubscribeResponseSubscriber.swift | 2 +- .../Client/Wallet/PushSubscriptionsObserver.swift | 3 +-- .../Client/Wallet/WalletPushClientFactory.swift | 11 +++++++---- Sources/WalletConnectPush/Push.swift | 9 ++++----- .../WalletConnectPush/PushStorageIdntifiers.swift | 3 ++- Sources/WalletConnectSync/Stores/SyncStore.swift | 12 +++++++----- Sources/WalletConnectUtils/KeyedDatabase.swift | 9 +++++++++ 11 files changed, 42 insertions(+), 26 deletions(-) diff --git a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift index 0693de806..b6d121528 100644 --- a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift +++ b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift @@ -29,7 +29,7 @@ class DeletePushSubscriptionService { guard let _ = pushSubscriptionStore.get(for: topic) else { throw Errors.pushSubscriptionNotFound} let protocolMethod = PushDeleteProtocolMethod() - pushSubscriptionStore.delete(forKey: topic) + try await pushSubscriptionStore.delete(id: topic) pushMessagesDatabase?.deletePushMessages(topic: topic) let request = RPCRequest(method: protocolMethod.method, params: params) try await networkingInteractor.request(request, topic: topic, protocolMethod: protocolMethod) diff --git a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift index 071080eff..9c583e0af 100644 --- a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift @@ -35,7 +35,9 @@ class DeletePushSubscriptionSubscriber { logger.debug("Peer deleted subscription") let topic = payload.topic networkingInteractor.unsubscribe(topic: topic) - pushSubscriptionStore.delete(forKey: topic) + Task(priority: .high) { + try await pushSubscriptionStore.delete(id: topic) + } kms.deleteSymmetricKey(for: topic) deleteSubscriptionPublisherSubject.send(payload.topic) }.store(in: &publishers) diff --git a/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift b/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift index 5cf6c025f..87dae8647 100644 --- a/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift @@ -3,7 +3,7 @@ import WalletConnectPairing public struct DappPushClientFactory { - public static func create(metadata: AppMetadata, networkInteractor: NetworkInteracting) -> DappPushClient { + public static func create(metadata: AppMetadata, networkInteractor: NetworkInteracting, syncClient: SyncClient) -> DappPushClient { let logger = ConsoleLogger(loggingLevel: .off) let keyValueStorage = UserDefaults.standard let keychainStorage = KeychainStorage(serviceIdentifier: "com.walletconnect.sdk") @@ -12,13 +12,14 @@ public struct DappPushClientFactory { logger: logger, keyValueStorage: keyValueStorage, keychainStorage: keychainStorage, - networkInteractor: networkInteractor + networkInteractor: networkInteractor, + syncClient: syncClient ) } - static func create(metadata: AppMetadata, logger: ConsoleLogging, keyValueStorage: KeyValueStorage, keychainStorage: KeychainStorageProtocol, networkInteractor: NetworkInteracting) -> DappPushClient { + static func create(metadata: AppMetadata, logger: ConsoleLogging, keyValueStorage: KeyValueStorage, keychainStorage: KeychainStorageProtocol, networkInteractor: NetworkInteracting, syncClient: SyncClient) -> DappPushClient { let kms = KeyManagementService(keychain: keychainStorage) - let subscriptionStore = SyncStore(defaults: keyValueStorage, identifier: PushStorageIdntifiers.pushSubscription) + let subscriptionStore: SyncStore = SyncStoreFactory.create(name: PushStorageIdntifiers.pushSubscription, syncClient: syncClient, storage: keyValueStorage) let subscriptionProvider = SubscriptionsProvider(store: subscriptionStore) let deletePushSubscriptionSubscriber = DeletePushSubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushSubscriptionStore: subscriptionStore) let resubscribeService = PushResubscribeService(networkInteractor: networkInteractor, subscriptionsStorage: subscriptionStore) diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift index a80653402..a43a3ce08 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift @@ -41,7 +41,7 @@ class NotifyUpdateResponseSubscriber { let (_, claims) = try SubscriptionJWTPayload.decodeAndVerify(from: payload.request) let scope = try await buildScope(selected: claims.scp, dappUrl: claims.aud) - guard let oldSubscription = try? subscriptionsStore.get(key: subscriptionTopic) else { + guard let oldSubscription = try? subscriptionsStore.get(for: subscriptionTopic) else { logger.debug("NotifyUpdateResponseSubscriber Subscription does not exist") subscriptionPublisherSubject.send(.failure(Errors.subscriptionDoesNotExist)) return @@ -50,7 +50,7 @@ class NotifyUpdateResponseSubscriber { let updatedSubscription = PushSubscription(topic: subscriptionTopic, account: oldSubscription.account, relay: oldSubscription.relay, metadata: oldSubscription.metadata, scope: scope, expiry: expiry) - subscriptionsStore.set(updatedSubscription, forKey: subscriptionTopic) + try await subscriptionsStore.set(object: updatedSubscription, for: updatedSubscription.account) subscriptionPublisherSubject.send(.success(updatedSubscription)) diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift index 3bfd9a069..6b2069551 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift @@ -90,7 +90,7 @@ class PushSubscribeResponseSubscriber { let scope: [String: ScopeValue] = subscribedTypes.reduce(into: [:]) { $0[$1.name] = ScopeValue(description: $1.description, enabled: true) } let pushSubscription = PushSubscription(topic: pushSubscriptionTopic, account: account, relay: RelayProtocolOptions(protocol: "irn", data: nil), metadata: metadata, scope: scope, expiry: expiry) - subscriptionsStore.set(pushSubscription, forKey: pushSubscriptionTopic) + try await subscriptionsStore.set(object: pushSubscription, for: pushSubscription.account) logger.debug("PushSubscribeResponseSubscriber: unsubscribing response topic: \(payload.topic)") networkingInteractor.unsubscribe(topic: payload.topic) diff --git a/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift b/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift index f32c57e2f..71922c8c1 100644 --- a/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift +++ b/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift @@ -17,8 +17,7 @@ class PushSubscriptionsObserver { } func setUpSubscription() { - store.storeUpdatePublisher.sink(receiveValue: { [unowned self] in - let subscriptions = store.getAll() + store.dataUpdatePublisher.sink(receiveValue: { [unowned self] subscriptions in subscriptionsPublisherSubject.send(subscriptions) }).store(in: &publishers) } diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift index fa9039aef..244d97d3f 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift @@ -5,7 +5,7 @@ import WalletConnectIdentity public struct WalletPushClientFactory { - public static func create(networkInteractor: NetworkInteracting, pairingRegisterer: PairingRegisterer, echoClient: EchoClient) -> WalletPushClient { + public static func create(networkInteractor: NetworkInteracting, pairingRegisterer: PairingRegisterer, echoClient: EchoClient, syncClient: SyncClient) -> WalletPushClient { let logger = ConsoleLogger(suffix: "🔔",loggingLevel: .debug) let keyValueStorage = UserDefaults.standard let keyserverURL = URL(string: "https://keys.walletconnect.com")! @@ -20,7 +20,8 @@ public struct WalletPushClientFactory { groupKeychainStorage: groupKeychainService, networkInteractor: networkInteractor, pairingRegisterer: pairingRegisterer, - echoClient: echoClient + echoClient: echoClient, + syncClient: syncClient ) } @@ -32,13 +33,15 @@ public struct WalletPushClientFactory { groupKeychainStorage: KeychainStorageProtocol, networkInteractor: NetworkInteracting, pairingRegisterer: PairingRegisterer, - echoClient: EchoClient + echoClient: EchoClient, + syncClient: SyncClient ) -> WalletPushClient { let kms = KeyManagementService(keychain: keychainStorage) let history = RPCHistoryFactory.createForNetwork(keyValueStorage: keyValueStorage) - let subscriptionStore = SyncStore(defaults: keyValueStorage, identifier: PushStorageIdntifiers.pushSubscription) + let subscriptionStore: SyncStore = SyncStoreFactory.create(name: PushStorageIdntifiers.pushSubscription, syncClient: syncClient, storage: keyValueStorage) + let identityClient = IdentityClientFactory.create(keyserver: keyserverURL, keychain: keychainStorage, logger: logger) diff --git a/Sources/WalletConnectPush/Push.swift b/Sources/WalletConnectPush/Push.swift index 6f217deb0..2c16e81e5 100644 --- a/Sources/WalletConnectPush/Push.swift +++ b/Sources/WalletConnectPush/Push.swift @@ -1,14 +1,12 @@ import Foundation -import WalletConnectNetworking -import WalletConnectPairing -import WalletConnectEcho public class Push { public static var dapp: DappPushClient = { return DappPushClientFactory.create( metadata: Pair.metadata, - networkInteractor: Networking.interactor + networkInteractor: Networking.interactor, + syncClient: Sync.instance ) }() @@ -20,7 +18,8 @@ public class Push { return WalletPushClientFactory.create( networkInteractor: Networking.interactor, pairingRegisterer: Pair.registerer, - echoClient: Echo.instance + echoClient: Echo.instance, + syncClient: Sync.instance ) }() diff --git a/Sources/WalletConnectPush/PushStorageIdntifiers.swift b/Sources/WalletConnectPush/PushStorageIdntifiers.swift index 57ac3611c..635242b7c 100644 --- a/Sources/WalletConnectPush/PushStorageIdntifiers.swift +++ b/Sources/WalletConnectPush/PushStorageIdntifiers.swift @@ -1,7 +1,8 @@ import Foundation enum PushStorageIdntifiers { - static let pushSubscription = "com.walletconnect.sdk.pushSbscription" + static let pushSubscription = "com.walletconnect.push.subscription" + static let pushMessagesRecords = "com.walletconnect.sdk.pushMessagesRecords" static let dappsMetadataStore = "com.walletconnect.sdk.dappsMetadataStore" } diff --git a/Sources/WalletConnectSync/Stores/SyncStore.swift b/Sources/WalletConnectSync/Stores/SyncStore.swift index 70d2d50b8..227a39140 100644 --- a/Sources/WalletConnectSync/Stores/SyncStore.swift +++ b/Sources/WalletConnectSync/Stores/SyncStore.swift @@ -80,11 +80,13 @@ public final class SyncStore { } } - public func delete(id: String) { - guard let object = get(for: id) else { return } - - // TODO: How to get store topic by object id ??? - // TODO: Let's try to add account + public func delete(id: String) async throws { + guard let result = objectStore.find(id: id) else { + return + } + // TODO: Should we pass topic to sync client? + let record = try indexStore.getRecord(topic: result.key) + try await delete(id: id, for: record.account) } } diff --git a/Sources/WalletConnectUtils/KeyedDatabase.swift b/Sources/WalletConnectUtils/KeyedDatabase.swift index 0deffcc8d..dfd8f30c4 100644 --- a/Sources/WalletConnectUtils/KeyedDatabase.swift +++ b/Sources/WalletConnectUtils/KeyedDatabase.swift @@ -42,6 +42,15 @@ public class KeyedDatabase where Element: DatabaseObject { return index[key]?[id] } + public func find(id: String) -> (key: String, element: Element)? { + guard + let value = index.first(where: { $0.key == id }), + let element = value.value[id] + else { return nil } + + return (value.key, element) + } + @discardableResult public func set(elements: [Element], for key: String) -> Bool { var map = index[key] ?? [:] From 5d05f4ad8a9f182b18405636c3b7bc9803b5c35e Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 16 Jun 2023 08:21:03 +0300 Subject: [PATCH 07/19] Redundant import --- Sources/WalletConnectPush/APNSEnvironment.swift | 3 --- .../Client/Common/DeletePushSubscriptionService.swift | 2 -- .../Client/Common/DeletePushSubscriptionSubscriber.swift | 2 -- .../Client/Common/PushDecryptionService.swift | 2 -- .../Client/Common/PushResubscribeService.swift | 1 - Sources/WalletConnectPush/Client/Dapp/DappPushClient.swift | 1 - .../WalletConnectPush/Client/Dapp/DappPushClientFactory.swift | 1 - .../ProtocolEngine/wc_pushMessage/PushMessageSubscriber.swift | 2 -- .../WalletConnectPush/Client/Wallet/PushMessagesDatabase.swift | 2 -- Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift | 2 -- .../Client/Wallet/WalletPushClientFactory.swift | 3 --- .../ProtocolMethods/PushDeleteProtocolMethod.swift | 1 - .../ProtocolMethods/PushMessageProtocolMethod.swift | 1 - Sources/WalletConnectPush/PushConfig.swift | 1 - Sources/WalletConnectPush/Types/PushRequest.swift | 2 -- Sources/WalletConnectPush/Types/PushSubscription.swift | 2 -- Sources/WalletConnectPush/Types/WebDidDoc.swift | 1 - 17 files changed, 29 deletions(-) delete mode 100644 Sources/WalletConnectPush/APNSEnvironment.swift diff --git a/Sources/WalletConnectPush/APNSEnvironment.swift b/Sources/WalletConnectPush/APNSEnvironment.swift deleted file mode 100644 index 567373443..000000000 --- a/Sources/WalletConnectPush/APNSEnvironment.swift +++ /dev/null @@ -1,3 +0,0 @@ -import WalletConnectEcho - -public typealias APNSEnvironment = WalletConnectEcho.APNSEnvironment diff --git a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift index b6d121528..c57306d40 100644 --- a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift +++ b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift @@ -1,6 +1,4 @@ import Foundation -import WalletConnectKMS -import WalletConnectUtils class DeletePushSubscriptionService { enum Errors: Error { diff --git a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift index 9c583e0af..d16698a79 100644 --- a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift @@ -1,7 +1,5 @@ import Foundation import Combine -import WalletConnectKMS -import WalletConnectPairing class DeletePushSubscriptionSubscriber { private let networkingInteractor: NetworkInteracting diff --git a/Sources/WalletConnectPush/Client/Common/PushDecryptionService.swift b/Sources/WalletConnectPush/Client/Common/PushDecryptionService.swift index e2179fc95..995ff4e4a 100644 --- a/Sources/WalletConnectPush/Client/Common/PushDecryptionService.swift +++ b/Sources/WalletConnectPush/Client/Common/PushDecryptionService.swift @@ -1,7 +1,5 @@ import Foundation -import WalletConnectKMS - public class PushDecryptionService { enum Errors: Error { case malformedPushMessage diff --git a/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift b/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift index cee996e2d..cb534dacc 100644 --- a/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift +++ b/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift @@ -1,5 +1,4 @@ import Foundation -import WalletConnectNetworking import Combine final class PushResubscribeService { diff --git a/Sources/WalletConnectPush/Client/Dapp/DappPushClient.swift b/Sources/WalletConnectPush/Client/Dapp/DappPushClient.swift index 116885340..a9182d80d 100644 --- a/Sources/WalletConnectPush/Client/Dapp/DappPushClient.swift +++ b/Sources/WalletConnectPush/Client/Dapp/DappPushClient.swift @@ -1,6 +1,5 @@ import Foundation import Combine -import WalletConnectUtils public class DappPushClient { public var proposalResponsePublisher: AnyPublisher, Never> { diff --git a/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift b/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift index 87dae8647..0849d02e9 100644 --- a/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift @@ -1,5 +1,4 @@ import Foundation -import WalletConnectPairing public struct DappPushClientFactory { diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushMessage/PushMessageSubscriber.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushMessage/PushMessageSubscriber.swift index ba95b837c..27dfa0ee9 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushMessage/PushMessageSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushMessage/PushMessageSubscriber.swift @@ -1,7 +1,5 @@ import Foundation import Combine -import WalletConnectKMS -import WalletConnectPairing class PushMessageSubscriber { private let networkingInteractor: NetworkInteracting diff --git a/Sources/WalletConnectPush/Client/Wallet/PushMessagesDatabase.swift b/Sources/WalletConnectPush/Client/Wallet/PushMessagesDatabase.swift index ecb31d791..8da65ce31 100644 --- a/Sources/WalletConnectPush/Client/Wallet/PushMessagesDatabase.swift +++ b/Sources/WalletConnectPush/Client/Wallet/PushMessagesDatabase.swift @@ -1,6 +1,4 @@ - import Foundation -import WalletConnectUtils import Combine class PushMessagesDatabase { diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift index 40855c14f..74faca47a 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift @@ -1,7 +1,5 @@ import Foundation import Combine -import WalletConnectNetworking -import WalletConnectEcho public class WalletPushClient { diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift index 244d97d3f..7c4be771e 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift @@ -1,7 +1,4 @@ import Foundation -import WalletConnectUtils -import WalletConnectEcho -import WalletConnectIdentity public struct WalletPushClientFactory { diff --git a/Sources/WalletConnectPush/ProtocolMethods/PushDeleteProtocolMethod.swift b/Sources/WalletConnectPush/ProtocolMethods/PushDeleteProtocolMethod.swift index 1aee08d1f..dd90fe7e2 100644 --- a/Sources/WalletConnectPush/ProtocolMethods/PushDeleteProtocolMethod.swift +++ b/Sources/WalletConnectPush/ProtocolMethods/PushDeleteProtocolMethod.swift @@ -1,5 +1,4 @@ import Foundation -import WalletConnectPairing struct PushDeleteProtocolMethod: ProtocolMethod { let method: String = "wc_pushDelete" diff --git a/Sources/WalletConnectPush/ProtocolMethods/PushMessageProtocolMethod.swift b/Sources/WalletConnectPush/ProtocolMethods/PushMessageProtocolMethod.swift index 808817290..6345d1dc8 100644 --- a/Sources/WalletConnectPush/ProtocolMethods/PushMessageProtocolMethod.swift +++ b/Sources/WalletConnectPush/ProtocolMethods/PushMessageProtocolMethod.swift @@ -1,5 +1,4 @@ import Foundation -import WalletConnectPairing struct PushMessageProtocolMethod: ProtocolMethod { let method: String = "wc_pushMessage" diff --git a/Sources/WalletConnectPush/PushConfig.swift b/Sources/WalletConnectPush/PushConfig.swift index 2e290caa5..9c955803a 100644 --- a/Sources/WalletConnectPush/PushConfig.swift +++ b/Sources/WalletConnectPush/PushConfig.swift @@ -1,5 +1,4 @@ import Foundation -import WalletConnectEcho extension Push { struct Config { diff --git a/Sources/WalletConnectPush/Types/PushRequest.swift b/Sources/WalletConnectPush/Types/PushRequest.swift index a27b87a9b..d1c4c8a92 100644 --- a/Sources/WalletConnectPush/Types/PushRequest.swift +++ b/Sources/WalletConnectPush/Types/PushRequest.swift @@ -1,5 +1,3 @@ - import Foundation -import WalletConnectPairing public typealias PushRequest = (id: RPCID, account: Account, metadata: AppMetadata) diff --git a/Sources/WalletConnectPush/Types/PushSubscription.swift b/Sources/WalletConnectPush/Types/PushSubscription.swift index bf69e8732..46e021b00 100644 --- a/Sources/WalletConnectPush/Types/PushSubscription.swift +++ b/Sources/WalletConnectPush/Types/PushSubscription.swift @@ -1,6 +1,4 @@ import Foundation -import WalletConnectUtils -import WalletConnectPairing public struct PushSubscription: DatabaseObject { public let topic: String diff --git a/Sources/WalletConnectPush/Types/WebDidDoc.swift b/Sources/WalletConnectPush/Types/WebDidDoc.swift index 28f301773..aca4975f0 100644 --- a/Sources/WalletConnectPush/Types/WebDidDoc.swift +++ b/Sources/WalletConnectPush/Types/WebDidDoc.swift @@ -1,4 +1,3 @@ - import Foundation // MARK: - WebDidDoc From 7ea7e6d2f6e39fe83504686b56ef72c49f0acf44 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 16 Jun 2023 15:19:28 +0300 Subject: [PATCH 08/19] Sync create store --- .../WalletConnectPush/Client/Wallet/WalletPushClient.swift | 6 ++++-- .../Client/Wallet/WalletPushClientFactory.swift | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift index 74faca47a..67390bb01 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift @@ -50,6 +50,7 @@ public class WalletPushClient { private let notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber private let notifyProposeResponder: NotifyProposeResponder private let notifyProposeSubscriber: NotifyProposeSubscriber + private let subscriptionsStore: SyncStore init(logger: ConsoleLogging, kms: KeyManagementServiceProtocol, @@ -66,7 +67,7 @@ public class WalletPushClient { notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber, notifyProposeResponder: NotifyProposeResponder, notifyProposeSubscriber: NotifyProposeSubscriber, - deletePushSubscriptionSubscriber: DeletePushSubscriptionSubscriber + subscriptionsStore: SyncStore ) { self.logger = logger self.echoClient = echoClient @@ -82,10 +83,11 @@ public class WalletPushClient { self.notifyUpdateResponseSubscriber = notifyUpdateResponseSubscriber self.notifyProposeResponder = notifyProposeResponder self.notifyProposeSubscriber = notifyProposeSubscriber - self.deletePushSubscriptionSubscriber = deletePushSubscriptionSubscriber + self.subscriptionsStore = subscriptionsStore } public func subscribe(metadata: AppMetadata, account: Account, onSign: @escaping SigningCallback) async throws { + try await subscriptionsStore.initialize(for: account) try await pushSubscribeRequester.subscribe(metadata: metadata, account: account, onSign: onSign) } diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift index 7c4be771e..1097296eb 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift @@ -83,7 +83,7 @@ public struct WalletPushClientFactory { notifyUpdateResponseSubscriber: notifyUpdateResponseSubscriber, notifyProposeResponder: notifyProposeResponder, notifyProposeSubscriber: notifyProposeSubscriber, - deletePushSubscriptionSubscriber: deletePushSubscriptionSubscriber + subscriptionsStore: subscriptionStore ) } } From 3d82139a9700212ec56ce80e0465d1e6e6b2ba98 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 19 Jun 2023 19:15:59 +0300 Subject: [PATCH 09/19] Sync register --- Example/IntegrationTests/Push/PushTests.swift | 1 - .../ApplicationLayer/EthKeyStore.swift | 17 +++++++------ .../Client/Common/SubscriptionsProvider.swift | 4 +++ .../NotifyProposeSubscriber.swift | 4 +-- .../PushSubscribeRequester.swift | 1 + .../PushSubscribeResponseSubscriber.swift | 2 +- .../Client/Wallet/WalletPushClient.swift | 25 +++++++++++++++---- .../Wallet/WalletPushClientFactory.swift | 6 ++--- .../WalletConnectPush/Types/PushError.swift | 9 +++++++ .../PushClientProxy/PushClientProxy.swift | 6 +++++ 10 files changed, 55 insertions(+), 20 deletions(-) diff --git a/Example/IntegrationTests/Push/PushTests.swift b/Example/IntegrationTests/Push/PushTests.swift index 328ea02b3..0620653b1 100644 --- a/Example/IntegrationTests/Push/PushTests.swift +++ b/Example/IntegrationTests/Push/PushTests.swift @@ -152,7 +152,6 @@ final class PushTests: XCTestCase { wait(for: [expectation], timeout: InputConfig.defaultTimeout) } - func testDeletePushSubscription() async { let expectation = expectation(description: "expects to delete push subscription") let uri = try! await dappPairingClient.create() diff --git a/Example/WalletApp/ApplicationLayer/EthKeyStore.swift b/Example/WalletApp/ApplicationLayer/EthKeyStore.swift index 782a1d3a0..5f6f085e0 100644 --- a/Example/WalletApp/ApplicationLayer/EthKeyStore.swift +++ b/Example/WalletApp/ApplicationLayer/EthKeyStore.swift @@ -7,7 +7,7 @@ class EthKeyStore { let privateKey: EthereumPrivateKey var address: String { - return privateKey.address.hex(eip55: false) + return privateKey.address.hex(eip55: true) } var privateKeyRaw: Data { @@ -15,11 +15,14 @@ class EthKeyStore { } private init() { - if let privateKeyRaw = UserDefaults.standard.data(forKey: defaultsKey) { - self.privateKey = try! EthereumPrivateKey(privateKeyRaw) - } else { - self.privateKey = try! EthereumPrivateKey() - UserDefaults.standard.set(privateKeyRaw, forKey: defaultsKey) - } + // TODO: For testing !!! + self.privateKey = try! EthereumPrivateKey(hexPrivateKey: "0x660bc2a94efbef506a499aef10066a914e2aaa1791362fd6d15a5b23a1078b44") + + // if let privateKeyRaw = UserDefaults.standard.data(forKey: defaultsKey) { + // self.privateKey = try! EthereumPrivateKey(privateKeyRaw) + // } else { + // self.privateKey = try! EthereumPrivateKey() + // UserDefaults.standard.set(privateKeyRaw, forKey: defaultsKey) + // } } } diff --git a/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift b/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift index b10390cdc..e82e2d9e8 100644 --- a/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift +++ b/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift @@ -10,4 +10,8 @@ class SubscriptionsProvider { public func getActiveSubscriptions() -> [PushSubscription] { store.getAll() } + + public func initialize(account: Account) async throws { + try await store.initialize(for: account) + } } diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeSubscriber.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeSubscriber.swift index a9b99b4ac..4bb71b881 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeSubscriber.swift @@ -6,7 +6,7 @@ class NotifyProposeSubscriber { private let requestPublisherSubject = PassthroughSubject() private let networkingInteractor: NetworkInteracting - private let subscriptionsStore: CodableStore + private let subscriptionsStore: SyncStore private var publishers = Set() public var requestPublisher: AnyPublisher { requestPublisherSubject.eraseToAnyPublisher() @@ -15,7 +15,7 @@ class NotifyProposeSubscriber { private let pairingRegisterer: PairingRegisterer init(networkingInteractor: NetworkInteracting, - subscriptionsStore: CodableStore, + subscriptionsStore: SyncStore, publishers: Set = Set(), logger: ConsoleLogging, pairingRegisterer: PairingRegisterer) { diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeRequester.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeRequester.swift index 2a4f12782..cfd061084 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeRequester.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeRequester.swift @@ -7,6 +7,7 @@ class PushSubscribeRequester { case didDocDoesNotContainKeyAgreement case noVerificationMethodForKey case unsupportedCurve + case signatureRejected } private let keyserverURL: URL diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift index 6b2069551..9d920dd8d 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift @@ -90,7 +90,7 @@ class PushSubscribeResponseSubscriber { let scope: [String: ScopeValue] = subscribedTypes.reduce(into: [:]) { $0[$1.name] = ScopeValue(description: $1.description, enabled: true) } let pushSubscription = PushSubscription(topic: pushSubscriptionTopic, account: account, relay: RelayProtocolOptions(protocol: "irn", data: nil), metadata: metadata, scope: scope, expiry: expiry) - try await subscriptionsStore.set(object: pushSubscription, for: pushSubscription.account) + try! await subscriptionsStore.set(object: pushSubscription, for: pushSubscription.account) logger.debug("PushSubscribeResponseSubscriber: unsubscribing response topic: \(payload.topic)") networkingInteractor.unsubscribe(topic: payload.topic) diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift index 67390bb01..074ab7988 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift @@ -41,6 +41,7 @@ public class WalletPushClient { public let logger: ConsoleLogging private let echoClient: EchoClient + private let syncClient: SyncClient private let pushMessageSubscriber: PushMessageSubscriber private let subscriptionsProvider: SubscriptionsProvider private let pushMessagesDatabase: PushMessagesDatabase @@ -50,11 +51,11 @@ public class WalletPushClient { private let notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber private let notifyProposeResponder: NotifyProposeResponder private let notifyProposeSubscriber: NotifyProposeSubscriber - private let subscriptionsStore: SyncStore init(logger: ConsoleLogging, kms: KeyManagementServiceProtocol, echoClient: EchoClient, + syncClient: SyncClient, pushMessageSubscriber: PushMessageSubscriber, subscriptionsProvider: SubscriptionsProvider, pushMessagesDatabase: PushMessagesDatabase, @@ -66,11 +67,11 @@ public class WalletPushClient { notifyUpdateRequester: NotifyUpdateRequester, notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber, notifyProposeResponder: NotifyProposeResponder, - notifyProposeSubscriber: NotifyProposeSubscriber, - subscriptionsStore: SyncStore + notifyProposeSubscriber: NotifyProposeSubscriber ) { self.logger = logger self.echoClient = echoClient + self.syncClient = syncClient self.pushMessageSubscriber = pushMessageSubscriber self.subscriptionsProvider = subscriptionsProvider self.pushMessagesDatabase = pushMessagesDatabase @@ -83,11 +84,25 @@ public class WalletPushClient { self.notifyUpdateResponseSubscriber = notifyUpdateResponseSubscriber self.notifyProposeResponder = notifyProposeResponder self.notifyProposeSubscriber = notifyProposeSubscriber - self.subscriptionsStore = subscriptionsStore + } + + public func register(account: Account, onSign: @escaping SigningCallback) async throws { + try await subscriptionsProvider.initialize(account: account) + + guard !syncClient.isRegistered(account: account) else { return } + + let result = await onSign(syncClient.getMessage(account: account)) + + switch result { + case .signed(let signature): + try await syncClient.register(account: account, signature: signature) + logger.debug("Sync pushSubscriptions store registered and initialized") + case .rejected: + throw PushError.registerSignatureRejected + } } public func subscribe(metadata: AppMetadata, account: Account, onSign: @escaping SigningCallback) async throws { - try await subscriptionsStore.initialize(for: account) try await pushSubscribeRequester.subscribe(metadata: metadata, account: account, onSign: onSign) } diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift index 1097296eb..0919df7da 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift @@ -39,7 +39,6 @@ public struct WalletPushClientFactory { let subscriptionStore: SyncStore = SyncStoreFactory.create(name: PushStorageIdntifiers.pushSubscription, syncClient: syncClient, storage: keyValueStorage) - let identityClient = IdentityClientFactory.create(keyserver: keyserverURL, keychain: keychainStorage, logger: logger) let pushMessagesRecordsStore = CodableStore(defaults: keyValueStorage, identifier: PushStorageIdntifiers.pushMessagesRecords) @@ -50,7 +49,6 @@ public struct WalletPushClientFactory { let resubscribeService = PushResubscribeService(networkInteractor: networkInteractor, subscriptionsStorage: subscriptionStore) let pushSubscriptionsObserver = PushSubscriptionsObserver(store: subscriptionStore) - let dappsMetadataStore = CodableStore(defaults: keyValueStorage, identifier: PushStorageIdntifiers.dappsMetadataStore) let subscriptionScopeProvider = SubscriptionScopeProvider() @@ -71,6 +69,7 @@ public struct WalletPushClientFactory { logger: logger, kms: kms, echoClient: echoClient, + syncClient: syncClient, pushMessageSubscriber: pushMessageSubscriber, subscriptionsProvider: subscriptionProvider, pushMessagesDatabase: pushMessagesDatabase, @@ -82,8 +81,7 @@ public struct WalletPushClientFactory { notifyUpdateRequester: notifyUpdateRequester, notifyUpdateResponseSubscriber: notifyUpdateResponseSubscriber, notifyProposeResponder: notifyProposeResponder, - notifyProposeSubscriber: notifyProposeSubscriber, - subscriptionsStore: subscriptionStore + notifyProposeSubscriber: notifyProposeSubscriber ) } } diff --git a/Sources/WalletConnectPush/Types/PushError.swift b/Sources/WalletConnectPush/Types/PushError.swift index 5912bc917..82c16c00e 100644 --- a/Sources/WalletConnectPush/Types/PushError.swift +++ b/Sources/WalletConnectPush/Types/PushError.swift @@ -4,6 +4,7 @@ public enum PushError: Codable, Equatable, Error { case userRejeted case userHasExistingSubscription case methodUnsupported + case registerSignatureRejected } extension PushError: Reason { @@ -12,8 +13,12 @@ extension PushError: Reason { switch code { case Self.userRejeted.code: self = .userRejeted + case Self.userHasExistingSubscription.code: + self = .userHasExistingSubscription case Self.methodUnsupported.code: self = .methodUnsupported + case Self.registerSignatureRejected.code: + self = .registerSignatureRejected default: return nil } @@ -26,6 +31,8 @@ extension PushError: Reason { return 5000 case .userHasExistingSubscription: return 6001 + case .registerSignatureRejected: + return 1501 } } @@ -37,6 +44,8 @@ extension PushError: Reason { return "Push request rejected" case .userHasExistingSubscription: return "User Has Existing Subscription" + case .registerSignatureRejected: + return "Register signature rejected" } } diff --git a/Sources/Web3Inbox/PushClientProxy/PushClientProxy.swift b/Sources/Web3Inbox/PushClientProxy/PushClientProxy.swift index 2a84f4bd4..cb6fb8e8d 100644 --- a/Sources/Web3Inbox/PushClientProxy/PushClientProxy.swift +++ b/Sources/Web3Inbox/PushClientProxy/PushClientProxy.swift @@ -10,6 +10,12 @@ final class PushClientProxy { init(client: WalletPushClient, onSign: @escaping SigningCallback) { self.client = client self.onSign = onSign + + // TODO: For testing !!! + Task(priority: .high) { + let account = Account("eip155:1:0x32F9ABCf897010fDF038D1A15c6553511EcD8c1D")! + try await client.register(account: account, onSign: onSign) + } } func request(_ request: RPCRequest) async throws { From cedfd3653f40f19c916f4610fa0b48cf631b90fb Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 29 Jun 2023 08:34:21 +0200 Subject: [PATCH 10/19] remove duplicated storage --- Example/IntegrationTests/Sign/SignClientTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/IntegrationTests/Sign/SignClientTests.swift b/Example/IntegrationTests/Sign/SignClientTests.swift index 62aaf4065..941a42d7c 100644 --- a/Example/IntegrationTests/Sign/SignClientTests.swift +++ b/Example/IntegrationTests/Sign/SignClientTests.swift @@ -18,7 +18,7 @@ final class SignClientTests: XCTestCase { let relayClient = RelayClientFactory.create( relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, - keyValueStorage: RuntimeKeyValueStorage(), + keyValueStorage: keyValueStorage, keychainStorage: keychain, socketFactory: DefaultSocketFactory(), logger: logger From 8233760edfb104953f02c94a00b6b6ac69e022cc Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 29 Jun 2023 09:01:37 +0200 Subject: [PATCH 11/19] fix relay tests --- .../RelayClientEndToEndTests.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Example/RelayIntegrationTests/RelayClientEndToEndTests.swift b/Example/RelayIntegrationTests/RelayClientEndToEndTests.swift index fd273e35a..e33ab1cec 100644 --- a/Example/RelayIntegrationTests/RelayClientEndToEndTests.swift +++ b/Example/RelayIntegrationTests/RelayClientEndToEndTests.swift @@ -50,7 +50,17 @@ final class RelayClientEndToEndTests: XCTestCase { socketConnectionType: .manual, logger: logger ) - let relayClient = RelayClient(dispatcher: dispatcher, logger: logger, keyValueStorage: RuntimeKeyValueStorage(), clientIdStorage: clientIdStorage) + let keychain = KeychainStorageMock() + let keyValueStorage = RuntimeKeyValueStorage() + let relayClient = RelayClientFactory.create( + relayHost: InputConfig.relayHost, + projectId: InputConfig.projectId, + keyValueStorage: keyValueStorage, + keychainStorage: keychain, + socketFactory: DefaultSocketFactory(), + socketConnectionType: .manual, + logger: logger + ) let clientId = try! relayClient.getClientId() logger.debug("My client id is: \(clientId)") From b8ad336828fd8836ce179efed65caa07e91a2588 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 29 Jun 2023 11:03:26 +0300 Subject: [PATCH 12/19] podspec updated --- WalletConnectSwiftV2.podspec | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/WalletConnectSwiftV2.podspec b/WalletConnectSwiftV2.podspec index 6b3b759a6..c2f80eb8f 100644 --- a/WalletConnectSwiftV2.podspec +++ b/WalletConnectSwiftV2.podspec @@ -75,6 +75,14 @@ Pod::Spec.new do |spec| spec.default_subspecs = 'WalletConnect' spec.subspec 'WalletConnect' do |ss| + ss.source_files = 'Sources/Web3Wallet/**/*.{h,m,swift}' + ss.dependency 'WalletConnectSwiftV2/WalletConnectSign' + ss.dependency 'WalletConnectSwiftV2/WalletConnectAuth' + ss.dependency 'WalletConnectSwiftV2/WalletConnectEcho' + ss.dependency 'WalletConnectSwiftV2/WalletConnectVerify' + end + + spec.subspec 'WalletConnectSign' do |ss| ss.source_files = 'Sources/WalletConnectSign/**/*.{h,m,swift}' ss.dependency 'WalletConnectSwiftV2/WalletConnectPairing' ss.dependency 'WalletConnectSwiftV2/WalletConnectVerify' @@ -86,14 +94,6 @@ Pod::Spec.new do |spec| ss.dependency 'WalletConnectSwiftV2/WalletConnectSigner' ss.dependency 'WalletConnectSwiftV2/WalletConnectVerify' end - - spec.subspec 'Web3Wallet' do |ss| - ss.source_files = 'Sources/Web3Wallet/**/*.{h,m,swift}' - ss.dependency 'WalletConnectSwiftV2/WalletConnect' - ss.dependency 'WalletConnectSwiftV2/WalletConnectAuth' - ss.dependency 'WalletConnectSwiftV2/WalletConnectEcho' - ss.dependency 'WalletConnectSwiftV2/WalletConnectVerify' - end spec.subspec 'WalletConnectVerify' do |ss| ss.source_files = 'Sources/WalletConnectVerify/**/*.{h,m,swift}' From 75bc40d76780d15a08036dd164e90bee870bd757 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 29 Jun 2023 11:12:20 +0300 Subject: [PATCH 13/19] Push: sync integration --- Example/ExampleApp.xcodeproj/project.pbxproj | 2 +- .../Pairing/PairingTests.swift | 25 ++++--- Example/IntegrationTests/Push/PushTests.swift | 45 +++++++---- .../ApplicationLayer/EthKeyStore.swift | 15 ++-- .../DeletePushSubscriptionService.swift | 10 +-- .../DeletePushSubscriptionSubscriber.swift | 15 +--- .../Common/PushResubscribeService.swift | 8 +- .../Client/Common/SubscriptionsProvider.swift | 17 ----- .../Client/Dapp/DappPushClient.swift | 10 +-- .../Client/Dapp/DappPushClientFactory.swift | 10 ++- .../NotifyProposeResponseSubscriber.swift | 2 +- .../NotifyProposeResponder.swift | 22 +++--- .../NotifyProposeSubscriber.swift | 8 +- .../NotifyUpdateRequester.swift | 10 +-- .../NotifyUpdateResponseSubscriber.swift | 12 +-- .../PushSubscribeResponseSubscriber.swift | 35 ++++----- .../Client/Wallet/PushStorage.swift | 74 +++++++++++++++++++ .../PushSubscriptionStoreDelegate.swift | 24 ++++++ .../Wallet/PushSubscriptionsObserver.swift | 24 ------ .../Client/Wallet/PushSyncService.swift | 26 +++++++ .../Client/Wallet/WalletPushClient.swift | 56 ++++++-------- .../Wallet/WalletPushClientFactory.swift | 31 ++++---- .../PushStorageIdntifiers.swift | 2 +- .../Types/PushSubscription.swift | 1 + .../WalletConnectSync/Stores/SyncStore.swift | 1 - .../WalletConnectUtils/KeyedDatabase.swift | 2 +- .../PushClientProxy/PushClientProxy.swift | 8 +- .../PushClientRequestSubscriber.swift | 13 ++-- 28 files changed, 290 insertions(+), 218 deletions(-) delete mode 100644 Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift create mode 100644 Sources/WalletConnectPush/Client/Wallet/PushStorage.swift create mode 100644 Sources/WalletConnectPush/Client/Wallet/PushSubscriptionStoreDelegate.swift delete mode 100644 Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift create mode 100644 Sources/WalletConnectPush/Client/Wallet/PushSyncService.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index f84ab55e2..af251ea96 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ diff --git a/Example/IntegrationTests/Pairing/PairingTests.swift b/Example/IntegrationTests/Pairing/PairingTests.swift index 267ed68d8..eb6c7d482 100644 --- a/Example/IntegrationTests/Pairing/PairingTests.swift +++ b/Example/IntegrationTests/Pairing/PairingTests.swift @@ -8,6 +8,7 @@ import WalletConnectNetworking import WalletConnectEcho @testable import WalletConnectPush @testable import WalletConnectPairing +@testable import WalletConnectSync final class PairingTests: XCTestCase { @@ -21,7 +22,7 @@ final class PairingTests: XCTestCase { private var publishers = [AnyCancellable]() - func makeClientDependencies(prefix: String) -> (PairingClient, NetworkInteracting, KeychainStorageProtocol, KeyValueStorage) { + func makeClientDependencies(prefix: String) -> (PairingClient, NetworkInteracting, SyncClient, KeychainStorageProtocol, KeyValueStorage) { let keychain = KeychainStorageMock() let keyValueStorage = RuntimeKeyValueStorage() @@ -49,27 +50,30 @@ final class PairingTests: XCTestCase { keychainStorage: keychain, networkingClient: networkingClient) + let syncClient = SyncClientFactory.create(networkInteractor: networkingClient, bip44: DefaultBIP44Provider(), keychain: keychain) + let clientId = try! networkingClient.getClientId() networkingLogger.debug("My client id is: \(clientId)") - return (pairingClient, networkingClient, keychain, keyValueStorage) + return (pairingClient, networkingClient, syncClient, keychain, keyValueStorage) } func makeDappClients() { let prefix = "🤖 Dapp: " - let (pairingClient, networkingInteractor, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) + let (pairingClient, networkingInteractor, syncClient, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) let pushLogger = ConsoleLogger(suffix: prefix + " [Push]", loggingLevel: .debug) appPairingClient = pairingClient appPushClient = DappPushClientFactory.create(metadata: AppMetadata(name: name, description: "", url: "", icons: [""]), - logger: pushLogger, - keyValueStorage: keyValueStorage, - keychainStorage: keychain, - networkInteractor: networkingInteractor) + logger: pushLogger, + keyValueStorage: keyValueStorage, + keychainStorage: keychain, + networkInteractor: networkingInteractor, + syncClient: syncClient) } func makeWalletClients() { let prefix = "🐶 Wallet: " - let (pairingClient, networkingInteractor, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) + let (pairingClient, networkingInteractor, syncClient, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) let pushLogger = ConsoleLogger(suffix: prefix + " [Push]", loggingLevel: .debug) walletPairingClient = pairingClient let echoClient = EchoClientFactory.create(projectId: "", @@ -84,12 +88,13 @@ final class PairingTests: XCTestCase { groupKeychainStorage: KeychainStorageMock(), networkInteractor: networkingInteractor, pairingRegisterer: pairingClient, - echoClient: echoClient) + echoClient: echoClient, + syncClient: syncClient) } func makeWalletPairingClient() { let prefix = "🐶 Wallet: " - let (pairingClient, _, _, _) = makeClientDependencies(prefix: prefix) + let (pairingClient, _, _, _, _) = makeClientDependencies(prefix: prefix) walletPairingClient = pairingClient } diff --git a/Example/IntegrationTests/Push/PushTests.swift b/Example/IntegrationTests/Push/PushTests.swift index 0620653b1..65ba20c25 100644 --- a/Example/IntegrationTests/Push/PushTests.swift +++ b/Example/IntegrationTests/Push/PushTests.swift @@ -1,6 +1,7 @@ import Foundation import XCTest import WalletConnectUtils +import Web3 @testable import WalletConnectKMS import WalletConnectRelay import Combine @@ -8,6 +9,7 @@ import WalletConnectNetworking import WalletConnectEcho @testable import WalletConnectPush @testable import WalletConnectPairing +@testable import WalletConnectSync import WalletConnectIdentity import WalletConnectSigner @@ -21,10 +23,19 @@ final class PushTests: XCTestCase { var pairingStorage: PairingStorage! + let pk = try! EthereumPrivateKey() + + var privateKey: Data { + return Data(pk.rawPrivateKey) + } + + var account: Account { + return Account("eip155:1:" + pk.address.hex(eip55: true))! + } private var publishers = [AnyCancellable]() - func makeClientDependencies(prefix: String) -> (PairingClient, NetworkInteracting, KeychainStorageProtocol, KeyValueStorage) { + func makeClientDependencies(prefix: String) -> (PairingClient, NetworkInteracting, SyncClient, KeychainStorageProtocol, KeyValueStorage) { let keychain = KeychainStorageMock() let keyValueStorage = RuntimeKeyValueStorage() @@ -52,26 +63,29 @@ final class PushTests: XCTestCase { keychainStorage: keychain, networkingClient: networkingClient) + let syncClient = SyncClientFactory.create(networkInteractor: networkingClient, bip44: DefaultBIP44Provider(), keychain: keychain) + let clientId = try! networkingClient.getClientId() networkingLogger.debug("My client id is: \(clientId)") - return (pairingClient, networkingClient, keychain, keyValueStorage) + return (pairingClient, networkingClient, syncClient, keychain, keyValueStorage) } func makeDappClients() { let prefix = "🦄 Dapp: " - let (pairingClient, networkingInteractor, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) + let (pairingClient, networkingInteractor, syncClient, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) let pushLogger = ConsoleLogger(suffix: prefix + " [Push]", loggingLevel: .debug) dappPairingClient = pairingClient dappPushClient = DappPushClientFactory.create(metadata: AppMetadata(name: "GM Dapp", description: "", url: "https://gm-dapp-xi.vercel.app/", icons: []), logger: pushLogger, keyValueStorage: keyValueStorage, keychainStorage: keychain, - networkInteractor: networkingInteractor) + networkInteractor: networkingInteractor, + syncClient: syncClient) } func makeWalletClients() { let prefix = "🦋 Wallet: " - let (pairingClient, networkingInteractor, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) + let (pairingClient, networkingInteractor, syncClient, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) let pushLogger = ConsoleLogger(suffix: prefix + " [Push]", loggingLevel: .debug) walletPairingClient = pairingClient let echoClient = EchoClientFactory.create(projectId: "", @@ -86,7 +100,8 @@ final class PushTests: XCTestCase { groupKeychainStorage: KeychainStorageMock(), networkInteractor: networkingInteractor, pairingRegisterer: pairingClient, - echoClient: echoClient) + echoClient: echoClient, + syncClient: syncClient) } override func setUp() { @@ -99,7 +114,8 @@ final class PushTests: XCTestCase { let uri = try! await dappPairingClient.create() try! await walletPairingClient.pair(uri: uri) - try! await dappPushClient.propose(account: Account.stub(), topic: uri.topic) + try! await walletPushClient.enableSync(account: account, onSign: sign) + try! await dappPushClient.propose(account: account, topic: uri.topic) walletPushClient.requestPublisher.sink { [unowned self] (id, _, _) in Task(priority: .high) { try! await walletPushClient.approve(id: id, onSign: sign) } @@ -121,7 +137,7 @@ final class PushTests: XCTestCase { let uri = try! await dappPairingClient.create() try! await walletPairingClient.pair(uri: uri) - try! await dappPushClient.propose(account: Account.stub(), topic: uri.topic) + try! await dappPushClient.propose(account: account, topic: uri.topic) walletPushClient.requestPublisher.sink { [unowned self] (id, _, _) in Task(priority: .high) { try! await walletPushClient.reject(id: id) } @@ -141,7 +157,8 @@ final class PushTests: XCTestCase { func testWalletCreatesSubscription() async { let expectation = expectation(description: "expects to create push subscription") let metadata = AppMetadata(name: "GM Dapp", description: "", url: "https://gm-dapp-xi.vercel.app/", icons: []) - try! await walletPushClient.subscribe(metadata: metadata, account: Account.stub(), onSign: sign) + try! await walletPushClient.enableSync(account: account, onSign: sign) + try! await walletPushClient.subscribe(metadata: metadata, account: account, onSign: sign) walletPushClient.subscriptionsPublisher .first() .sink { [unowned self] subscriptions in @@ -156,7 +173,8 @@ final class PushTests: XCTestCase { let expectation = expectation(description: "expects to delete push subscription") let uri = try! await dappPairingClient.create() try! await walletPairingClient.pair(uri: uri) - try! await dappPushClient.propose(account: Account.stub(), topic: uri.topic) + try! await walletPushClient.enableSync(account: account, onSign: sign) + try! await dappPushClient.propose(account: account, topic: uri.topic) var subscriptionTopic: String! walletPushClient.requestPublisher.sink { [unowned self] (id, _, _) in @@ -184,7 +202,8 @@ final class PushTests: XCTestCase { let expectation = expectation(description: "expects to create and update push subscription") let metadata = AppMetadata(name: "GM Dapp", description: "", url: "https://gm-dapp-xi.vercel.app/", icons: []) let updateScope: Set = ["alerts"] - try! await walletPushClient.subscribe(metadata: metadata, account: Account.stub(), onSign: sign) + try! await walletPushClient.enableSync(account: account, onSign: sign) + try! await walletPushClient.subscribe(metadata: metadata, account: account, onSign: sign) walletPushClient.subscriptionsPublisher .first() .sink { [unowned self] subscriptions in @@ -211,7 +230,8 @@ final class PushTests: XCTestCase { let pushMessage = PushMessage.stub() let metadata = AppMetadata(name: "GM Dapp", description: "", url: "https://gm-dapp-xi.vercel.app/", icons: []) - try! await walletPushClient.subscribe(metadata: metadata, account: Account.stub(), onSign: sign) + try! await walletPushClient.enableSync(account: account, onSign: sign) + try! await walletPushClient.subscribe(metadata: metadata, account: account, onSign: sign) var subscription: PushSubscription! walletPushClient.subscriptionsPublisher .first() @@ -238,7 +258,6 @@ final class PushTests: XCTestCase { private extension PushTests { func sign(_ message: String) -> SigningResult { - let privateKey = Data(hex: "305c6cde3846927892cd32762f6120539f3ec74c9e3a16b9b798b1e85351ae2a") let signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create(projectId: InputConfig.projectId) return .signed(try! signer.sign(message: message, privateKey: privateKey, type: .eip191)) } diff --git a/Example/WalletApp/ApplicationLayer/EthKeyStore.swift b/Example/WalletApp/ApplicationLayer/EthKeyStore.swift index 5f6f085e0..7b4608a34 100644 --- a/Example/WalletApp/ApplicationLayer/EthKeyStore.swift +++ b/Example/WalletApp/ApplicationLayer/EthKeyStore.swift @@ -15,14 +15,11 @@ class EthKeyStore { } private init() { - // TODO: For testing !!! - self.privateKey = try! EthereumPrivateKey(hexPrivateKey: "0x660bc2a94efbef506a499aef10066a914e2aaa1791362fd6d15a5b23a1078b44") - - // if let privateKeyRaw = UserDefaults.standard.data(forKey: defaultsKey) { - // self.privateKey = try! EthereumPrivateKey(privateKeyRaw) - // } else { - // self.privateKey = try! EthereumPrivateKey() - // UserDefaults.standard.set(privateKeyRaw, forKey: defaultsKey) - // } + if let privateKeyRaw = UserDefaults.standard.data(forKey: defaultsKey) { + self.privateKey = try! EthereumPrivateKey(privateKeyRaw) + } else { + self.privateKey = try! EthereumPrivateKey() + UserDefaults.standard.set(privateKeyRaw, forKey: defaultsKey) + } } } diff --git a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift index c57306d40..287cdb61a 100644 --- a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift +++ b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift @@ -7,27 +7,27 @@ class DeletePushSubscriptionService { private let networkingInteractor: NetworkInteracting private let kms: KeyManagementServiceProtocol private let logger: ConsoleLogging - private let pushSubscriptionStore: SyncStore + private let pushStorage: PushStorage private let pushMessagesDatabase: PushMessagesDatabase? init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, - pushSubscriptionStore: SyncStore, + pushStorage: PushStorage, pushMessagesDatabase: PushMessagesDatabase?) { self.networkingInteractor = networkingInteractor self.kms = kms self.logger = logger self.pushMessagesDatabase = pushMessagesDatabase - self.pushSubscriptionStore = pushSubscriptionStore + self.pushStorage = pushStorage } func delete(topic: String) async throws { let params = PushDeleteParams.userDisconnected logger.debug("Will delete push subscription for reason: message: \(params.message) code: \(params.code), topic: \(topic)") - guard let _ = pushSubscriptionStore.get(for: topic) + guard let _ = pushStorage.getSubscription(topic: topic) else { throw Errors.pushSubscriptionNotFound} let protocolMethod = PushDeleteProtocolMethod() - try await pushSubscriptionStore.delete(id: topic) + try await pushStorage.deleteSubscription(topic: topic) pushMessagesDatabase?.deletePushMessages(topic: topic) let request = RPCRequest(method: protocolMethod.method, params: params) try await networkingInteractor.request(request, topic: topic, protocolMethod: protocolMethod) diff --git a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift index d16698a79..7ec0f6f3a 100644 --- a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionSubscriber.swift @@ -6,23 +6,17 @@ class DeletePushSubscriptionSubscriber { private let kms: KeyManagementServiceProtocol private let logger: ConsoleLogging private var publishers = [AnyCancellable]() - private let pushSubscriptionStore: SyncStore - - private let deleteSubscriptionPublisherSubject = PassthroughSubject() - - public var deleteSubscriptionPublisher: AnyPublisher { - deleteSubscriptionPublisherSubject.eraseToAnyPublisher() - } + private let pushStorage: PushStorage init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, - pushSubscriptionStore: SyncStore + pushStorage: PushStorage ) { self.networkingInteractor = networkingInteractor self.kms = kms self.logger = logger - self.pushSubscriptionStore = pushSubscriptionStore + self.pushStorage = pushStorage subscribeForDeleteSubscription() } @@ -34,10 +28,9 @@ class DeletePushSubscriptionSubscriber { let topic = payload.topic networkingInteractor.unsubscribe(topic: topic) Task(priority: .high) { - try await pushSubscriptionStore.delete(id: topic) + try await pushStorage.deleteSubscription(topic: topic) } kms.deleteSymmetricKey(for: topic) - deleteSubscriptionPublisherSubject.send(payload.topic) }.store(in: &publishers) } } diff --git a/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift b/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift index cb534dacc..c19769f4d 100644 --- a/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift +++ b/Sources/WalletConnectPush/Client/Common/PushResubscribeService.swift @@ -6,11 +6,11 @@ final class PushResubscribeService { private var publishers = Set() private let networkInteractor: NetworkInteracting - private let subscriptionsStorage: SyncStore + private let pushStorage: PushStorage - init(networkInteractor: NetworkInteracting, subscriptionsStorage: SyncStore) { + init(networkInteractor: NetworkInteracting, pushStorage: PushStorage) { self.networkInteractor = networkInteractor - self.subscriptionsStorage = subscriptionsStorage + self.pushStorage = pushStorage setUpResubscription() } @@ -18,7 +18,7 @@ final class PushResubscribeService { networkInteractor.socketConnectionStatusPublisher .sink { [unowned self] status in guard status == .connected else { return } - let topics = subscriptionsStorage.getAll().map{$0.topic} + let topics = pushStorage.getSubscriptions().map{$0.topic} Task(priority: .high) { try await networkInteractor.batchSubscribe(topics: topics) } diff --git a/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift b/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift deleted file mode 100644 index e82e2d9e8..000000000 --- a/Sources/WalletConnectPush/Client/Common/SubscriptionsProvider.swift +++ /dev/null @@ -1,17 +0,0 @@ -import Foundation - -class SubscriptionsProvider { - let store: SyncStore - - init(store: SyncStore) { - self.store = store - } - - public func getActiveSubscriptions() -> [PushSubscription] { - store.getAll() - } - - public func initialize(account: Account) async throws { - try await store.initialize(for: account) - } -} diff --git a/Sources/WalletConnectPush/Client/Dapp/DappPushClient.swift b/Sources/WalletConnectPush/Client/Dapp/DappPushClient.swift index a9182d80d..9c7d820ea 100644 --- a/Sources/WalletConnectPush/Client/Dapp/DappPushClient.swift +++ b/Sources/WalletConnectPush/Client/Dapp/DappPushClient.swift @@ -7,26 +7,26 @@ public class DappPushClient { } public var deleteSubscriptionPublisher: AnyPublisher { - deletePushSubscriptionSubscriber.deleteSubscriptionPublisher + return pushStorage.deleteSubscriptionPublisher } public let logger: ConsoleLogging private let notifyProposer: NotifyProposer - private let subscriptionsProvider: SubscriptionsProvider + private let pushStorage: PushStorage private let deletePushSubscriptionSubscriber: DeletePushSubscriptionSubscriber private let resubscribeService: PushResubscribeService private let notifyProposeResponseSubscriber: NotifyProposeResponseSubscriber init(logger: ConsoleLogging, kms: KeyManagementServiceProtocol, - subscriptionsProvider: SubscriptionsProvider, + pushStorage: PushStorage, deletePushSubscriptionSubscriber: DeletePushSubscriptionSubscriber, resubscribeService: PushResubscribeService, notifyProposer: NotifyProposer, notifyProposeResponseSubscriber: NotifyProposeResponseSubscriber) { self.logger = logger - self.subscriptionsProvider = subscriptionsProvider + self.pushStorage = pushStorage self.deletePushSubscriptionSubscriber = deletePushSubscriptionSubscriber self.resubscribeService = resubscribeService self.notifyProposer = notifyProposer @@ -38,6 +38,6 @@ public class DappPushClient { } public func getActiveSubscriptions() -> [PushSubscription] { - subscriptionsProvider.getActiveSubscriptions() + pushStorage.getSubscriptions() } } diff --git a/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift b/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift index 0849d02e9..18737a113 100644 --- a/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Dapp/DappPushClientFactory.swift @@ -19,15 +19,17 @@ public struct DappPushClientFactory { static func create(metadata: AppMetadata, logger: ConsoleLogging, keyValueStorage: KeyValueStorage, keychainStorage: KeychainStorageProtocol, networkInteractor: NetworkInteracting, syncClient: SyncClient) -> DappPushClient { let kms = KeyManagementService(keychain: keychainStorage) let subscriptionStore: SyncStore = SyncStoreFactory.create(name: PushStorageIdntifiers.pushSubscription, syncClient: syncClient, storage: keyValueStorage) - let subscriptionProvider = SubscriptionsProvider(store: subscriptionStore) - let deletePushSubscriptionSubscriber = DeletePushSubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushSubscriptionStore: subscriptionStore) - let resubscribeService = PushResubscribeService(networkInteractor: networkInteractor, subscriptionsStorage: subscriptionStore) + + let subscriptionStoreDelegate = PushSubscriptionStoreDelegate(networkingInteractor: networkInteractor, kms: kms) + let pushStorage = PushStorage(subscriptionStore: subscriptionStore, subscriptionStoreDelegate: subscriptionStoreDelegate) + let deletePushSubscriptionSubscriber = DeletePushSubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushStorage: pushStorage) + let resubscribeService = PushResubscribeService(networkInteractor: networkInteractor, pushStorage: pushStorage) let notifyProposer = NotifyProposer(networkingInteractor: networkInteractor, kms: kms, appMetadata: metadata, logger: logger) let notifyProposeResponseSubscriber = NotifyProposeResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, metadata: metadata) return DappPushClient( logger: logger, kms: kms, - subscriptionsProvider: subscriptionProvider, + pushStorage: pushStorage, deletePushSubscriptionSubscriber: deletePushSubscriptionSubscriber, resubscribeService: resubscribeService, notifyProposer: notifyProposer, diff --git a/Sources/WalletConnectPush/Client/Dapp/wc_notifyPropose/NotifyProposeResponseSubscriber.swift b/Sources/WalletConnectPush/Client/Dapp/wc_notifyPropose/NotifyProposeResponseSubscriber.swift index beed07644..ee294a384 100644 --- a/Sources/WalletConnectPush/Client/Dapp/wc_notifyPropose/NotifyProposeResponseSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Dapp/wc_notifyPropose/NotifyProposeResponseSubscriber.swift @@ -51,7 +51,7 @@ class NotifyProposeResponseSubscriber { let subscriptionKey = try SymmetricKey(hex: payload.response.subscriptionSymKey) let subscriptionTopic = subscriptionKey.rawRepresentation.sha256().toHexString() let relay = RelayProtocolOptions(protocol: "irn", data: nil) - let subscription = PushSubscription(topic: subscriptionTopic, account: payload.request.account, relay: relay, metadata: metadata, scope: [:], expiry: expiry) + let subscription = PushSubscription(topic: subscriptionTopic, account: payload.request.account, relay: relay, metadata: metadata, scope: [:], expiry: expiry, symKey: subscriptionKey.hexRepresentation) try kms.setSymmetricKey(subscriptionKey, for: subscriptionTopic) try await networkingInteractor.subscribe(topic: subscriptionTopic) return subscription diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeResponder.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeResponder.swift index 21b52257a..01b4fbcf2 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeResponder.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeResponder.swift @@ -11,24 +11,25 @@ class NotifyProposeResponder { private let networkingInteractor: NetworkInteracting private let kms: KeyManagementServiceProtocol private let logger: ConsoleLogging + private let pushStorage: PushStorage private let pushSubscribeRequester: PushSubscribeRequester private let rpcHistory: RPCHistory - private var subscriptionResponsePublisher: AnyPublisher, Never> private var publishers = [AnyCancellable]() init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, + pushStorage: PushStorage, pushSubscribeRequester: PushSubscribeRequester, rpcHistory: RPCHistory, - pushSubscribeResponseSubscriber: PushSubscribeResponseSubscriber + pushSubscribeResponseSubscriber: PushSubscribeResponseSubscriber ) { self.networkingInteractor = networkingInteractor self.kms = kms self.logger = logger + self.pushStorage = pushStorage self.pushSubscribeRequester = pushSubscribeRequester - self.subscriptionResponsePublisher = pushSubscribeResponseSubscriber.subscriptionPublisher self.rpcHistory = rpcHistory } @@ -42,18 +43,13 @@ class NotifyProposeResponder { let subscriptionAuthWrapper = try await pushSubscribeRequester.subscribe(metadata: proposal.metadata, account: proposal.account, onSign: onSign) var pushSubscription: PushSubscription! - try await withCheckedThrowingContinuation { continuation in - subscriptionResponsePublisher + try await withCheckedThrowingContinuation { [unowned self] continuation in + pushStorage.newSubscriptionPublisher .first() - .sink(receiveValue: { value in - switch value { - case .success(let subscription): - pushSubscription = subscription + .sink { value in + pushSubscription = value continuation.resume() - case .failure(let error): - continuation.resume(throwing: error) - } - }).store(in: &publishers) + }.store(in: &publishers) } guard let peerPublicKey = try? AgreementPublicKey(hex: proposal.publicKey) else { diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeSubscriber.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeSubscriber.swift index 4bb71b881..3ea41d805 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyPropose/NotifyProposeSubscriber.swift @@ -6,7 +6,7 @@ class NotifyProposeSubscriber { private let requestPublisherSubject = PassthroughSubject() private let networkingInteractor: NetworkInteracting - private let subscriptionsStore: SyncStore + private let pushStorage: PushStorage private var publishers = Set() public var requestPublisher: AnyPublisher { requestPublisherSubject.eraseToAnyPublisher() @@ -15,12 +15,12 @@ class NotifyProposeSubscriber { private let pairingRegisterer: PairingRegisterer init(networkingInteractor: NetworkInteracting, - subscriptionsStore: SyncStore, + pushStorage: PushStorage, publishers: Set = Set(), logger: ConsoleLogging, pairingRegisterer: PairingRegisterer) { self.networkingInteractor = networkingInteractor - self.subscriptionsStore = subscriptionsStore + self.pushStorage = pushStorage self.publishers = publishers self.logger = logger self.pairingRegisterer = pairingRegisterer @@ -40,7 +40,7 @@ class NotifyProposeSubscriber { } func hasNoSubscription(for domain: String) -> Bool { - subscriptionsStore.getAll().first {$0.metadata.url == domain} == nil + pushStorage.getSubscriptions().first { $0.metadata.url == domain } == nil } func respondError(requestId: RPCID, pairingTopic: String) async throws { diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift index f893bc8f9..565c57753 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift @@ -9,25 +9,25 @@ class NotifyUpdateRequester { private let identityClient: IdentityClient private let networkingInteractor: NetworkInteracting private let logger: ConsoleLogging - private let subscriptionsStore: SyncStore + private let pushStorage: PushStorage init(keyserverURL: URL, identityClient: IdentityClient, networkingInteractor: NetworkInteracting, logger: ConsoleLogging, - subscriptionsStore: SyncStore + pushStorage: PushStorage ) { self.keyserverURL = keyserverURL self.identityClient = identityClient self.networkingInteractor = networkingInteractor self.logger = logger - self.subscriptionsStore = subscriptionsStore + self.pushStorage = pushStorage } func update(topic: String, scope: Set) async throws { - logger.debug("NotifyUpdateRequester: updating subscription for topic: \(topic)") - guard let subscription = subscriptionsStore.get(for: topic) else { throw Errors.noSubscriptionForGivenTopic } + + guard let subscription = pushStorage.getSubscription(topic: topic) else { throw Errors.noSubscriptionForGivenTopic } let request = try createJWTRequest(subscriptionAccount: subscription.account, dappUrl: subscription.metadata.url, scope: scope) diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift index a43a3ce08..e3b77d8ca 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift @@ -10,7 +10,7 @@ class NotifyUpdateResponseSubscriber { private let networkingInteractor: NetworkInteracting private var publishers = [AnyCancellable]() private let logger: ConsoleLogging - private let subscriptionsStore: SyncStore + private let pushStorage: PushStorage private let subscriptionScopeProvider: SubscriptionScopeProvider private var subscriptionPublisherSubject = PassthroughSubject, Never>() var updateSubscriptionPublisher: AnyPublisher, Never> { @@ -20,11 +20,11 @@ class NotifyUpdateResponseSubscriber { init(networkingInteractor: NetworkInteracting, logger: ConsoleLogging, subscriptionScopeProvider: SubscriptionScopeProvider, - subscriptionsStore: SyncStore + pushStorage: PushStorage ) { self.networkingInteractor = networkingInteractor self.logger = logger - self.subscriptionsStore = subscriptionsStore + self.pushStorage = pushStorage self.subscriptionScopeProvider = subscriptionScopeProvider subscribeForUpdateResponse() } @@ -41,16 +41,16 @@ class NotifyUpdateResponseSubscriber { let (_, claims) = try SubscriptionJWTPayload.decodeAndVerify(from: payload.request) let scope = try await buildScope(selected: claims.scp, dappUrl: claims.aud) - guard let oldSubscription = try? subscriptionsStore.get(for: subscriptionTopic) else { + guard let oldSubscription = pushStorage.getSubscription(topic: subscriptionTopic) else { logger.debug("NotifyUpdateResponseSubscriber Subscription does not exist") subscriptionPublisherSubject.send(.failure(Errors.subscriptionDoesNotExist)) return } let expiry = Date(timeIntervalSince1970: TimeInterval(claims.exp)) - let updatedSubscription = PushSubscription(topic: subscriptionTopic, account: oldSubscription.account, relay: oldSubscription.relay, metadata: oldSubscription.metadata, scope: scope, expiry: expiry) + let updatedSubscription = PushSubscription(topic: subscriptionTopic, account: oldSubscription.account, relay: oldSubscription.relay, metadata: oldSubscription.metadata, scope: scope, expiry: expiry, symKey: oldSubscription.symKey) - try await subscriptionsStore.set(object: updatedSubscription, for: updatedSubscription.account) + try await pushStorage.setSubscription(updatedSubscription) subscriptionPublisherSubject.send(.success(updatedSubscription)) diff --git a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift index 9d920dd8d..d8c5fe66c 100644 --- a/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectPush/Client/Wallet/ProtocolEngine/wc_pushSubscribe/PushSubscribeResponseSubscriber.swift @@ -1,4 +1,3 @@ - import Foundation import Combine @@ -7,24 +6,26 @@ class PushSubscribeResponseSubscriber { case couldNotCreateSubscription } + private let subscriptionErrorSubject = PassthroughSubject() + + var subscriptionErrorPublisher: AnyPublisher { + return subscriptionErrorSubject.eraseToAnyPublisher() + } + private let networkingInteractor: NetworkInteracting private let kms: KeyManagementServiceProtocol private var publishers = [AnyCancellable]() private let logger: ConsoleLogging - private let subscriptionsStore: SyncStore + private let pushStorage: PushStorage private let groupKeychainStorage: KeychainStorageProtocol private let dappsMetadataStore: CodableStore private let subscriptionScopeProvider: SubscriptionScopeProvider - private var subscriptionPublisherSubject = PassthroughSubject, Never>() - var subscriptionPublisher: AnyPublisher, Never> { - return subscriptionPublisherSubject.eraseToAnyPublisher() - } init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, groupKeychainStorage: KeychainStorageProtocol, - subscriptionsStore: SyncStore, + pushStorage: PushStorage, dappsMetadataStore: CodableStore, subscriptionScopeProvider: SubscriptionScopeProvider ) { @@ -32,7 +33,7 @@ class PushSubscribeResponseSubscriber { self.kms = kms self.logger = logger self.groupKeychainStorage = groupKeychainStorage - self.subscriptionsStore = subscriptionsStore + self.pushStorage = pushStorage self.dappsMetadataStore = dappsMetadataStore self.subscriptionScopeProvider = subscriptionScopeProvider subscribeForSubscriptionResponse() @@ -47,8 +48,7 @@ class PushSubscribeResponseSubscriber { guard let responseKeys = kms.getAgreementSecret(for: payload.topic) else { logger.debug("PushSubscribeResponseSubscriber: no symmetric key for topic \(payload.topic)") - subscriptionPublisherSubject.send(.failure(Errors.couldNotCreateSubscription)) - return + return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) } // get keypair Y @@ -59,12 +59,13 @@ class PushSubscribeResponseSubscriber { var metadata: AppMetadata! var pushSubscriptionTopic: String! var subscribedTypes: Set! + var agreementKeysP: AgreementKeys! let (subscriptionPayload, claims) = try SubscriptionJWTPayload.decodeAndVerify(from: payload.request) let subscribedScope = subscriptionPayload.scope .components(separatedBy: " ") do { // generate symm key P - let agreementKeysP = try kms.performKeyAgreement(selfPublicKey: pubKeyY, peerPublicKey: peerPubKeyZ) + agreementKeysP = try kms.performKeyAgreement(selfPublicKey: pubKeyY, peerPublicKey: peerPubKeyZ) pushSubscriptionTopic = agreementKeysP.derivedTopic() try kms.setAgreementSecret(agreementKeysP, topic: pushSubscriptionTopic) try groupKeychainStorage.add(agreementKeysP, forKey: pushSubscriptionTopic) @@ -76,26 +77,22 @@ class PushSubscribeResponseSubscriber { try await networkingInteractor.subscribe(topic: pushSubscriptionTopic) } catch { logger.debug("PushSubscribeResponseSubscriber: error: \(error)") - subscriptionPublisherSubject.send(.failure(Errors.couldNotCreateSubscription)) - return + return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) } guard let metadata = metadata else { logger.debug("PushSubscribeResponseSubscriber: no metadata for topic: \(pushSubscriptionTopic!)") - subscriptionPublisherSubject.send(.failure(Errors.couldNotCreateSubscription)) - return + return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) } dappsMetadataStore.delete(forKey: payload.topic) let expiry = Date(timeIntervalSince1970: TimeInterval(claims.exp)) let scope: [String: ScopeValue] = subscribedTypes.reduce(into: [:]) { $0[$1.name] = ScopeValue(description: $1.description, enabled: true) } - let pushSubscription = PushSubscription(topic: pushSubscriptionTopic, account: account, relay: RelayProtocolOptions(protocol: "irn", data: nil), metadata: metadata, scope: scope, expiry: expiry) + let pushSubscription = PushSubscription(topic: pushSubscriptionTopic, account: account, relay: RelayProtocolOptions(protocol: "irn", data: nil), metadata: metadata, scope: scope, expiry: expiry, symKey: agreementKeysP.sharedKey.hexRepresentation) - try! await subscriptionsStore.set(object: pushSubscription, for: pushSubscription.account) + try await pushStorage.setSubscription(pushSubscription) logger.debug("PushSubscribeResponseSubscriber: unsubscribing response topic: \(payload.topic)") networkingInteractor.unsubscribe(topic: payload.topic) - - subscriptionPublisherSubject.send(.success(pushSubscription)) } }.store(in: &publishers) } diff --git a/Sources/WalletConnectPush/Client/Wallet/PushStorage.swift b/Sources/WalletConnectPush/Client/Wallet/PushStorage.swift new file mode 100644 index 000000000..8393c734f --- /dev/null +++ b/Sources/WalletConnectPush/Client/Wallet/PushStorage.swift @@ -0,0 +1,74 @@ +import Foundation +import Combine + +final class PushStorage { + + private var publishers = Set() + + private let subscriptionStore: SyncStore + + private let newSubscriptionSubject = PassthroughSubject() + private let deleteSubscriptionSubject = PassthroughSubject() + + private let subscriptionStoreDelegate: PushSubscriptionStoreDelegate + + var newSubscriptionPublisher: AnyPublisher { + return newSubscriptionSubject.eraseToAnyPublisher() + } + + var deleteSubscriptionPublisher: AnyPublisher { + return deleteSubscriptionSubject.eraseToAnyPublisher() + } + + var subscriptionsPublisher: AnyPublisher<[PushSubscription], Never> { + return subscriptionStore.dataUpdatePublisher + } + + init(subscriptionStore: SyncStore, subscriptionStoreDelegate: PushSubscriptionStoreDelegate) { + self.subscriptionStore = subscriptionStore + self.subscriptionStoreDelegate = subscriptionStoreDelegate + setupSubscriptions() + } + + func initialize(account: Account) async throws { + try await subscriptionStore.initialize(for: account) + } + + func setupSubscriptions(account: Account) async throws { + try subscriptionStore.setupSubscriptions(account: account) + } + + func getSubscriptions() -> [PushSubscription] { + return subscriptionStore.getAll() + } + + func getSubscription(topic: String) -> PushSubscription? { + return subscriptionStore.get(for: topic) + } + + func setSubscription(_ subscription: PushSubscription) async throws { + try await subscriptionStore.set(object: subscription, for: subscription.account) + newSubscriptionSubject.send(subscription) + } + + func deleteSubscription(topic: String) async throws { + try await subscriptionStore.delete(id: topic) + deleteSubscriptionSubject.send(topic) + } +} + +private extension PushStorage { + + func setupSubscriptions() { + subscriptionStore.syncUpdatePublisher.sink { [unowned self] (_, _, update) in + switch update { + case .set(let subscription): + subscriptionStoreDelegate.onUpdate(subscription) + newSubscriptionSubject.send(subscription) + case .delete(let id): + subscriptionStoreDelegate.onDelete(id) + deleteSubscriptionSubject.send(id) + } + }.store(in: &publishers) + } +} diff --git a/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionStoreDelegate.swift b/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionStoreDelegate.swift new file mode 100644 index 000000000..e38f5043c --- /dev/null +++ b/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionStoreDelegate.swift @@ -0,0 +1,24 @@ +import Foundation + +final class PushSubscriptionStoreDelegate { + + private let networkingInteractor: NetworkInteracting + private let kms: KeyManagementServiceProtocol + + init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol) { + self.networkingInteractor = networkingInteractor + self.kms = kms + } + + func onUpdate(_ subscription: PushSubscription) { + Task(priority: .high) { + let symmetricKey = try SymmetricKey(hex: subscription.symKey) + try kms.setSymmetricKey(symmetricKey, for: subscription.topic) + try await networkingInteractor.subscribe(topic: subscription.topic) + } + } + + func onDelete(_ id: String) { + + } +} diff --git a/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift b/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift deleted file mode 100644 index 71922c8c1..000000000 --- a/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Combine -import Foundation - -class PushSubscriptionsObserver { - private var publishers = [AnyCancellable]() - - public var subscriptionsPublisher: AnyPublisher<[PushSubscription], Never> { - subscriptionsPublisherSubject.eraseToAnyPublisher() - } - private let subscriptionsPublisherSubject = PassthroughSubject<[PushSubscription], Never>() - - private let store: SyncStore - - init(store: SyncStore) { - self.store = store - setUpSubscription() - } - - func setUpSubscription() { - store.dataUpdatePublisher.sink(receiveValue: { [unowned self] subscriptions in - subscriptionsPublisherSubject.send(subscriptions) - }).store(in: &publishers) - } -} diff --git a/Sources/WalletConnectPush/Client/Wallet/PushSyncService.swift b/Sources/WalletConnectPush/Client/Wallet/PushSyncService.swift new file mode 100644 index 000000000..6b4a5d8d1 --- /dev/null +++ b/Sources/WalletConnectPush/Client/Wallet/PushSyncService.swift @@ -0,0 +1,26 @@ +import Foundation + +final class PushSyncService { + + private let syncClient: SyncClient + private let logger: ConsoleLogging + + init(syncClient: SyncClient, logger: ConsoleLogging) { + self.syncClient = syncClient + self.logger = logger + } + + func registerIfNeeded(account: Account, onSign: @escaping SigningCallback) async throws { + guard !syncClient.isRegistered(account: account) else { return } + + let result = await onSign(syncClient.getMessage(account: account)) + + switch result { + case .signed(let signature): + try await syncClient.register(account: account, signature: signature) + logger.debug("Sync pushSubscriptions store registered and initialized") + case .rejected: + throw PushError.registerSignatureRejected + } + } +} diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift index 074ab7988..ee6b5c6ca 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift @@ -6,23 +6,23 @@ public class WalletPushClient { private var publishers = Set() - private let deletePushSubscriptionSubscriber: DeletePushSubscriptionSubscriber + /// publishes new subscriptions + public var newSubscriptionPublisher: AnyPublisher { + return pushStorage.newSubscriptionPublisher + } - public var deleteSubscriptionPublisher: AnyPublisher { - deletePushSubscriptionSubscriber.deleteSubscriptionPublisher + public var subscriptionErrorPublisher: AnyPublisher { + return pushSubscribeResponseSubscriber.subscriptionErrorPublisher } - /// publishes new subscriptions - public var subscriptionPublisher: AnyPublisher, Never> { - return pushSubscribeResponseSubscriber.subscriptionPublisher + public var deleteSubscriptionPublisher: AnyPublisher { + return pushStorage.deleteSubscriptionPublisher } public var subscriptionsPublisher: AnyPublisher<[PushSubscription], Never> { - return pushSubscriptionsObserver.subscriptionsPublisher + return pushStorage.subscriptionsPublisher } - private let pushSubscriptionsObserver: PushSubscriptionsObserver - public var requestPublisher: AnyPublisher { notifyProposeSubscriber.requestPublisher } @@ -41,12 +41,13 @@ public class WalletPushClient { public let logger: ConsoleLogging private let echoClient: EchoClient - private let syncClient: SyncClient + private let pushStorage: PushStorage + private let pushSyncService: PushSyncService private let pushMessageSubscriber: PushMessageSubscriber - private let subscriptionsProvider: SubscriptionsProvider private let pushMessagesDatabase: PushMessagesDatabase private let resubscribeService: PushResubscribeService private let pushSubscribeResponseSubscriber: PushSubscribeResponseSubscriber + private let deletePushSubscriptionSubscriber: DeletePushSubscriptionSubscriber private let notifyUpdateRequester: NotifyUpdateRequester private let notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber private let notifyProposeResponder: NotifyProposeResponder @@ -55,15 +56,15 @@ public class WalletPushClient { init(logger: ConsoleLogging, kms: KeyManagementServiceProtocol, echoClient: EchoClient, - syncClient: SyncClient, pushMessageSubscriber: PushMessageSubscriber, - subscriptionsProvider: SubscriptionsProvider, + pushStorage: PushStorage, + pushSyncService: PushSyncService, pushMessagesDatabase: PushMessagesDatabase, deletePushSubscriptionService: DeletePushSubscriptionService, resubscribeService: PushResubscribeService, - pushSubscriptionsObserver: PushSubscriptionsObserver, pushSubscribeRequester: PushSubscribeRequester, pushSubscribeResponseSubscriber: PushSubscribeResponseSubscriber, + deletePushSubscriptionSubscriber: DeletePushSubscriptionSubscriber, notifyUpdateRequester: NotifyUpdateRequester, notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber, notifyProposeResponder: NotifyProposeResponder, @@ -71,35 +72,25 @@ public class WalletPushClient { ) { self.logger = logger self.echoClient = echoClient - self.syncClient = syncClient self.pushMessageSubscriber = pushMessageSubscriber - self.subscriptionsProvider = subscriptionsProvider + self.pushStorage = pushStorage + self.pushSyncService = pushSyncService self.pushMessagesDatabase = pushMessagesDatabase self.deletePushSubscriptionService = deletePushSubscriptionService self.resubscribeService = resubscribeService - self.pushSubscriptionsObserver = pushSubscriptionsObserver self.pushSubscribeRequester = pushSubscribeRequester self.pushSubscribeResponseSubscriber = pushSubscribeResponseSubscriber + self.deletePushSubscriptionSubscriber = deletePushSubscriptionSubscriber self.notifyUpdateRequester = notifyUpdateRequester self.notifyUpdateResponseSubscriber = notifyUpdateResponseSubscriber self.notifyProposeResponder = notifyProposeResponder self.notifyProposeSubscriber = notifyProposeSubscriber } - public func register(account: Account, onSign: @escaping SigningCallback) async throws { - try await subscriptionsProvider.initialize(account: account) - - guard !syncClient.isRegistered(account: account) else { return } - - let result = await onSign(syncClient.getMessage(account: account)) - - switch result { - case .signed(let signature): - try await syncClient.register(account: account, signature: signature) - logger.debug("Sync pushSubscriptions store registered and initialized") - case .rejected: - throw PushError.registerSignatureRejected - } + public func enableSync(account: Account, onSign: @escaping SigningCallback) async throws { + try await pushSyncService.registerIfNeeded(account: account, onSign: onSign) + try await pushStorage.initialize(account: account) + try await pushStorage.setupSubscriptions(account: account) } public func subscribe(metadata: AppMetadata, account: Account, onSign: @escaping SigningCallback) async throws { @@ -119,7 +110,7 @@ public class WalletPushClient { } public func getActiveSubscriptions() -> [PushSubscription] { - subscriptionsProvider.getActiveSubscriptions() + return pushStorage.getSubscriptions() } public func getMessageHistory(topic: String) -> [PushMessageRecord] { @@ -139,7 +130,6 @@ public class WalletPushClient { } } - #if targetEnvironment(simulator) extension WalletPushClient { public func register(deviceToken: String) async throws { diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift index 0919df7da..f57d7b7ef 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift @@ -34,50 +34,47 @@ public struct WalletPushClientFactory { syncClient: SyncClient ) -> WalletPushClient { let kms = KeyManagementService(keychain: keychainStorage) - let history = RPCHistoryFactory.createForNetwork(keyValueStorage: keyValueStorage) - let subscriptionStore: SyncStore = SyncStoreFactory.create(name: PushStorageIdntifiers.pushSubscription, syncClient: syncClient, storage: keyValueStorage) - + let subscriptionStoreDelegate = PushSubscriptionStoreDelegate(networkingInteractor: networkInteractor, kms: kms) + let pushStorage = PushStorage(subscriptionStore: subscriptionStore, subscriptionStoreDelegate: subscriptionStoreDelegate) + let pushSyncService = PushSyncService(syncClient: syncClient, logger: logger) let identityClient = IdentityClientFactory.create(keyserver: keyserverURL, keychain: keychainStorage, logger: logger) - let pushMessagesRecordsStore = CodableStore(defaults: keyValueStorage, identifier: PushStorageIdntifiers.pushMessagesRecords) let pushMessagesDatabase = PushMessagesDatabase(store: pushMessagesRecordsStore) let pushMessageSubscriber = PushMessageSubscriber(networkingInteractor: networkInteractor, pushMessagesDatabase: pushMessagesDatabase, logger: logger) - let subscriptionProvider = SubscriptionsProvider(store: subscriptionStore) - let deletePushSubscriptionService = DeletePushSubscriptionService(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushSubscriptionStore: subscriptionStore, pushMessagesDatabase: pushMessagesDatabase) - let resubscribeService = PushResubscribeService(networkInteractor: networkInteractor, subscriptionsStorage: subscriptionStore) - let pushSubscriptionsObserver = PushSubscriptionsObserver(store: subscriptionStore) + let deletePushSubscriptionService = DeletePushSubscriptionService(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushStorage: pushStorage, pushMessagesDatabase: pushMessagesDatabase) + let resubscribeService = PushResubscribeService(networkInteractor: networkInteractor, pushStorage: pushStorage) let dappsMetadataStore = CodableStore(defaults: keyValueStorage, identifier: PushStorageIdntifiers.dappsMetadataStore) let subscriptionScopeProvider = SubscriptionScopeProvider() let pushSubscribeRequester = PushSubscribeRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, subscriptionScopeProvider: subscriptionScopeProvider, dappsMetadataStore: dappsMetadataStore) - let pushSubscribeResponseSubscriber = PushSubscribeResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, groupKeychainStorage: groupKeychainStorage, subscriptionsStore: subscriptionStore, dappsMetadataStore: dappsMetadataStore, subscriptionScopeProvider: subscriptionScopeProvider) + let pushSubscribeResponseSubscriber = PushSubscribeResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, groupKeychainStorage: groupKeychainStorage, pushStorage: pushStorage, dappsMetadataStore: dappsMetadataStore, subscriptionScopeProvider: subscriptionScopeProvider) - let notifyUpdateRequester = NotifyUpdateRequester(keyserverURL: keyserverURL, identityClient: identityClient, networkingInteractor: networkInteractor, logger: logger, subscriptionsStore: subscriptionStore) + let notifyUpdateRequester = NotifyUpdateRequester(keyserverURL: keyserverURL, identityClient: identityClient, networkingInteractor: networkInteractor, logger: logger, pushStorage: pushStorage) - let notifyUpdateResponseSubscriber = NotifyUpdateResponseSubscriber(networkingInteractor: networkInteractor, logger: logger, subscriptionScopeProvider: subscriptionScopeProvider, subscriptionsStore: subscriptionStore) - let notifyProposeResponder = NotifyProposeResponder(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushSubscribeRequester: pushSubscribeRequester, rpcHistory: history, pushSubscribeResponseSubscriber: pushSubscribeResponseSubscriber) + let notifyUpdateResponseSubscriber = NotifyUpdateResponseSubscriber(networkingInteractor: networkInteractor, logger: logger, subscriptionScopeProvider: subscriptionScopeProvider, pushStorage: pushStorage) + let notifyProposeResponder = NotifyProposeResponder(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushStorage: pushStorage, pushSubscribeRequester: pushSubscribeRequester, rpcHistory: history, pushSubscribeResponseSubscriber: pushSubscribeResponseSubscriber) - let notifyProposeSubscriber = NotifyProposeSubscriber(networkingInteractor: networkInteractor, subscriptionsStore: subscriptionStore, logger: logger, pairingRegisterer: pairingRegisterer) + let notifyProposeSubscriber = NotifyProposeSubscriber(networkingInteractor: networkInteractor, pushStorage: pushStorage, logger: logger, pairingRegisterer: pairingRegisterer) - let deletePushSubscriptionSubscriber = DeletePushSubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushSubscriptionStore: subscriptionStore) + let deletePushSubscriptionSubscriber = DeletePushSubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushStorage: pushStorage) return WalletPushClient( logger: logger, kms: kms, echoClient: echoClient, - syncClient: syncClient, pushMessageSubscriber: pushMessageSubscriber, - subscriptionsProvider: subscriptionProvider, + pushStorage: pushStorage, + pushSyncService: pushSyncService, pushMessagesDatabase: pushMessagesDatabase, deletePushSubscriptionService: deletePushSubscriptionService, resubscribeService: resubscribeService, - pushSubscriptionsObserver: pushSubscriptionsObserver, pushSubscribeRequester: pushSubscribeRequester, pushSubscribeResponseSubscriber: pushSubscribeResponseSubscriber, + deletePushSubscriptionSubscriber: deletePushSubscriptionSubscriber, notifyUpdateRequester: notifyUpdateRequester, notifyUpdateResponseSubscriber: notifyUpdateResponseSubscriber, notifyProposeResponder: notifyProposeResponder, diff --git a/Sources/WalletConnectPush/PushStorageIdntifiers.swift b/Sources/WalletConnectPush/PushStorageIdntifiers.swift index 635242b7c..bc627ce69 100644 --- a/Sources/WalletConnectPush/PushStorageIdntifiers.swift +++ b/Sources/WalletConnectPush/PushStorageIdntifiers.swift @@ -1,7 +1,7 @@ import Foundation enum PushStorageIdntifiers { - static let pushSubscription = "com.walletconnect.push.subscription" + static let pushSubscription = "com.walletconnect.notify.pushSubscription" static let pushMessagesRecords = "com.walletconnect.sdk.pushMessagesRecords" static let dappsMetadataStore = "com.walletconnect.sdk.dappsMetadataStore" diff --git a/Sources/WalletConnectPush/Types/PushSubscription.swift b/Sources/WalletConnectPush/Types/PushSubscription.swift index 46e021b00..756d33781 100644 --- a/Sources/WalletConnectPush/Types/PushSubscription.swift +++ b/Sources/WalletConnectPush/Types/PushSubscription.swift @@ -7,6 +7,7 @@ public struct PushSubscription: DatabaseObject { public let metadata: AppMetadata public let scope: [String: ScopeValue] public let expiry: Date + public let symKey: String public var databaseId: String { return topic diff --git a/Sources/WalletConnectSync/Stores/SyncStore.swift b/Sources/WalletConnectSync/Stores/SyncStore.swift index 227a39140..3ad9f6629 100644 --- a/Sources/WalletConnectSync/Stores/SyncStore.swift +++ b/Sources/WalletConnectSync/Stores/SyncStore.swift @@ -84,7 +84,6 @@ public final class SyncStore { guard let result = objectStore.find(id: id) else { return } - // TODO: Should we pass topic to sync client? let record = try indexStore.getRecord(topic: result.key) try await delete(id: id, for: record.account) } diff --git a/Sources/WalletConnectUtils/KeyedDatabase.swift b/Sources/WalletConnectUtils/KeyedDatabase.swift index dfd8f30c4..6218c6ffc 100644 --- a/Sources/WalletConnectUtils/KeyedDatabase.swift +++ b/Sources/WalletConnectUtils/KeyedDatabase.swift @@ -44,7 +44,7 @@ public class KeyedDatabase where Element: DatabaseObject { public func find(id: String) -> (key: String, element: Element)? { guard - let value = index.first(where: { $0.key == id }), + let value = index.first(where: { $0.value[id] != nil }), let element = value.value[id] else { return nil } diff --git a/Sources/Web3Inbox/PushClientProxy/PushClientProxy.swift b/Sources/Web3Inbox/PushClientProxy/PushClientProxy.swift index cb6fb8e8d..ff8c3e47d 100644 --- a/Sources/Web3Inbox/PushClientProxy/PushClientProxy.swift +++ b/Sources/Web3Inbox/PushClientProxy/PushClientProxy.swift @@ -10,18 +10,14 @@ final class PushClientProxy { init(client: WalletPushClient, onSign: @escaping SigningCallback) { self.client = client self.onSign = onSign - - // TODO: For testing !!! - Task(priority: .high) { - let account = Account("eip155:1:0x32F9ABCf897010fDF038D1A15c6553511EcD8c1D")! - try await client.register(account: account, onSign: onSign) - } } func request(_ request: RPCRequest) async throws { guard let event = PushWebViewEvent(rawValue: request.method) else { throw Errors.unregisteredMethod } + // TODO: Handle register event + switch event { case .approve: let params = try parse(ApproveRequest.self, params: request.params) diff --git a/Sources/Web3Inbox/PushClientProxy/PushClientRequestSubscriber.swift b/Sources/Web3Inbox/PushClientProxy/PushClientRequestSubscriber.swift index 7cb07c45a..921322154 100644 --- a/Sources/Web3Inbox/PushClientProxy/PushClientRequestSubscriber.swift +++ b/Sources/Web3Inbox/PushClientProxy/PushClientRequestSubscriber.swift @@ -31,15 +31,12 @@ final class PushClientRequestSubscriber { handle(event: .pushDelete, params: record) }.store(in: &publishers) - client.subscriptionPublisher.sink { [unowned self] record in - switch record { - case .success(let subscription): - handle(event: .pushSubscription, params: subscription) - case .failure: - //TODO - handle error - break + client.newSubscriptionPublisher.sink { [unowned self] subscription in + handle(event: .pushSubscription, params: subscription) + }.store(in: &publishers) - } + client.deleteSubscriptionPublisher.sink { [unowned self] topic in + handle(event: .pushDelete, params: topic) }.store(in: &publishers) client.updateSubscriptionPublisher.sink { [unowned self] record in From 09bd78e4fccf679eaf01ac233c6e9229eac4725a Mon Sep 17 00:00:00 2001 From: Alexander Lisovik Date: Thu, 29 Jun 2023 14:25:35 +0200 Subject: [PATCH 14/19] Add topic to AuthRequest --- Sources/Auth/Services/Wallet/PendingRequestsProvider.swift | 2 +- Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift | 4 ++-- Sources/Auth/Types/Public/AuthRequest.swift | 1 + Sources/Web3Wallet/Web3WalletClient.swift | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift b/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift index 524c029d5..5050ef778 100644 --- a/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift +++ b/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift @@ -12,7 +12,7 @@ class PendingRequestsProvider { .filter {$0.request.method == "wc_authRequest"} .compactMap { guard let params = try? $0.request.params?.get(AuthRequestParams.self) else { return nil } - return AuthRequest(id: $0.request.id!, payload: params.payloadParams) + return AuthRequest(id: $0.request.id!, topic: $0.topic, payload: params.payloadParams) } return pendingRequests } diff --git a/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift b/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift index 2b8164eb7..fd575188d 100644 --- a/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift +++ b/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift @@ -38,7 +38,7 @@ class WalletRequestSubscriber { peerMetadata: payload.request.requester.metadata ) - let request = AuthRequest(id: payload.id, payload: payload.request.payloadParams, appMetadata: payload.request.requester.metadata) + let request = AuthRequest(id: payload.id, topic: payload.topic, payload: payload.request.payloadParams) guard let verifyClient else { onRequest?((request, nil)) @@ -51,7 +51,7 @@ class WalletRequestSubscriber { origin: origin, domain: payload.request.payloadParams.domain ) - onRequest?((request, verifyContext, payload.request.requester.metadata)) + onRequest?((request, verifyContext)) } }.store(in: &publishers) } diff --git a/Sources/Auth/Types/Public/AuthRequest.swift b/Sources/Auth/Types/Public/AuthRequest.swift index b5095751c..4cee66bb1 100644 --- a/Sources/Auth/Types/Public/AuthRequest.swift +++ b/Sources/Auth/Types/Public/AuthRequest.swift @@ -2,5 +2,6 @@ import Foundation public struct AuthRequest: Equatable, Codable { public let id: RPCID + public let topic: String public let payload: AuthPayload } diff --git a/Sources/Web3Wallet/Web3WalletClient.swift b/Sources/Web3Wallet/Web3WalletClient.swift index 4b96b692b..757b15e7f 100644 --- a/Sources/Web3Wallet/Web3WalletClient.swift +++ b/Sources/Web3Wallet/Web3WalletClient.swift @@ -26,7 +26,7 @@ public class Web3WalletClient { /// Publisher that sends authentication requests /// /// Wallet should subscribe on events in order to receive auth requests. - public var authRequestPublisher: AnyPublisher<(request: AuthRequest, context: VerifyContext?, appMetadata: payload.request.requester.metadata), Never> { + public var authRequestPublisher: AnyPublisher<(request: AuthRequest, context: VerifyContext?), Never> { authClient.authRequestPublisher.eraseToAnyPublisher() } From 27c29e7b224de83bffb4356a0ebf2f3d07098e2b Mon Sep 17 00:00:00 2001 From: Alexander Lisovik Date: Fri, 30 Jun 2023 10:52:34 +0200 Subject: [PATCH 15/19] Allow empty optional events --- Sources/WalletConnectSign/Namespace.swift | 14 +- .../AutoNamespacesValidationTests.swift | 140 ++++++++++++++++++ 2 files changed, 152 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectSign/Namespace.swift b/Sources/WalletConnectSign/Namespace.swift index 43ba9518a..35529e68b 100644 --- a/Sources/WalletConnectSign/Namespace.swift +++ b/Sources/WalletConnectSign/Namespace.swift @@ -266,7 +266,12 @@ public enum AutoNamespaces { return } - let sessionEvents = Set(proposalNamespace.events).intersection(Set(events)) + var sessionEvents = Set() + if !proposalNamespace.events.isEmpty && !events.isEmpty { + sessionEvents = Set(proposalNamespace.events).intersection(Set(events)) + } else { + sessionEvents = Set(proposalNamespace.events).symmetricDifference(Set(events)) + } guard !sessionEvents.isEmpty else { return } @@ -304,7 +309,12 @@ public enum AutoNamespaces { return } - let sessionEvents = Set(proposalNamespace.events).intersection(Set(events)) + var sessionEvents = Set() + if !proposalNamespace.events.isEmpty && !events.isEmpty { + sessionEvents = Set(proposalNamespace.events).intersection(Set(events)) + } else { + sessionEvents = Set(proposalNamespace.events).symmetricDifference(Set(events)) + } guard !sessionEvents.isEmpty else { return } diff --git a/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift b/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift index af452092d..36f7dcf68 100644 --- a/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift +++ b/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift @@ -799,4 +799,144 @@ final class AutoNamespacesValidationTests: XCTestCase { ) ) } + + func testAutoNamespacesSameChainEmptyOptinalEvents() { + let accounts = [ + Account(blockchain: Blockchain("eip155:1")!, address: "0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")! + ] + let requiredNamespaces = [ + "eip155": ProposalNamespace( + chains: [Blockchain("eip155:1")!], + methods: ["personal_sign", "eth_sendTransaction"], + events: ["chainChanged", "accountsChanged"]) + ] + let optionalNamespaces = [ + "eip155": ProposalNamespace( + chains: [Blockchain("eip155:1")!], + methods: ["eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign"], + events: [] + ) + ] + let sessionProposal = Session.Proposal( + id: "", + pairingTopic: "", + proposer: AppMetadata(name: "", description: "", url: "", icons: []), + requiredNamespaces: requiredNamespaces, + optionalNamespaces: optionalNamespaces, + sessionProperties: nil, + proposal: SessionProposal(relays: [], proposer: Participant(publicKey: "", metadata: AppMetadata(name: "", description: "", url: "", icons: [])), requiredNamespaces: [:], optionalNamespaces: [:], sessionProperties: [:]) + ) + let sessionNamespaces = try! AutoNamespaces.build( + sessionProposal: sessionProposal, + chains: [Blockchain("eip155:1")!], + methods: ["personal_sign", "eth_sendTransaction", "eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign"], + events: ["chainChanged", "accountsChanged"], + accounts: accounts + ) + let expectedNamespaces: [String: SessionNamespace] = [ + "eip155": SessionNamespace( + chains: [Blockchain("eip155:1")!], + accounts: Set([ + Account(blockchain: Blockchain("eip155:1")!, address: "0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")! + ]), + methods: ["eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign", "personal_sign", "eth_sendTransaction"], + events: ["chainChanged", "accountsChanged"] + ) + ] + XCTAssertEqual(sessionNamespaces, expectedNamespaces) + } + + func testAutoNamespacesSameChainEmptyRequiredEvents() { + let accounts = [ + Account(blockchain: Blockchain("eip155:1")!, address: "0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")! + ] + let requiredNamespaces = [ + "eip155": ProposalNamespace( + chains: [Blockchain("eip155:1")!], + methods: ["personal_sign", "eth_sendTransaction"], + events: [] + ) + ] + let optionalNamespaces = [ + "eip155": ProposalNamespace( + chains: [Blockchain("eip155:1")!], + methods: ["eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign"], + events: ["chainChanged", "accountsChanged"] + ) + ] + let sessionProposal = Session.Proposal( + id: "", + pairingTopic: "", + proposer: AppMetadata(name: "", description: "", url: "", icons: []), + requiredNamespaces: requiredNamespaces, + optionalNamespaces: optionalNamespaces, + sessionProperties: nil, + proposal: SessionProposal(relays: [], proposer: Participant(publicKey: "", metadata: AppMetadata(name: "", description: "", url: "", icons: [])), requiredNamespaces: [:], optionalNamespaces: [:], sessionProperties: [:]) + ) + let sessionNamespaces = try! AutoNamespaces.build( + sessionProposal: sessionProposal, + chains: [Blockchain("eip155:1")!], + methods: ["personal_sign", "eth_sendTransaction", "eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign"], + events: ["chainChanged", "accountsChanged"], + accounts: accounts + ) + let expectedNamespaces: [String: SessionNamespace] = [ + "eip155": SessionNamespace( + chains: [Blockchain("eip155:1")!], + accounts: Set([ + Account(blockchain: Blockchain("eip155:1")!, address: "0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")! + ]), + methods: ["eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign", "personal_sign", "eth_sendTransaction"], + events: ["chainChanged", "accountsChanged"] + ) + ] + XCTAssertEqual(sessionNamespaces, expectedNamespaces) + } + + func testAutoNamespacesSameChainEmptyEvents() { + let accounts = [ + Account(blockchain: Blockchain("eip155:1")!, address: "0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")! + ] + let requiredNamespaces = [ + "eip155": ProposalNamespace( + chains: [Blockchain("eip155:1")!], + methods: ["personal_sign", "eth_sendTransaction"], + events: [] + ) + ] + let optionalNamespaces = [ + "eip155": ProposalNamespace( + chains: [Blockchain("eip155:1")!], + methods: ["eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign"], + events: [] + ) + ] + let sessionProposal = Session.Proposal( + id: "", + pairingTopic: "", + proposer: AppMetadata(name: "", description: "", url: "", icons: []), + requiredNamespaces: requiredNamespaces, + optionalNamespaces: optionalNamespaces, + sessionProperties: nil, + proposal: SessionProposal(relays: [], proposer: Participant(publicKey: "", metadata: AppMetadata(name: "", description: "", url: "", icons: [])), requiredNamespaces: [:], optionalNamespaces: [:], sessionProperties: [:]) + ) + let sessionNamespaces = try! AutoNamespaces.build( + sessionProposal: sessionProposal, + chains: [Blockchain("eip155:1")!], + methods: ["personal_sign", "eth_sendTransaction", "eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign"], + events: ["chainChanged", "accountsChanged"], + accounts: accounts + ) + let expectedNamespaces: [String: SessionNamespace] = [ + "eip155": SessionNamespace( + chains: [Blockchain("eip155:1")!], + accounts: Set([ + Account(blockchain: Blockchain("eip155:1")!, address: "0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")! + ]), + methods: ["eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign", "personal_sign", "eth_sendTransaction"], + events: ["chainChanged", "accountsChanged"] + ) + ] + XCTAssertEqual(sessionNamespaces, expectedNamespaces) + } } From e767d4f0109c495f3e72ccec720d170671946727 Mon Sep 17 00:00:00 2001 From: Alexander Lisovik Date: Fri, 30 Jun 2023 11:51:32 +0200 Subject: [PATCH 16/19] Update tests --- Sources/WalletConnectSign/Namespace.swift | 22 +------ .../AutoNamespacesValidationTests.swift | 60 +++++++++++++++++++ 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/Sources/WalletConnectSign/Namespace.swift b/Sources/WalletConnectSign/Namespace.swift index 35529e68b..6de73e1cc 100644 --- a/Sources/WalletConnectSign/Namespace.swift +++ b/Sources/WalletConnectSign/Namespace.swift @@ -265,16 +265,8 @@ public enum AutoNamespaces { guard !sessionMethods.isEmpty else { return } - - var sessionEvents = Set() - if !proposalNamespace.events.isEmpty && !events.isEmpty { - sessionEvents = Set(proposalNamespace.events).intersection(Set(events)) - } else { - sessionEvents = Set(proposalNamespace.events).symmetricDifference(Set(events)) - } - guard !sessionEvents.isEmpty else { - return - } + + let sessionEvents = Set(proposalNamespace.events).intersection(Set(events)) let sessionNamespace = SessionNamespace( chains: sessionChains, @@ -309,15 +301,7 @@ public enum AutoNamespaces { return } - var sessionEvents = Set() - if !proposalNamespace.events.isEmpty && !events.isEmpty { - sessionEvents = Set(proposalNamespace.events).intersection(Set(events)) - } else { - sessionEvents = Set(proposalNamespace.events).symmetricDifference(Set(events)) - } - guard !sessionEvents.isEmpty else { - return - } + let sessionEvents = Set(proposalNamespace.events).intersection(Set(events)) let sessionNamespace = SessionNamespace( chains: Set([Blockchain(namespace: network, reference: chain)!]), diff --git a/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift b/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift index 36f7dcf68..5dd2e2d58 100644 --- a/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift +++ b/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift @@ -927,6 +927,58 @@ final class AutoNamespacesValidationTests: XCTestCase { events: ["chainChanged", "accountsChanged"], accounts: accounts ) + let expectedNamespaces: [String: SessionNamespace] = [ + "eip155": SessionNamespace( + chains: [Blockchain("eip155:1")!], + accounts: Set([ + Account(blockchain: Blockchain("eip155:1")!, address: "0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")! + ]), + methods: ["eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign", "personal_sign", "eth_sendTransaction"], + events: [] + ) + ] + XCTAssertEqual(sessionNamespaces, expectedNamespaces) + } + + func testAutoNamespacesDifferentChainEmptyOptinalEvents() { + let accounts = [ + Account(blockchain: Blockchain("eip155:1")!, address: "0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")!, + Account(blockchain: Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!, address: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")! + ] + let requiredNamespaces = [ + "eip155": ProposalNamespace( + chains: [Blockchain("eip155:1")!], + methods: ["personal_sign", "eth_sendTransaction"], + events: ["chainChanged", "accountsChanged"]) + ] + let optionalNamespaces = [ + "eip155": ProposalNamespace( + chains: [Blockchain("eip155:1")!], + methods: ["eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign"], + events: [] + ), + "solana": ProposalNamespace( + chains: [Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!], + methods: ["solana_signMessage"], + events: [] + ) + ] + let sessionProposal = Session.Proposal( + id: "", + pairingTopic: "", + proposer: AppMetadata(name: "", description: "", url: "", icons: []), + requiredNamespaces: requiredNamespaces, + optionalNamespaces: optionalNamespaces, + sessionProperties: nil, + proposal: SessionProposal(relays: [], proposer: Participant(publicKey: "", metadata: AppMetadata(name: "", description: "", url: "", icons: [])), requiredNamespaces: [:], optionalNamespaces: [:], sessionProperties: [:]) + ) + let sessionNamespaces = try! AutoNamespaces.build( + sessionProposal: sessionProposal, + chains: [Blockchain("eip155:1")!, Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!], + methods: ["personal_sign", "eth_sendTransaction", "eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign", "solana_signMessage", "solana_signMessage"], + events: ["chainChanged", "accountsChanged"], + accounts: accounts + ) let expectedNamespaces: [String: SessionNamespace] = [ "eip155": SessionNamespace( chains: [Blockchain("eip155:1")!], @@ -935,6 +987,14 @@ final class AutoNamespacesValidationTests: XCTestCase { ]), methods: ["eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign", "personal_sign", "eth_sendTransaction"], events: ["chainChanged", "accountsChanged"] + ), + "solana": SessionNamespace( + chains: [Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!], + accounts: Set([ + Account(blockchain: Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!, address: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!, + ]), + methods: ["solana_signMessage"], + events: [] ) ] XCTAssertEqual(sessionNamespaces, expectedNamespaces) From b341e5b65002013aa8c9be9730d853d86da30208 Mon Sep 17 00:00:00 2001 From: Alexander Lisovik Date: Sun, 2 Jul 2023 21:51:31 +0200 Subject: [PATCH 17/19] Update tests --- Tests/WalletConnectSignTests/Stub/Session+Stub.swift | 3 +++ Tests/Web3WalletTests/Mocks/AuthClientMock.swift | 1 + Tests/Web3WalletTests/Mocks/SignClientMock.swift | 9 ++++----- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Tests/WalletConnectSignTests/Stub/Session+Stub.swift b/Tests/WalletConnectSignTests/Stub/Session+Stub.swift index e60b778ec..37fcfdef9 100644 --- a/Tests/WalletConnectSignTests/Stub/Session+Stub.swift +++ b/Tests/WalletConnectSignTests/Stub/Session+Stub.swift @@ -9,6 +9,7 @@ extension WCSession { expiryDate: Date = Date.distantFuture, selfPrivateKey: AgreementPrivateKey = AgreementPrivateKey(), namespaces: [String: SessionNamespace] = [:], + sessionProperties: [String: String] = [:], requiredNamespaces: [String: ProposalNamespace] = [:], acknowledged: Bool = true, timestamp: Date = Date() @@ -25,6 +26,7 @@ extension WCSession { selfParticipant: Participant.stub(publicKey: selfKey), peerParticipant: Participant.stub(publicKey: peerKey), namespaces: namespaces, + sessionProperties: sessionProperties, requiredNamespaces: requiredNamespaces, events: [], accounts: Account.stubSet(), @@ -45,6 +47,7 @@ extension SessionType.SettleParams { relay: RelayProtocolOptions.stub(), controller: Participant.stub(), namespaces: SessionNamespace.stubDictionary(), + sessionProperties: nil, expiry: Int64(Date.distantFuture.timeIntervalSince1970)) } } diff --git a/Tests/Web3WalletTests/Mocks/AuthClientMock.swift b/Tests/Web3WalletTests/Mocks/AuthClientMock.swift index 535ace60a..302d40a53 100644 --- a/Tests/Web3WalletTests/Mocks/AuthClientMock.swift +++ b/Tests/Web3WalletTests/Mocks/AuthClientMock.swift @@ -22,6 +22,7 @@ final class AuthClientMock: AuthClientProtocol { return AuthRequest( id: .left(""), + topic: "", payload: AuthPayload(requestParams: requestParams, iat: "") ) } diff --git a/Tests/Web3WalletTests/Mocks/SignClientMock.swift b/Tests/Web3WalletTests/Mocks/SignClientMock.swift index fec7b51c4..721af0e46 100644 --- a/Tests/Web3WalletTests/Mocks/SignClientMock.swift +++ b/Tests/Web3WalletTests/Mocks/SignClientMock.swift @@ -4,7 +4,6 @@ import Combine @testable import WalletConnectSign final class SignClientMock: SignClientProtocol { - var approveCalled = false var rejectCalled = false var updateCalled = false @@ -41,7 +40,7 @@ final class SignClientMock: SignClientProtocol { } var sessionsPublisher: AnyPublisher<[WalletConnectSign.Session], Never> { - return Result.Publisher([WalletConnectSign.Session(topic: "", pairingTopic: "", peer: metadata, namespaces: [:], expiryDate: Date())]) + return Result.Publisher([WalletConnectSign.Session(topic: "", pairingTopic: "", peer: metadata, requiredNamespaces: [:], namespaces: [:], sessionProperties: nil, expiryDate: Date())]) .eraseToAnyPublisher() } @@ -51,7 +50,7 @@ final class SignClientMock: SignClientProtocol { } var sessionSettlePublisher: AnyPublisher { - return Result.Publisher(Session(topic: "", pairingTopic: "", peer: metadata, namespaces: [:], expiryDate: Date())) + return Result.Publisher(Session(topic: "", pairingTopic: "", peer: metadata, requiredNamespaces: [:], namespaces: [:], sessionProperties: nil, expiryDate: Date())) .eraseToAnyPublisher() } @@ -80,7 +79,7 @@ final class SignClientMock: SignClientProtocol { .eraseToAnyPublisher() } - func approve(proposalId: String, namespaces: [String : WalletConnectSign.SessionNamespace]) async throws { + func approve(proposalId: String, namespaces: [String : WalletConnectSign.SessionNamespace], sessionProperties: [String : String]? = nil) async throws { approveCalled = true } @@ -113,7 +112,7 @@ final class SignClientMock: SignClientProtocol { } func getSessions() -> [WalletConnectSign.Session] { - return [WalletConnectSign.Session(topic: "", pairingTopic: "", peer: metadata, namespaces: [:], expiryDate: Date())] + return [WalletConnectSign.Session(topic: "", pairingTopic: "", peer: metadata, requiredNamespaces: [:], namespaces: [:], sessionProperties: nil, expiryDate: Date())] } func getPendingRequests(topic: String?) -> [WalletConnectSign.Request] { From a0a853a0cb9cf31c26217b790dfe056c2c1b2f98 Mon Sep 17 00:00:00 2001 From: Alexander Lisovik Date: Sun, 2 Jul 2023 21:56:34 +0200 Subject: [PATCH 18/19] Update tests --- Tests/Web3ModalTests/Mocks/ModalSheetInteractorMock.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Web3ModalTests/Mocks/ModalSheetInteractorMock.swift b/Tests/Web3ModalTests/Mocks/ModalSheetInteractorMock.swift index 2197afbaa..171e44574 100644 --- a/Tests/Web3ModalTests/Mocks/ModalSheetInteractorMock.swift +++ b/Tests/Web3ModalTests/Mocks/ModalSheetInteractorMock.swift @@ -28,7 +28,7 @@ final class ModalSheetInteractorMock: ModalSheetInteractor { } var sessionSettlePublisher: AnyPublisher { - Result.Publisher(Session(topic: "", pairingTopic: "", peer: .stub(), namespaces: [:], expiryDate: Date())) + Result.Publisher(Session(topic: "", pairingTopic: "", peer: .stub(), requiredNamespaces: [:], namespaces: [:], sessionProperties: nil, expiryDate: Date())) .eraseToAnyPublisher() } From b4ad15e7617db8816cd2f099f5b9bf8eaa4e0b45 Mon Sep 17 00:00:00 2001 From: alexander-lsvk Date: Mon, 3 Jul 2023 06:30:09 +0000 Subject: [PATCH 19/19] Set User Agent --- Sources/WalletConnectRelay/PackageConfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectRelay/PackageConfig.json b/Sources/WalletConnectRelay/PackageConfig.json index 1aca540e3..eb68828e1 100644 --- a/Sources/WalletConnectRelay/PackageConfig.json +++ b/Sources/WalletConnectRelay/PackageConfig.json @@ -1 +1 @@ -{"version": "1.6.10"} +{"version": "1.6.11"}