From ab2f317f87861665672af493590fc2b2d98e0d3f Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 31 Aug 2023 23:26:28 +0800 Subject: [PATCH 01/91] Networking error publisher --- .../NetworkInteracting.swift | 13 +++ .../NetworkingInteractor.swift | 41 +++++++ .../DeleteNotifySubscriptionSubscriber.swift | 17 ++- .../NotifyMessageSubscriber.swift | 63 +++++------ .../NotifyUpdateResponseSubscriber.swift | 34 +++--- .../NotifySubscribeResponseSubscriber.swift | 104 +++++++++--------- .../NetworkingInteractorMock.swift | 46 ++++++++ 7 files changed, 205 insertions(+), 113 deletions(-) diff --git a/Sources/WalletConnectNetworking/NetworkInteracting.swift b/Sources/WalletConnectNetworking/NetworkInteracting.swift index 54987272c..fc8ee987d 100644 --- a/Sources/WalletConnectNetworking/NetworkInteracting.swift +++ b/Sources/WalletConnectNetworking/NetworkInteracting.swift @@ -27,6 +27,19 @@ public protocol NetworkInteracting { on request: ProtocolMethod ) -> AnyPublisher, Never> + func subscribeOnRequest( + protocolMethod: ProtocolMethod, + requestOfType: RequestParams.Type, + subscription: @escaping (RequestSubscriptionPayload) async throws -> Void + ) + + func subscribeOnResponse( + protocolMethod: ProtocolMethod, + requestOfType: Request.Type, + responseOfType: Response.Type, + subscription: @escaping (ResponseSubscriptionPayload) async throws -> Void + ) + func getClientId() throws -> String } diff --git a/Sources/WalletConnectNetworking/NetworkingInteractor.swift b/Sources/WalletConnectNetworking/NetworkingInteractor.swift index e92cfa3ea..fcc801c1b 100644 --- a/Sources/WalletConnectNetworking/NetworkingInteractor.swift +++ b/Sources/WalletConnectNetworking/NetworkingInteractor.swift @@ -8,6 +8,8 @@ public class NetworkingInteractor: NetworkInteracting { private let rpcHistory: RPCHistory private let logger: ConsoleLogging + private let errorPublisherSubject = PassthroughSubject() + private let requestPublisherSubject = PassthroughSubject<(topic: String, request: RPCRequest, decryptedPayload: Data, publishedAt: Date, derivedTopic: String?), Never>() private let responsePublisherSubject = PassthroughSubject<(topic: String, request: RPCRequest, response: RPCResponse, publishedAt: Date, derivedTopic: String?), Never>() @@ -19,6 +21,10 @@ public class NetworkingInteractor: NetworkInteracting { responsePublisherSubject.eraseToAnyPublisher() } + public var errorPublisher: AnyPublisher { + return errorPublisherSubject.eraseToAnyPublisher() + } + public var logsPublisher: AnyPublisher { logger.logsPublisher .merge(with: serializer.logsPublisher) @@ -84,6 +90,41 @@ public class NetworkingInteractor: NetworkInteracting { rpcHistory.deleteAll(forTopics: topics) } + public func subscribeOnRequest( + protocolMethod: ProtocolMethod, + requestOfType: RequestParams.Type, + subscription: @escaping (RequestSubscriptionPayload) async throws -> Void + ) { + requestSubscription(on: protocolMethod) + .sink { [unowned self] (payload: RequestSubscriptionPayload) in + Task(priority: .high) { + do { + try await subscription(payload) + } catch { + errorPublisherSubject.send(error) + } + } + }.store(in: &publishers) + } + + public func subscribeOnResponse( + protocolMethod: ProtocolMethod, + requestOfType: Request.Type, + responseOfType: Response.Type, + subscription: @escaping (ResponseSubscriptionPayload) async throws -> Void + ) { + responseSubscription(on: protocolMethod) + .sink { [unowned self] (payload: ResponseSubscriptionPayload) in + Task(priority: .high) { + do { + try await subscription(payload) + } catch { + errorPublisherSubject.send(error) + } + } + }.store(in: &publishers) + } + public func requestSubscription(on request: ProtocolMethod) -> AnyPublisher, Never> { return requestPublisher .filter { rpcRequest in diff --git a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionSubscriber.swift b/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionSubscriber.swift index 435ece85f..fa62a8d8e 100644 --- a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionSubscriber.swift @@ -5,7 +5,6 @@ class DeleteNotifySubscriptionSubscriber { private let networkingInteractor: NetworkInteracting private let kms: KeyManagementServiceProtocol private let logger: ConsoleLogging - private var publishers = [AnyCancellable]() private let notifyStorage: NotifyStorage init(networkingInteractor: NetworkInteracting, @@ -21,14 +20,12 @@ class DeleteNotifySubscriptionSubscriber { } private func subscribeForDeleteSubscription() { - let protocolMethod = NotifyDeleteProtocolMethod() - networkingInteractor.requestSubscription(on: protocolMethod) - .sink { [unowned self] (payload: RequestSubscriptionPayload) in - - guard let (_, _) = try? NotifyDeleteResponsePayload.decodeAndVerify(from: payload.request) - else { fatalError() /* TODO: Handle error */ } - - logger.debug("Peer deleted subscription") - }.store(in: &publishers) + networkingInteractor.subscribeOnRequest( + protocolMethod: NotifyDeleteProtocolMethod(), + requestOfType: NotifyDeleteResponsePayload.Wrapper.self + ) { [unowned self] payload in + let (_, _) = try NotifyDeleteResponsePayload.decodeAndVerify(from: payload.request) + logger.debug("Peer deleted subscription") + } } } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift index 957c4df60..a73a49c92 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift @@ -8,7 +8,6 @@ class NotifyMessageSubscriber { private let notifyStorage: NotifyStorage private let crypto: CryptoProvider private let logger: ConsoleLogging - private var publishers = [AnyCancellable]() private let notifyMessagePublisherSubject = PassthroughSubject() public var notifyMessagePublisher: AnyPublisher { @@ -26,45 +25,41 @@ class NotifyMessageSubscriber { } private func subscribeForNotifyMessages() { - let protocolMethod = NotifyMessageProtocolMethod() - networkingInteractor.requestSubscription(on: protocolMethod) - .sink { [unowned self] (payload: RequestSubscriptionPayload) in + networkingInteractor.subscribeOnRequest( + protocolMethod: NotifyMessageProtocolMethod(), + requestOfType: NotifyMessagePayload.Wrapper.self + ) { [unowned self] payload in + logger.debug("Received Notify Message on topic: \(payload.topic)", properties: ["topic": payload.topic]) - logger.debug("Received Notify Message on topic: \(payload.topic)", properties: ["topic": payload.topic]) + let (messagePayload, claims) = try NotifyMessagePayload.decodeAndVerify(from: payload.request) + logger.debug("Decoded Notify Message: \(payload.topic)", properties: ["topic": payload.topic, "messageBody": messagePayload.message.body, "messageTitle": messagePayload.message.title, "publishedAt": payload.publishedAt.description, "id": payload.id.string]) + let dappPubKey = try DIDKey(did: claims.iss) + let messageData = try JSONEncoder().encode(messagePayload.message) - Task(priority: .high) { - let (messagePayload, claims) = try NotifyMessagePayload.decodeAndVerify(from: payload.request) - logger.debug("Decoded Notify Message: \(payload.topic)", properties: ["topic": payload.topic, "messageBody": messagePayload.message.body, "messageTitle": messagePayload.message.title, "publishedAt": payload.publishedAt.description, "id": payload.id.string]) - let dappPubKey = try DIDKey(did: claims.iss) - let messageData = try JSONEncoder().encode(messagePayload.message) + let record = NotifyMessageRecord(id: payload.id.string, topic: payload.topic, message: messagePayload.message, publishedAt: payload.publishedAt) + notifyStorage.setMessage(record) + notifyMessagePublisherSubject.send(record) - let record = NotifyMessageRecord(id: payload.id.string, topic: payload.topic, message: messagePayload.message, publishedAt: payload.publishedAt) - notifyStorage.setMessage(record) - notifyMessagePublisherSubject.send(record) + let receiptPayload = NotifyMessageReceiptPayload( + keyserver: keyserver, dappPubKey: dappPubKey, + messageHash: crypto.keccak256(messageData).toHexString(), + app: messagePayload.app + ) - let receiptPayload = NotifyMessageReceiptPayload( - keyserver: keyserver, dappPubKey: dappPubKey, - messageHash: crypto.keccak256(messageData).toHexString(), - app: messagePayload.app - ) + let wrapper = try identityClient.signAndCreateWrapper( + payload: receiptPayload, + account: messagePayload.account + ) - let wrapper = try identityClient.signAndCreateWrapper( - payload: receiptPayload, - account: messagePayload.account - ) + let response = RPCResponse(id: payload.id, result: wrapper) - let response = RPCResponse(id: payload.id, result: wrapper) - - try await networkingInteractor.respond( - topic: payload.topic, - response: response, - protocolMethod: NotifyMessageProtocolMethod() - ) - - logger.debug("Sent Notify Message Response on topic: \(payload.topic)", properties: ["topic" : payload.topic, "messageBody": messagePayload.message.body, "messageTitle": messagePayload.message.title, "id": payload.id.string, "result": wrapper.jwtString]) - } - - }.store(in: &publishers) + try await networkingInteractor.respond( + topic: payload.topic, + response: response, + protocolMethod: NotifyMessageProtocolMethod() + ) + logger.debug("Sent Notify Message Response on topic: \(payload.topic)", properties: ["topic" : payload.topic, "messageBody": messagePayload.message.body, "messageTitle": messagePayload.message.title, "id": payload.id.string, "result": wrapper.jwtString]) + } } } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift index ce74dea16..fe69ae1dc 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift @@ -30,29 +30,29 @@ private extension NotifyUpdateResponseSubscriber { } func subscribeForUpdateResponse() { - let protocolMethod = NotifyUpdateProtocolMethod() - networkingInteractor.responseSubscription(on: protocolMethod) - .sink {[unowned self] (payload: ResponseSubscriptionPayload) in - Task(priority: .high) { - logger.debug("Received Notify Update response") + networkingInteractor.subscribeOnResponse( + protocolMethod: NotifyUpdateProtocolMethod(), + requestOfType: NotifyUpdatePayload.Wrapper.self, + responseOfType: NotifyUpdateResponsePayload.Wrapper.self + ) { [unowned self] payload in + logger.debug("Received Notify Update response") - let subscriptionTopic = payload.topic + let subscriptionTopic = payload.topic - let (requestPayload, requestClaims) = try NotifyUpdatePayload.decodeAndVerify(from: payload.request) - let (_, _) = try NotifyUpdateResponsePayload.decodeAndVerify(from: payload.response) + let (requestPayload, requestClaims) = try NotifyUpdatePayload.decodeAndVerify(from: payload.request) + let (_, _) = try NotifyUpdateResponsePayload.decodeAndVerify(from: payload.response) - let scope = try await buildScope(selected: requestPayload.scope, dappUrl: requestPayload.dappUrl) + let scope = try await buildScope(selected: requestPayload.scope, dappUrl: requestPayload.dappUrl) - guard let oldSubscription = notifyStorage.getSubscription(topic: subscriptionTopic) else { - logger.debug("NotifyUpdateResponseSubscriber Subscription does not exist") - return - } + guard let oldSubscription = notifyStorage.getSubscription(topic: subscriptionTopic) else { + logger.debug("NotifyUpdateResponseSubscriber Subscription does not exist") + return + } - notifyStorage.updateSubscription(oldSubscription, scope: scope, expiry: requestClaims.exp) + notifyStorage.updateSubscription(oldSubscription, scope: scope, expiry: requestClaims.exp) - logger.debug("Updated Subscription") - } - }.store(in: &publishers) + logger.debug("Updated Subscription") + } } func buildScope(selected: String, dappUrl: String) async throws -> [String: ScopeValue] { diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift index b663aaa14..28b3e8c56 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift @@ -40,65 +40,65 @@ class NotifySubscribeResponseSubscriber { } private func subscribeForSubscriptionResponse() { - let protocolMethod = NotifySubscribeProtocolMethod() - networkingInteractor.responseSubscription(on: protocolMethod) - .sink { [unowned self] (payload: ResponseSubscriptionPayload) in - Task(priority: .high) { - logger.debug("Received Notify Subscribe response") + networkingInteractor.subscribeOnResponse( + protocolMethod: NotifySubscribeProtocolMethod(), + requestOfType: NotifySubscriptionPayload.Wrapper.self, + responseOfType: NotifySubscriptionResponsePayload.Wrapper.self + ) { [unowned self] payload in + logger.debug("Received Notify Subscribe response") - guard - let (responsePayload, _) = try? NotifySubscriptionResponsePayload.decodeAndVerify(from: payload.response) - else { fatalError() /* TODO: Handle error */ } + guard + let (responsePayload, _) = try? NotifySubscriptionResponsePayload.decodeAndVerify(from: payload.response) + else { fatalError() /* TODO: Handle error */ } - guard let responseKeys = kms.getAgreementSecret(for: payload.topic) else { - logger.debug("No symmetric key for topic \(payload.topic)") - return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) - } + guard let responseKeys = kms.getAgreementSecret(for: payload.topic) else { + logger.debug("No symmetric key for topic \(payload.topic)") + return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) + } - // get keypair Y - let pubKeyY = responseKeys.publicKey - let peerPubKeyZ = responsePayload.publicKey.hexString + // get keypair Y + let pubKeyY = responseKeys.publicKey + let peerPubKeyZ = responsePayload.publicKey.hexString - var account: Account! - var metadata: AppMetadata! - var notifySubscriptionTopic: String! - var subscribedTypes: Set! - var agreementKeysP: AgreementKeys! - let (subscriptionPayload, claims) = try NotifySubscriptionPayload.decodeAndVerify(from: payload.request) - let subscribedScope = subscriptionPayload.scope - .components(separatedBy: " ") - do { - // generate symm key P - agreementKeysP = try kms.performKeyAgreement(selfPublicKey: pubKeyY, peerPublicKey: peerPubKeyZ) - notifySubscriptionTopic = agreementKeysP.derivedTopic() - try kms.setAgreementSecret(agreementKeysP, topic: notifySubscriptionTopic) - try groupKeychainStorage.add(agreementKeysP, forKey: notifySubscriptionTopic) - account = try Account(DIDPKHString: claims.sub) - metadata = try dappsMetadataStore.get(key: payload.topic) - let availableTypes = try await subscriptionScopeProvider.getSubscriptionScope(dappUrl: metadata!.url) - subscribedTypes = availableTypes.filter{subscribedScope.contains($0.name)} - logger.debug("subscribing notify subscription topic: \(notifySubscriptionTopic!)") - try await networkingInteractor.subscribe(topic: notifySubscriptionTopic) - } catch { - logger.debug("error: \(error)") - return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) - } + var account: Account! + var metadata: AppMetadata! + var notifySubscriptionTopic: String! + var subscribedTypes: Set! + var agreementKeysP: AgreementKeys! + let (subscriptionPayload, claims) = try NotifySubscriptionPayload.decodeAndVerify(from: payload.request) + let subscribedScope = subscriptionPayload.scope + .components(separatedBy: " ") + do { + // generate symm key P + agreementKeysP = try kms.performKeyAgreement(selfPublicKey: pubKeyY, peerPublicKey: peerPubKeyZ) + notifySubscriptionTopic = agreementKeysP.derivedTopic() + try kms.setAgreementSecret(agreementKeysP, topic: notifySubscriptionTopic) + try groupKeychainStorage.add(agreementKeysP, forKey: notifySubscriptionTopic) + account = try Account(DIDPKHString: claims.sub) + metadata = try dappsMetadataStore.get(key: payload.topic) + let availableTypes = try await subscriptionScopeProvider.getSubscriptionScope(dappUrl: metadata!.url) + subscribedTypes = availableTypes.filter{subscribedScope.contains($0.name)} + logger.debug("NotifySubscribeResponseSubscriber: subscribing notify subscription topic: \(notifySubscriptionTopic!)") + try await networkingInteractor.subscribe(topic: notifySubscriptionTopic) + } catch { + logger.debug("NotifySubscribeResponseSubscriber: error: \(error)") + return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) + } - guard let metadata = metadata else { - logger.debug("No metadata for topic: \(notifySubscriptionTopic!)") - 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 notifySubscription = NotifySubscription(topic: notifySubscriptionTopic, account: account, relay: RelayProtocolOptions(protocol: "irn", data: nil), metadata: metadata, scope: scope, expiry: expiry, symKey: agreementKeysP.sharedKey.hexRepresentation) + guard let metadata = metadata else { + logger.debug("NotifySubscribeResponseSubscriber: no metadata for topic: \(notifySubscriptionTopic!)") + 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 notifySubscription = NotifySubscription(topic: notifySubscriptionTopic, account: account, relay: RelayProtocolOptions(protocol: "irn", data: nil), metadata: metadata, scope: scope, expiry: expiry, symKey: agreementKeysP.sharedKey.hexRepresentation) - notifyStorage.setSubscription(notifySubscription) + try await notifyStorage.setSubscription(notifySubscription) - logger.debug("Unsubscribing response topic: \(payload.topic)") - networkingInteractor.unsubscribe(topic: payload.topic) - } - }.store(in: &publishers) + logger.debug("NotifySubscribeResponseSubscriber: unsubscribing response topic: \(payload.topic)") + networkingInteractor.unsubscribe(topic: payload.topic) + } } // TODO: handle error response diff --git a/Tests/TestingUtils/NetworkingInteractorMock.swift b/Tests/TestingUtils/NetworkingInteractorMock.swift index 8764e7675..d2dee362e 100644 --- a/Tests/TestingUtils/NetworkingInteractorMock.swift +++ b/Tests/TestingUtils/NetworkingInteractorMock.swift @@ -6,6 +6,9 @@ import WalletConnectKMS import WalletConnectNetworking public class NetworkingInteractorMock: NetworkInteracting { + + private var publishers = Set() + private(set) var subscriptions: [String] = [] private(set) var unsubscriptions: [String] = [] @@ -46,6 +49,12 @@ public class NetworkingInteractorMock: NetworkInteracting { responsePublisherSubject.eraseToAnyPublisher() } + private let errorPublisherSubject = PassthroughSubject() + + public var errorPublisher: AnyPublisher { + return errorPublisherSubject.eraseToAnyPublisher() + } + // TODO: Avoid copy paste from NetworkInteractor public func requestSubscription(on request: ProtocolMethod) -> AnyPublisher, Never> { return requestPublisher @@ -86,6 +95,43 @@ public class NetworkingInteractorMock: NetworkInteracting { .eraseToAnyPublisher() } + // TODO: Avoid copy paste from NetworkInteractor + public func subscribeOnRequest( + protocolMethod: ProtocolMethod, + requestOfType: RequestParams.Type, + subscription: @escaping (RequestSubscriptionPayload) async throws -> Void + ) { + requestSubscription(on: protocolMethod) + .sink { [unowned self] (payload: RequestSubscriptionPayload) in + Task(priority: .high) { + do { + try await subscription(payload) + } catch { + errorPublisherSubject.send(error) + } + } + }.store(in: &publishers) + } + + // TODO: Avoid copy paste from NetworkInteractor + public func subscribeOnResponse( + protocolMethod: ProtocolMethod, + requestOfType: Request.Type, + responseOfType: Response.Type, + subscription: @escaping (ResponseSubscriptionPayload) async throws -> Void + ) { + responseSubscription(on: protocolMethod) + .sink { [unowned self] (payload: ResponseSubscriptionPayload) in + Task(priority: .high) { + do { + try await subscription(payload) + } catch { + errorPublisherSubject.send(error) + } + } + }.store(in: &publishers) + } + public func subscribe(topic: String) async throws { defer { onSubscribeCalled?() } subscriptions.append(topic) From d998b2f71aa98f178af21affdc03953b1a500a3a Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 4 Sep 2023 20:50:58 +0800 Subject: [PATCH 02/91] Unused removed --- .../Client/Wallet/NotifyClient.swift | 4 ---- .../NotifySubscribeResponseSubscriber.swift | 14 ++++---------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 8065dfa78..00aed991d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -10,10 +10,6 @@ public class NotifyClient { return notifyStorage.newSubscriptionPublisher } - public var subscriptionErrorPublisher: AnyPublisher { - return notifySubscribeResponseSubscriber.subscriptionErrorPublisher - } - public var deleteSubscriptionPublisher: AnyPublisher { return notifyStorage.deleteSubscriptionPublisher } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift index 28b3e8c56..ed096fe4c 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift @@ -6,12 +6,6 @@ class NotifySubscribeResponseSubscriber { case couldNotCreateSubscription } - private let subscriptionErrorSubject = PassthroughSubject() - - var subscriptionErrorPublisher: AnyPublisher { - return subscriptionErrorSubject.eraseToAnyPublisher() - } - private let networkingInteractor: NetworkInteracting private let kms: KeyManagementServiceProtocol private var publishers = [AnyCancellable]() @@ -53,7 +47,7 @@ class NotifySubscribeResponseSubscriber { guard let responseKeys = kms.getAgreementSecret(for: payload.topic) else { logger.debug("No symmetric key for topic \(payload.topic)") - return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) + throw Errors.couldNotCreateSubscription } // get keypair Y @@ -82,19 +76,19 @@ class NotifySubscribeResponseSubscriber { try await networkingInteractor.subscribe(topic: notifySubscriptionTopic) } catch { logger.debug("NotifySubscribeResponseSubscriber: error: \(error)") - return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) + throw Errors.couldNotCreateSubscription } guard let metadata = metadata else { logger.debug("NotifySubscribeResponseSubscriber: no metadata for topic: \(notifySubscriptionTopic!)") - return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) + throw 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 notifySubscription = NotifySubscription(topic: notifySubscriptionTopic, account: account, relay: RelayProtocolOptions(protocol: "irn", data: nil), metadata: metadata, scope: scope, expiry: expiry, symKey: agreementKeysP.sharedKey.hexRepresentation) - try await notifyStorage.setSubscription(notifySubscription) + notifyStorage.setSubscription(notifySubscription) logger.debug("NotifySubscribeResponseSubscriber: unsubscribing response topic: \(payload.topic)") networkingInteractor.unsubscribe(topic: payload.topic) From 700d65c1c7bd95012577ca02888cd786fd24784e Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 4 Sep 2023 22:23:04 +0800 Subject: [PATCH 03/91] errorPublisher into public protocol --- Sources/WalletConnectNetworking/NetworkingClient.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/WalletConnectNetworking/NetworkingClient.swift b/Sources/WalletConnectNetworking/NetworkingClient.swift index e7c7fcd76..81313a256 100644 --- a/Sources/WalletConnectNetworking/NetworkingClient.swift +++ b/Sources/WalletConnectNetworking/NetworkingClient.swift @@ -3,7 +3,8 @@ import Combine public protocol NetworkingClient { var socketConnectionStatusPublisher: AnyPublisher { get } - var logsPublisher: AnyPublisher {get} + var logsPublisher: AnyPublisher { get } + var errorPublisher: AnyPublisher { get } func setLogging(level: LoggingLevel) func connect() throws func disconnect(closeCode: URLSessionWebSocketTask.CloseCode) throws From e4d8ec8559e4234f8c179891c08411e67ac7ff3a Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 6 Sep 2023 23:58:54 +0800 Subject: [PATCH 04/91] Error handler as param --- .../NetworkInteracting.swift | 2 ++ .../NetworkingClient.swift | 1 - .../NetworkingInteractor.swift | 16 ++++++---------- .../DeleteNotifySubscriptionSubscriber.swift | 3 ++- .../NotifyMessageSubscriber.swift | 3 ++- .../NotifyUpdateResponseSubscriber.swift | 3 ++- .../NotifySubscribeResponseSubscriber.swift | 3 ++- .../Logger/ConsoleLogger.swift | 8 ++++++-- .../WalletConnectUtils/Logger/ErrorHandler.swift | 5 +++++ .../TestingUtils/NetworkingInteractorMock.swift | 10 ++++++---- 10 files changed, 33 insertions(+), 21 deletions(-) create mode 100644 Sources/WalletConnectUtils/Logger/ErrorHandler.swift diff --git a/Sources/WalletConnectNetworking/NetworkInteracting.swift b/Sources/WalletConnectNetworking/NetworkInteracting.swift index fc8ee987d..6bad90646 100644 --- a/Sources/WalletConnectNetworking/NetworkInteracting.swift +++ b/Sources/WalletConnectNetworking/NetworkInteracting.swift @@ -30,6 +30,7 @@ public protocol NetworkInteracting { func subscribeOnRequest( protocolMethod: ProtocolMethod, requestOfType: RequestParams.Type, + errorHandler: ErrorHandler?, subscription: @escaping (RequestSubscriptionPayload) async throws -> Void ) @@ -37,6 +38,7 @@ public protocol NetworkInteracting { protocolMethod: ProtocolMethod, requestOfType: Request.Type, responseOfType: Response.Type, + errorHandler: ErrorHandler?, subscription: @escaping (ResponseSubscriptionPayload) async throws -> Void ) diff --git a/Sources/WalletConnectNetworking/NetworkingClient.swift b/Sources/WalletConnectNetworking/NetworkingClient.swift index 81313a256..f8b782c03 100644 --- a/Sources/WalletConnectNetworking/NetworkingClient.swift +++ b/Sources/WalletConnectNetworking/NetworkingClient.swift @@ -4,7 +4,6 @@ import Combine public protocol NetworkingClient { var socketConnectionStatusPublisher: AnyPublisher { get } var logsPublisher: AnyPublisher { get } - var errorPublisher: AnyPublisher { get } func setLogging(level: LoggingLevel) func connect() throws func disconnect(closeCode: URLSessionWebSocketTask.CloseCode) throws diff --git a/Sources/WalletConnectNetworking/NetworkingInteractor.swift b/Sources/WalletConnectNetworking/NetworkingInteractor.swift index fcc801c1b..cb48e6d47 100644 --- a/Sources/WalletConnectNetworking/NetworkingInteractor.swift +++ b/Sources/WalletConnectNetworking/NetworkingInteractor.swift @@ -8,8 +8,6 @@ public class NetworkingInteractor: NetworkInteracting { private let rpcHistory: RPCHistory private let logger: ConsoleLogging - private let errorPublisherSubject = PassthroughSubject() - private let requestPublisherSubject = PassthroughSubject<(topic: String, request: RPCRequest, decryptedPayload: Data, publishedAt: Date, derivedTopic: String?), Never>() private let responsePublisherSubject = PassthroughSubject<(topic: String, request: RPCRequest, response: RPCResponse, publishedAt: Date, derivedTopic: String?), Never>() @@ -21,10 +19,6 @@ public class NetworkingInteractor: NetworkInteracting { responsePublisherSubject.eraseToAnyPublisher() } - public var errorPublisher: AnyPublisher { - return errorPublisherSubject.eraseToAnyPublisher() - } - public var logsPublisher: AnyPublisher { logger.logsPublisher .merge(with: serializer.logsPublisher) @@ -93,15 +87,16 @@ public class NetworkingInteractor: NetworkInteracting { public func subscribeOnRequest( protocolMethod: ProtocolMethod, requestOfType: RequestParams.Type, + errorHandler: ErrorHandler?, subscription: @escaping (RequestSubscriptionPayload) async throws -> Void ) { requestSubscription(on: protocolMethod) - .sink { [unowned self] (payload: RequestSubscriptionPayload) in + .sink { (payload: RequestSubscriptionPayload) in Task(priority: .high) { do { try await subscription(payload) } catch { - errorPublisherSubject.send(error) + errorHandler?.handle(error: error) } } }.store(in: &publishers) @@ -111,15 +106,16 @@ public class NetworkingInteractor: NetworkInteracting { protocolMethod: ProtocolMethod, requestOfType: Request.Type, responseOfType: Response.Type, + errorHandler: ErrorHandler?, subscription: @escaping (ResponseSubscriptionPayload) async throws -> Void ) { responseSubscription(on: protocolMethod) - .sink { [unowned self] (payload: ResponseSubscriptionPayload) in + .sink { (payload: ResponseSubscriptionPayload) in Task(priority: .high) { do { try await subscription(payload) } catch { - errorPublisherSubject.send(error) + errorHandler?.handle(error: error) } } }.store(in: &publishers) diff --git a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionSubscriber.swift b/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionSubscriber.swift index fa62a8d8e..2ae697d7d 100644 --- a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionSubscriber.swift @@ -22,7 +22,8 @@ class DeleteNotifySubscriptionSubscriber { private func subscribeForDeleteSubscription() { networkingInteractor.subscribeOnRequest( protocolMethod: NotifyDeleteProtocolMethod(), - requestOfType: NotifyDeleteResponsePayload.Wrapper.self + requestOfType: NotifyDeleteResponsePayload.Wrapper.self, + errorHandler: logger ) { [unowned self] payload in let (_, _) = try NotifyDeleteResponsePayload.decodeAndVerify(from: payload.request) logger.debug("Peer deleted subscription") diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift index a73a49c92..5763c4b05 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift @@ -27,7 +27,8 @@ class NotifyMessageSubscriber { private func subscribeForNotifyMessages() { networkingInteractor.subscribeOnRequest( protocolMethod: NotifyMessageProtocolMethod(), - requestOfType: NotifyMessagePayload.Wrapper.self + requestOfType: NotifyMessagePayload.Wrapper.self, + errorHandler: logger ) { [unowned self] payload in logger.debug("Received Notify Message on topic: \(payload.topic)", properties: ["topic": payload.topic]) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift index fe69ae1dc..2b489618b 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift @@ -33,7 +33,8 @@ private extension NotifyUpdateResponseSubscriber { networkingInteractor.subscribeOnResponse( protocolMethod: NotifyUpdateProtocolMethod(), requestOfType: NotifyUpdatePayload.Wrapper.self, - responseOfType: NotifyUpdateResponsePayload.Wrapper.self + responseOfType: NotifyUpdateResponsePayload.Wrapper.self, + errorHandler: logger ) { [unowned self] payload in logger.debug("Received Notify Update response") diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift index ed096fe4c..3642d3420 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift @@ -37,7 +37,8 @@ class NotifySubscribeResponseSubscriber { networkingInteractor.subscribeOnResponse( protocolMethod: NotifySubscribeProtocolMethod(), requestOfType: NotifySubscriptionPayload.Wrapper.self, - responseOfType: NotifySubscriptionResponsePayload.Wrapper.self + responseOfType: NotifySubscriptionResponsePayload.Wrapper.self, + errorHandler: logger ) { [unowned self] payload in logger.debug("Received Notify Subscribe response") diff --git a/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift b/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift index f87f2dfef..e63e8945a 100644 --- a/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift +++ b/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift @@ -1,7 +1,7 @@ import Foundation import Combine -public protocol ConsoleLogging { +public protocol ConsoleLogging: ErrorHandler { var logsPublisher: AnyPublisher { get } func debug(_ items: Any..., file: String, function: String, line: Int, properties: [String: String]?) func info(_ items: Any..., file: String, function: String, line: Int) @@ -104,9 +104,11 @@ extension ConsoleLogger: ConsoleLogging { } } + public func handle(error: Error) { + debug(error.localizedDescription) + } } - #if DEBUG public struct ConsoleLoggerMock: ConsoleLogging { public var logsPublisher: AnyPublisher { @@ -121,6 +123,8 @@ public struct ConsoleLoggerMock: ConsoleLogging { public func error(_ items: Any..., file: String, function: String, line: Int) { } public func setLogging(level: LoggingLevel) { } + + public func handle(error: Error) { } } #endif diff --git a/Sources/WalletConnectUtils/Logger/ErrorHandler.swift b/Sources/WalletConnectUtils/Logger/ErrorHandler.swift new file mode 100644 index 000000000..daf1ac009 --- /dev/null +++ b/Sources/WalletConnectUtils/Logger/ErrorHandler.swift @@ -0,0 +1,5 @@ +import Foundation + +public protocol ErrorHandler { + func handle(error: Error) +} diff --git a/Tests/TestingUtils/NetworkingInteractorMock.swift b/Tests/TestingUtils/NetworkingInteractorMock.swift index d2dee362e..27fa35a5c 100644 --- a/Tests/TestingUtils/NetworkingInteractorMock.swift +++ b/Tests/TestingUtils/NetworkingInteractorMock.swift @@ -99,15 +99,16 @@ public class NetworkingInteractorMock: NetworkInteracting { public func subscribeOnRequest( protocolMethod: ProtocolMethod, requestOfType: RequestParams.Type, + errorHandler: ErrorHandler?, subscription: @escaping (RequestSubscriptionPayload) async throws -> Void ) { requestSubscription(on: protocolMethod) - .sink { [unowned self] (payload: RequestSubscriptionPayload) in + .sink { (payload: RequestSubscriptionPayload) in Task(priority: .high) { do { try await subscription(payload) } catch { - errorPublisherSubject.send(error) + errorHandler?.handle(error: error) } } }.store(in: &publishers) @@ -118,15 +119,16 @@ public class NetworkingInteractorMock: NetworkInteracting { protocolMethod: ProtocolMethod, requestOfType: Request.Type, responseOfType: Response.Type, + errorHandler: ErrorHandler?, subscription: @escaping (ResponseSubscriptionPayload) async throws -> Void ) { responseSubscription(on: protocolMethod) - .sink { [unowned self] (payload: ResponseSubscriptionPayload) in + .sink { (payload: ResponseSubscriptionPayload) in Task(priority: .high) { do { try await subscription(payload) } catch { - errorPublisherSubject.send(error) + errorHandler?.handle(error: error) } } }.store(in: &publishers) From b8da2936b5a40466d56926fed7a1a3d00a406229 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 8 Sep 2023 16:14:33 +0800 Subject: [PATCH 05/91] call error --- Sources/WalletConnectUtils/Logger/ConsoleLogger.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift b/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift index e63e8945a..bfd5ccd26 100644 --- a/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift +++ b/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift @@ -105,7 +105,7 @@ extension ConsoleLogger: ConsoleLogging { } public func handle(error: Error) { - debug(error.localizedDescription) + self.error(error.localizedDescription) } } From ad78b173dc0d71ea127450dea9194299b79fbf53 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 8 Sep 2023 23:15:36 +0800 Subject: [PATCH 06/91] OnSign callback removed from client --- Example/IntegrationTests/Push/NotifyTests.swift | 6 +++--- .../WalletConnectNotify/Client/Wallet/NotifyClient.swift | 4 ++-- .../wc_pushSubscribe/NotifySubscribeRequester.swift | 2 +- Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index 965c56f5a..ff358cb99 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -103,7 +103,7 @@ final class NotifyTests: XCTestCase { }.store(in: &publishers) try! await walletNotifyClient.register(account: account, onSign: sign) - try! await walletNotifyClient.subscribe(metadata: metadata, account: account, onSign: sign) + try! await walletNotifyClient.subscribe(metadata: metadata, account: account) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } @@ -113,7 +113,7 @@ final class NotifyTests: XCTestCase { let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) let updateScope: Set = ["alerts"] try! await walletNotifyClient.register(account: account, onSign: sign) - try! await walletNotifyClient.subscribe(metadata: metadata, account: account, onSign: sign) + try! await walletNotifyClient.subscribe(metadata: metadata, account: account) walletNotifyClient.newSubscriptionPublisher .sink { [unowned self] subscription in Task(priority: .high) { @@ -142,7 +142,7 @@ final class NotifyTests: XCTestCase { let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) try! await walletNotifyClient.register(account: account, onSign: sign) - try! await walletNotifyClient.subscribe(metadata: metadata, account: account, onSign: sign) + try! await walletNotifyClient.subscribe(metadata: metadata, account: account) walletNotifyClient.newSubscriptionPublisher .sink { subscription in diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 00aed991d..96fa0374d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -85,8 +85,8 @@ public class NotifyClient { logger.setLogging(level: level) } - public func subscribe(metadata: AppMetadata, account: Account, onSign: @escaping SigningCallback) async throws { - try await notifySubscribeRequester.subscribe(metadata: metadata, account: account, onSign: onSign) + public func subscribe(metadata: AppMetadata, account: Account) async throws { + try await notifySubscribeRequester.subscribe(metadata: metadata, account: account) } public func update(topic: String, scope: Set) async throws { diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift index 7a77693ed..b6f6b7470 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift @@ -35,7 +35,7 @@ class NotifySubscribeRequester { self.dappsMetadataStore = dappsMetadataStore } - @discardableResult func subscribe(metadata: AppMetadata, account: Account, onSign: @escaping SigningCallback) async throws -> NotifySubscriptionPayload.Wrapper { + @discardableResult func subscribe(metadata: AppMetadata, account: Account) async throws -> NotifySubscriptionPayload.Wrapper { let dappUrl = metadata.url diff --git a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift index 4a2a39138..51481a2b7 100644 --- a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift +++ b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift @@ -25,7 +25,7 @@ final class NotifyClientProxy { try await respond(request: request) case .subscribe: let params = try parse(SubscribeRequest.self, params: request.params) - try await client.subscribe(metadata: params.metadata, account: params.account, onSign: onSign) + try await client.subscribe(metadata: params.metadata, account: params.account) try await respond(request: request) case .getActiveSubscriptions: let subscriptions = client.getActiveSubscriptions() From d042af5ef1884b214537986e4b0ecb411255f02f Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Sun, 10 Sep 2023 22:31:04 +0800 Subject: [PATCH 07/91] Inject group ID --- Example/PNDecryptionService/NotificationService.swift | 2 +- .../WalletApp/ApplicationLayer/ConfigurationService.swift | 1 + .../Client/Common/NotifyDecryptionService.swift | 4 ++-- .../Client/Wallet/NotifyClientFactory.swift | 4 ++-- Sources/WalletConnectNotify/Notify.swift | 5 +++-- Sources/WalletConnectNotify/NotifyConfig.swift | 1 + Sources/Web3Inbox/Web3Inbox.swift | 3 ++- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Example/PNDecryptionService/NotificationService.swift b/Example/PNDecryptionService/NotificationService.swift index abf6473c2..21da33666 100644 --- a/Example/PNDecryptionService/NotificationService.swift +++ b/Example/PNDecryptionService/NotificationService.swift @@ -15,7 +15,7 @@ class NotificationService: UNNotificationServiceExtension { let ciphertext = bestAttemptContent.userInfo["blob"] as! String NSLog("Push decryption, topic=%@", topic) do { - let service = NotifyDecryptionService() + let service = NotifyDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") let pushMessage = try service.decryptMessage(topic: topic, ciphertext: ciphertext) bestAttemptContent.title = pushMessage.title bestAttemptContent.body = pushMessage.body diff --git a/Example/WalletApp/ApplicationLayer/ConfigurationService.swift b/Example/WalletApp/ApplicationLayer/ConfigurationService.swift index 5aa30d797..225848c93 100644 --- a/Example/WalletApp/ApplicationLayer/ConfigurationService.swift +++ b/Example/WalletApp/ApplicationLayer/ConfigurationService.swift @@ -22,6 +22,7 @@ final class ConfigurationService { account: importAccount.account, bip44: DefaultBIP44Provider(), config: [.chatEnabled: false, .settingsEnabled: false], + groupIdentifier: "group.com.walletconnect.sdk", environment: BuildConfiguration.shared.apnsEnvironment, crypto: DefaultCryptoProvider(), onSign: importAccount.onSign diff --git a/Sources/WalletConnectNotify/Client/Common/NotifyDecryptionService.swift b/Sources/WalletConnectNotify/Client/Common/NotifyDecryptionService.swift index 5fe116af5..7931911ed 100644 --- a/Sources/WalletConnectNotify/Client/Common/NotifyDecryptionService.swift +++ b/Sources/WalletConnectNotify/Client/Common/NotifyDecryptionService.swift @@ -10,8 +10,8 @@ public class NotifyDecryptionService { self.serializer = serializer } - public init() { - let keychainStorage = GroupKeychainStorage(serviceIdentifier: "group.com.walletconnect.sdk") + public init(groupIdentifier: String) { + let keychainStorage = GroupKeychainStorage(serviceIdentifier: groupIdentifier) let kms = KeyManagementService(keychain: keychainStorage) self.serializer = Serializer(kms: kms, logger: ConsoleLogger(prefix: "🔐", loggingLevel: .off)) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index cb77bce9a..436cb724d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -2,12 +2,12 @@ import Foundation public struct NotifyClientFactory { - public static func create(networkInteractor: NetworkInteracting, pairingRegisterer: PairingRegisterer, pushClient: PushClient, crypto: CryptoProvider) -> NotifyClient { + public static func create(groupIdentifier: String, networkInteractor: NetworkInteracting, pairingRegisterer: PairingRegisterer, pushClient: PushClient, crypto: CryptoProvider) -> NotifyClient { let logger = ConsoleLogger(prefix: "🔔",loggingLevel: .debug) let keyValueStorage = UserDefaults.standard let keyserverURL = URL(string: "https://keys.walletconnect.com")! let keychainStorage = KeychainStorage(serviceIdentifier: "com.walletconnect.sdk") - let groupKeychainService = GroupKeychainStorage(serviceIdentifier: "group.com.walletconnect.sdk") + let groupKeychainService = GroupKeychainStorage(serviceIdentifier: groupIdentifier) return NotifyClientFactory.create( keyserverURL: keyserverURL, diff --git a/Sources/WalletConnectNotify/Notify.swift b/Sources/WalletConnectNotify/Notify.swift index 3a8a0bb14..9b258d89f 100644 --- a/Sources/WalletConnectNotify/Notify.swift +++ b/Sources/WalletConnectNotify/Notify.swift @@ -7,6 +7,7 @@ public class Notify { } Push.configure(pushHost: config.pushHost, environment: config.environment) return NotifyClientFactory.create( + groupIdentifier: config.groupIdentifier, networkInteractor: Networking.interactor, pairingRegisterer: Pair.registerer, pushClient: Push.instance, @@ -19,8 +20,8 @@ public class Notify { private init() { } /// Wallet's configuration method - static public func configure(pushHost: String = "echo.walletconnect.com", environment: APNSEnvironment, crypto: CryptoProvider) { - Notify.config = Notify.Config(pushHost: pushHost, environment: environment, crypto: crypto) + static public func configure(pushHost: String = "echo.walletconnect.com", groupIdentifier: String, environment: APNSEnvironment, crypto: CryptoProvider) { + Notify.config = Notify.Config(pushHost: pushHost, groupIdentifier: groupIdentifier, environment: environment, crypto: crypto) } } diff --git a/Sources/WalletConnectNotify/NotifyConfig.swift b/Sources/WalletConnectNotify/NotifyConfig.swift index 479c830ab..977f024f3 100644 --- a/Sources/WalletConnectNotify/NotifyConfig.swift +++ b/Sources/WalletConnectNotify/NotifyConfig.swift @@ -3,6 +3,7 @@ import Foundation extension Notify { struct Config { let pushHost: String + let groupIdentifier: String let environment: APNSEnvironment let crypto: CryptoProvider } diff --git a/Sources/Web3Inbox/Web3Inbox.swift b/Sources/Web3Inbox/Web3Inbox.swift index 17bbc7f55..17b139665 100644 --- a/Sources/Web3Inbox/Web3Inbox.swift +++ b/Sources/Web3Inbox/Web3Inbox.swift @@ -21,6 +21,7 @@ public final class Web3Inbox { account: Account, bip44: BIP44Provider, config: [ConfigParam: Bool] = [:], + groupIdentifier: String, environment: APNSEnvironment, crypto: CryptoProvider, onSign: @escaping SigningCallback @@ -29,6 +30,6 @@ public final class Web3Inbox { Web3Inbox.config = config Web3Inbox.onSign = onSign Chat.configure(bip44: bip44) - Notify.configure(environment: environment, crypto: crypto) + Notify.configure(groupIdentifier: groupIdentifier, environment: environment, crypto: crypto) } } From f0b4c3ccd879963f1b36a6300dac55adf0b998a2 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 6 Sep 2023 12:59:54 +0200 Subject: [PATCH 08/91] Add NotifyWatchSubscriptionsRequester --- .../DeleteNotifySubscriptionService.swift | 8 +- .../NotifyUpdateRequester.swift | 4 +- .../NotifyWatchSubscriptionsRequester.swift | 79 +++++++++++++++++++ ...WatchSubscriptionsResponseSubscriber.swift | 2 + .../NotifySubscribeRequester.swift | 6 +- .../Client/Wallet/WebDidResolver.swift | 18 ++++- .../ProtocolMethods/File.swift | 11 +++ .../NotifyWatchSubscriptionsPayload.swift | 66 ++++++++++++++++ 8 files changed, 185 insertions(+), 9 deletions(-) create mode 100644 Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift create mode 100644 Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift create mode 100644 Sources/WalletConnectNotify/ProtocolMethods/File.swift create mode 100644 Sources/WalletConnectNotify/Types/Payload/NotifyWatchSubscriptionsPayload.swift diff --git a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift b/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift index fc4a361fd..0ddfefbdd 100644 --- a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift +++ b/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift @@ -37,10 +37,10 @@ class DeleteNotifySubscriptionService { else { throw Errors.notifySubscriptionNotFound} let protocolMethod = NotifyDeleteProtocolMethod() - let dappPubKey = try await webDidResolver.resolvePublicKey(dappUrl: subscription.metadata.url) + let dappAuthenticationKey = try await webDidResolver.resolveAuthenticationKey(domain: subscription.metadata.url) let wrapper = try createJWTWrapper( - dappPubKey: DIDKey(rawData: dappPubKey.rawRepresentation), + dappPubKey: DIDKey(rawData: dappAuthenticationKey), reason: NotifyDeleteParams.userDisconnected.message, app: subscription.metadata.url, account: subscription.account @@ -58,6 +58,10 @@ class DeleteNotifySubscriptionService { kms.deleteSymmetricKey(for: topic) } + + + + } private extension DeleteNotifySubscriptionService { diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift index 8f4c8a103..21c3c87c0 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift @@ -40,10 +40,10 @@ class NotifyUpdateRequester: NotifyUpdateRequesting { guard let subscription = notifyStorage.getSubscription(topic: topic) else { throw Errors.noSubscriptionForGivenTopic } - let dappPubKey = try await webDidResolver.resolvePublicKey(dappUrl: subscription.metadata.url) + let dappAuthenticationKey = try await webDidResolver.resolveAuthenticationKey(domain: subscription.metadata.url) let request = try createJWTRequest( - dappPubKey: DIDKey(rawData: dappPubKey.rawRepresentation), + dappPubKey: DIDKey(rawData: dappAuthenticationKey), subscriptionAccount: subscription.account, dappUrl: subscription.metadata.url, scope: scope ) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift new file mode 100644 index 000000000..143cacf71 --- /dev/null +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift @@ -0,0 +1,79 @@ +import Foundation + +class NotifyWatchSubscriptionsRequester { + + private let keyserverURL: URL + private let identityClient: IdentityClient + private let networkingInteractor: NetworkInteracting + private let kms: KeyManagementService + private let logger: ConsoleLogging + private let webDidResolver: WebDidResolver + private let notifyServerUrl = "https://notify.walletconnect.com/" + + init(keyserverURL: URL, + networkingInteractor: NetworkInteracting, + identityClient: IdentityClient, + logger: ConsoleLogging, + kms: KeyManagementService, + webDidResolver: WebDidResolver + ) { + self.keyserverURL = keyserverURL + self.identityClient = identityClient + self.networkingInteractor = networkingInteractor + self.logger = logger + self.kms = kms + self.webDidResolver = webDidResolver + } + + func watchSubscriptions(account: Account) async throws { + + logger.debug("Watching subscriptions") + + let notifyServerAgreementKey = try await webDidResolver.resolveAgreementKey(domain: notifyServerUrl) + let notifyServerAuthenticationKey = try await webDidResolver.resolveAuthenticationKey(domain: notifyServerUrl) + let notifyServerAuthenticationDidKey = DIDKey(rawData: notifyServerAuthenticationKey) + let watchSubscriptionsTopic = notifyServerAgreementKey.rawRepresentation.sha256().toHexString() + + // todo - generate keypair only once + let keysY = try generateAgreementKeys(peerPublicKey: notifyServerAgreementKey) + + let responseTopic = keysY.derivedTopic() + + try kms.setSymmetricKey(keysY.sharedKey, for: watchSubscriptionsTopic) + try kms.setAgreementSecret(keysY, topic: responseTopic) + + logger.debug("setting symm key for response topic \(responseTopic)") + + let protocolMethod = NotifyWatchSubscriptionsProtocolMethod() + + + let watchSubscriptionsAuthWrapper = try await createJWTWrapper( + notifyServerAuthenticationDidKey: notifyServerAuthenticationDidKey, + subscriptionAccount: account) + + + let request = RPCRequest(method: protocolMethod.method, params: watchSubscriptionsAuthWrapper) + + logger.debug("Subscribing to response topic: \(responseTopic)") + + try await networkingInteractor.subscribe(topic: responseTopic) + + try await networkingInteractor.request(request, topic: watchSubscriptionsTopic, protocolMethod: protocolMethod, envelopeType: .type1(pubKey: keysY.publicKey.rawRepresentation)) + } + + + private func generateAgreementKeys(peerPublicKey: AgreementPublicKey) throws -> AgreementKeys { + let selfPubKey = try kms.createX25519KeyPair() + + let keys = try kms.performKeyAgreement(selfPublicKey: selfPubKey, peerPublicKey: peerPublicKey.hexRepresentation) + return keys + } + + private func createJWTWrapper(notifyServerAuthenticationDidKey: DIDKey, subscriptionAccount: Account) async throws -> NotifyWatchSubscriptionsPayload.Wrapper { + let jwtPayload = NotifyWatchSubscriptionsPayload(notifyServerAuthenticationKey: notifyServerAuthenticationDidKey, keyserver: keyserverURL, subscriptionAccount: subscriptionAccount) + return try identityClient.signAndCreateWrapper( + payload: jwtPayload, + account: subscriptionAccount + ) + } +} diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift new file mode 100644 index 000000000..fbf287572 --- /dev/null +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -0,0 +1,2 @@ +import Foundation + diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift index b6f6b7470..c61efb603 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift @@ -39,9 +39,9 @@ class NotifySubscribeRequester { let dappUrl = metadata.url - logger.debug("Subscribing for Notify") + logger.debug("Subscribing for Notify, dappUrl: \(dappUrl)") - let peerPublicKey = try await webDidResolver.resolvePublicKey(dappUrl: metadata.url) + let peerPublicKey = try await webDidResolver.resolveAgreementKey(domain: metadata.url) let subscribeTopic = peerPublicKey.rawRepresentation.sha256().toHexString() let keysY = try generateAgreementKeys(peerPublicKey: peerPublicKey) @@ -64,7 +64,7 @@ class NotifySubscribeRequester { ) let request = RPCRequest(method: protocolMethod.method, params: subscriptionAuthWrapper) - logger.debug("NotifySubscribeRequester: subscribing to response topic: \(responseTopic)") + logger.debug("Subscribing to response topic: \(responseTopic)") try await networkingInteractor.subscribe(topic: responseTopic) diff --git a/Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift b/Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift index 2f27c2693..9d642ff07 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift @@ -2,21 +2,35 @@ import Foundation final class WebDidResolver { - func resolvePublicKey(dappUrl: String) async throws -> AgreementPublicKey { - let didDoc = try await resolveDidDoc(domainUrl: dappUrl) + func resolveAgreementKey(domain: String) async throws -> AgreementPublicKey { + let didDoc = try await resolveDidDoc(domainUrl: domain) guard let keyAgreement = didDoc.keyAgreement.first else { throw Errors.didDocDoesNotContainKeyAgreement } guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == keyAgreement }) else { throw Errors.noVerificationMethodForKey } guard verificationMethod.publicKeyJwk.crv == .X25519 else { throw Errors.unsupportedCurve} let pubKeyBase64Url = verificationMethod.publicKeyJwk.x return try AgreementPublicKey(base64url: pubKeyBase64Url) } + + // TODO - Add cache for diddocs + + func resolveAuthenticationKey(domain: String) async throws -> Data { + let didDoc = try await resolveDidDoc(domainUrl: domain) + guard let authentication = didDoc.authentication?.first else { throw Errors.didDocDoesNotContainAuthenticationKey } + guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == authentication }) else { throw Errors.noVerificationMethodForKey } + guard verificationMethod.publicKeyJwk.crv == .Ed25519 else { throw Errors.unsupportedCurve} + let pubKeyBase64Url = verificationMethod.publicKeyJwk.x + guard let raw = Data(base64url: pubKeyBase64Url) else { throw Errors.invalidBase64urlString } + return raw + } } private extension WebDidResolver { enum Errors: Error { case invalidUrl + case invalidBase64urlString case didDocDoesNotContainKeyAgreement + case didDocDoesNotContainAuthenticationKey case noVerificationMethodForKey case unsupportedCurve } diff --git a/Sources/WalletConnectNotify/ProtocolMethods/File.swift b/Sources/WalletConnectNotify/ProtocolMethods/File.swift new file mode 100644 index 000000000..36166bd66 --- /dev/null +++ b/Sources/WalletConnectNotify/ProtocolMethods/File.swift @@ -0,0 +1,11 @@ +// + +import Foundation + +struct NotifyWatchSubscriptionsProtocolMethod: ProtocolMethod { + let method: String = "wc_notifyWatchSubscriptions" + + let requestConfig: RelayConfig = RelayConfig(tag: 4010, prompt: false, ttl: 30) + + let responseConfig: RelayConfig = RelayConfig(tag: 4011, prompt: false, ttl: 300) +} diff --git a/Sources/WalletConnectNotify/Types/Payload/NotifyWatchSubscriptionsPayload.swift b/Sources/WalletConnectNotify/Types/Payload/NotifyWatchSubscriptionsPayload.swift new file mode 100644 index 000000000..dd1c0207e --- /dev/null +++ b/Sources/WalletConnectNotify/Types/Payload/NotifyWatchSubscriptionsPayload.swift @@ -0,0 +1,66 @@ +import Foundation + +class NotifyWatchSubscriptionsPayload: JWTClaimsCodable { + struct Claims: JWTClaims { + /// Timestamp when JWT was issued + let iat: UInt64 + /// Timestamp when JWT must expire + let exp: UInt64 + /// Key server URL + let ksu: String + /// Description of action intent. Must be equal to `notify_watch_subscriptions` + let act: String? + + /// `did:key` of an identity key. Enables to resolve attached blockchain account. + let iss: String + /// `did:key` of an identity key. Enables to resolve associated Dapp domain used. + let aud: String + /// Blockchain account that notify subscription has been proposed for -`did:pkh` + let sub: String + + static var action: String? { + return "notify_watch_subscriptions" + } + } + + struct Wrapper: JWTWrapper { + let subscriptionAuth: String + + init(jwtString: String) { + self.subscriptionAuth = jwtString + } + + var jwtString: String { + return subscriptionAuth + } + } + + let notifyServerIdentityKey: DIDKey + let keyserver: URL + let subscriptionAccount: Account + + init(notifyServerAuthenticationKey: DIDKey, keyserver: URL, subscriptionAccount: Account) { + self.notifyServerIdentityKey = notifyServerAuthenticationKey + self.keyserver = keyserver + self.subscriptionAccount = subscriptionAccount + } + + required init(claims: Claims) throws { + self.notifyServerIdentityKey = try DIDKey(did: claims.aud) + self.keyserver = try claims.ksu.asURL() + self.subscriptionAccount = try Account(DIDPKHString: claims.sub) + } + + func encode(iss: String) throws -> Claims { + return Claims( + iat: defaultIat(), + exp: expiry(days: 30), + ksu: keyserver.absoluteString, + act: Claims.action, + iss: iss, + aud: notifyServerIdentityKey.did(variant: .ED25519), + sub: subscriptionAccount.did + ) + } + +} From 80bb8104720c0b6f28f604566de0aada84400548 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 6 Sep 2023 18:34:28 +0200 Subject: [PATCH 09/91] savepoint --- ...WatchSubscriptionsResponseSubscriber.swift | 37 +++++++++++++++++++ .../NotifyDeletePayload.swift | 0 .../NotifyDeleteResponsePayload.swift | 0 .../NotifyMessagePayload.swift | 0 .../NotifyMessageReceiptPayload.swift | 0 .../NotifySubscriptionPayload.swift | 0 .../NotifySubscriptionResponsePayload.swift | 0 .../NotifyUpdatePayload.swift | 0 .../NotifyUpdateResponsePayload.swift | 0 .../NotifyWatchSubscriptionsPayload.swift | 0 10 files changed, 37 insertions(+) rename Sources/WalletConnectNotify/Types/{Payload => JWTPayloads}/NotifyDeletePayload.swift (100%) rename Sources/WalletConnectNotify/Types/{Payload => JWTPayloads}/NotifyDeleteResponsePayload.swift (100%) rename Sources/WalletConnectNotify/Types/{Payload => JWTPayloads}/NotifyMessagePayload.swift (100%) rename Sources/WalletConnectNotify/Types/{Payload => JWTPayloads}/NotifyMessageReceiptPayload.swift (100%) rename Sources/WalletConnectNotify/Types/{Payload => JWTPayloads}/NotifySubscriptionPayload.swift (100%) rename Sources/WalletConnectNotify/Types/{Payload => JWTPayloads}/NotifySubscriptionResponsePayload.swift (100%) rename Sources/WalletConnectNotify/Types/{Payload => JWTPayloads}/NotifyUpdatePayload.swift (100%) rename Sources/WalletConnectNotify/Types/{Payload => JWTPayloads}/NotifyUpdateResponsePayload.swift (100%) rename Sources/WalletConnectNotify/Types/{Payload => JWTPayloads}/NotifyWatchSubscriptionsPayload.swift (100%) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index fbf287572..8bf5a48e0 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -1,2 +1,39 @@ import Foundation +import Combine +class NotifyWatchSubscriptionsResponseSubscriber { + private let networkingInteractor: NetworkInteracting + private let kms: KeyManagementServiceProtocol + private var publishers = [AnyCancellable]() + private let logger: ConsoleLogging + private let notifyStorage: NotifyStorage + private let subscriptionScopeProvider: SubscriptionScopeProvider + + init(networkingInteractor: NetworkInteracting, + kms: KeyManagementServiceProtocol, + logger: ConsoleLogging, + notifyStorage: NotifyStorage, + subscriptionScopeProvider: SubscriptionScopeProvider + ) { + self.networkingInteractor = networkingInteractor + self.kms = kms + self.logger = logger + self.notifyStorage = notifyStorage + self.subscriptionScopeProvider = subscriptionScopeProvider + subscribeForWatchSubscriptionsResponse() + } + + + private func subscribeForWatchSubscriptionsResponse() { + + let protocolMethod = NotifySubscribeProtocolMethod() + networkingInteractor.responseSubscription(on: protocolMethod) + .sink { [unowned self] (payload: ResponseSubscriptionPayload) in + Task(priority: .high) { + logger.debug("Received Notify watch Subscription response") + + + } + }.store(in: &publishers) + } +} diff --git a/Sources/WalletConnectNotify/Types/Payload/NotifyDeletePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeletePayload.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/Payload/NotifyDeletePayload.swift rename to Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeletePayload.swift diff --git a/Sources/WalletConnectNotify/Types/Payload/NotifyDeleteResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeleteResponsePayload.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/Payload/NotifyDeleteResponsePayload.swift rename to Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeleteResponsePayload.swift diff --git a/Sources/WalletConnectNotify/Types/Payload/NotifyMessagePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/Payload/NotifyMessagePayload.swift rename to Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift diff --git a/Sources/WalletConnectNotify/Types/Payload/NotifyMessageReceiptPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/Payload/NotifyMessageReceiptPayload.swift rename to Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift diff --git a/Sources/WalletConnectNotify/Types/Payload/NotifySubscriptionPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionPayload.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/Payload/NotifySubscriptionPayload.swift rename to Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionPayload.swift diff --git a/Sources/WalletConnectNotify/Types/Payload/NotifySubscriptionResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/Payload/NotifySubscriptionResponsePayload.swift rename to Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift diff --git a/Sources/WalletConnectNotify/Types/Payload/NotifyUpdatePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdatePayload.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/Payload/NotifyUpdatePayload.swift rename to Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdatePayload.swift diff --git a/Sources/WalletConnectNotify/Types/Payload/NotifyUpdateResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdateResponsePayload.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/Payload/NotifyUpdateResponsePayload.swift rename to Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdateResponsePayload.swift diff --git a/Sources/WalletConnectNotify/Types/Payload/NotifyWatchSubscriptionsPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyWatchSubscriptionsPayload.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/Payload/NotifyWatchSubscriptionsPayload.swift rename to Sources/WalletConnectNotify/Types/JWTPayloads/NotifyWatchSubscriptionsPayload.swift From 926148e8fdebfe71023380e0fabeaeaeed68f11d Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 6 Sep 2023 19:20:15 +0200 Subject: [PATCH 10/91] Add jwt payloads --- ...WatchSubscriptionsResponseSubscriber.swift | 4 +- .../NotificationConfig.swift | 0 .../NotificationType.swift | 0 .../{ => DataStructures}/NotifyError.swift | 0 .../{ => DataStructures}/NotifyMessage.swift | 0 .../{ => DataStructures}/NotifyRequest.swift | 0 .../NotifySubscription.swift | 0 .../NotifySubscriptionResult.swift | 0 .../{ => DataStructures}/WebDidDoc.swift | 0 .../NotifyWatchSubscriptionsPayload.swift | 2 +- ...ifyWatchSubscriptionsResponsePayload.swift | 55 +++++++++++++++++++ 11 files changed, 58 insertions(+), 3 deletions(-) rename Sources/WalletConnectNotify/Types/{ => DataStructures}/NotificationConfig.swift (100%) rename Sources/WalletConnectNotify/Types/{ => DataStructures}/NotificationType.swift (100%) rename Sources/WalletConnectNotify/Types/{ => DataStructures}/NotifyError.swift (100%) rename Sources/WalletConnectNotify/Types/{ => DataStructures}/NotifyMessage.swift (100%) rename Sources/WalletConnectNotify/Types/{ => DataStructures}/NotifyRequest.swift (100%) rename Sources/WalletConnectNotify/Types/{ => DataStructures}/NotifySubscription.swift (100%) rename Sources/WalletConnectNotify/Types/{ => DataStructures}/NotifySubscriptionResult.swift (100%) rename Sources/WalletConnectNotify/Types/{ => DataStructures}/WebDidDoc.swift (100%) rename Sources/WalletConnectNotify/Types/JWTPayloads/{ => notify_watch_subscriptions}/NotifyWatchSubscriptionsPayload.swift (95%) create mode 100644 Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 8bf5a48e0..20b2d5b05 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -28,11 +28,11 @@ class NotifyWatchSubscriptionsResponseSubscriber { let protocolMethod = NotifySubscribeProtocolMethod() networkingInteractor.responseSubscription(on: protocolMethod) - .sink { [unowned self] (payload: ResponseSubscriptionPayload) in + .sink { [unowned self] (payload: ResponseSubscriptionPayload) in Task(priority: .high) { logger.debug("Received Notify watch Subscription response") - + } }.store(in: &publishers) } diff --git a/Sources/WalletConnectNotify/Types/NotificationConfig.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotificationConfig.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/NotificationConfig.swift rename to Sources/WalletConnectNotify/Types/DataStructures/NotificationConfig.swift diff --git a/Sources/WalletConnectNotify/Types/NotificationType.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotificationType.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/NotificationType.swift rename to Sources/WalletConnectNotify/Types/DataStructures/NotificationType.swift diff --git a/Sources/WalletConnectNotify/Types/NotifyError.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotifyError.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/NotifyError.swift rename to Sources/WalletConnectNotify/Types/DataStructures/NotifyError.swift diff --git a/Sources/WalletConnectNotify/Types/NotifyMessage.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotifyMessage.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/NotifyMessage.swift rename to Sources/WalletConnectNotify/Types/DataStructures/NotifyMessage.swift diff --git a/Sources/WalletConnectNotify/Types/NotifyRequest.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotifyRequest.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/NotifyRequest.swift rename to Sources/WalletConnectNotify/Types/DataStructures/NotifyRequest.swift diff --git a/Sources/WalletConnectNotify/Types/NotifySubscription.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotifySubscription.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/NotifySubscription.swift rename to Sources/WalletConnectNotify/Types/DataStructures/NotifySubscription.swift diff --git a/Sources/WalletConnectNotify/Types/NotifySubscriptionResult.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotifySubscriptionResult.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/NotifySubscriptionResult.swift rename to Sources/WalletConnectNotify/Types/DataStructures/NotifySubscriptionResult.swift diff --git a/Sources/WalletConnectNotify/Types/WebDidDoc.swift b/Sources/WalletConnectNotify/Types/DataStructures/WebDidDoc.swift similarity index 100% rename from Sources/WalletConnectNotify/Types/WebDidDoc.swift rename to Sources/WalletConnectNotify/Types/DataStructures/WebDidDoc.swift diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyWatchSubscriptionsPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsPayload.swift similarity index 95% rename from Sources/WalletConnectNotify/Types/JWTPayloads/NotifyWatchSubscriptionsPayload.swift rename to Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsPayload.swift index dd1c0207e..021195cc5 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyWatchSubscriptionsPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsPayload.swift @@ -13,7 +13,7 @@ class NotifyWatchSubscriptionsPayload: JWTClaimsCodable { /// `did:key` of an identity key. Enables to resolve attached blockchain account. let iss: String - /// `did:key` of an identity key. Enables to resolve associated Dapp domain used. + /// `did:key` of an identity key. let aud: String /// Blockchain account that notify subscription has been proposed for -`did:pkh` let sub: String diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift new file mode 100644 index 000000000..3e43bfc21 --- /dev/null +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift @@ -0,0 +1,55 @@ +import Foundation + +class NotifyWatchSubscriptionsRersponsePayload: JWTClaimsCodable { + struct Claims: JWTClaims { + /// Timestamp when JWT was issued + let iat: UInt64 + /// Timestamp when JWT must expire + let exp: UInt64 + /// Description of action intent. Must be equal to `notify_watch_subscriptions` + let act: String? + + /// `did:key` of Notify Server authentication key + let iss: String + /// `did:key` of an identity key. + let aud: String + /// array of Notify Subscriptions + let sbs: [NotifySubscription] + + static var action: String? { + return "notify_watch_subscriptions" + } + } + + struct Wrapper: JWTWrapper { + let subscriptionAuth: String + + init(jwtString: String) { + self.subscriptionAuth = jwtString + } + + var jwtString: String { + return subscriptionAuth + } + } + + let subscriptions: [NotifySubscription] + let selfIdentityKey: DIDKey + + required init(claims: Claims) throws { + self.selfIdentityKey = try DIDKey(did: claims.aud) + self.subscriptions = claims.sbs + } + + func encode(iss: String) throws -> Claims { + return Claims( + iat: defaultIat(), + exp: expiry(days: 30), + act: Claims.action, + iss: iss, + aud: selfIdentityKey.did(variant: .ED25519), + sbs: subscriptions + ) + } + +} From b7f0c6ba979a63c4ba3b4314c1d7b8711fc24edb Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 6 Sep 2023 19:55:36 +0200 Subject: [PATCH 11/91] Update NotifyWatchSubscriptionsResponseSubscriber --- .../Client/Wallet/NotifyStorage.swift | 10 +++++++++ ...WatchSubscriptionsResponseSubscriber.swift | 21 +++++++++++++++++-- ...ifyWatchSubscriptionsResponsePayload.swift | 2 +- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift index ebc55c784..9afcdad80 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift @@ -63,6 +63,16 @@ final class NotifyStorage: NotifyStoring { newSubscriptionSubject.send(subscription) } + func replaceAllSubscriptions(_ subscriptions: [NotifySubscription]) { + fatalError("how it works?") + subscriptionStore.deleteAll(for: <#T##String#>) + + //delete messages for removed subscriptions + //messages for new subscriptions are not required + subscriptions.forEach { subscriptionStore.set(element: $0, for: $0.account.absoluteString) } + subscriptionsSubject.send(subscriptions) + } + func deleteSubscription(topic: String) throws { guard let subscription = getSubscription(topic: topic) else { throw Errors.subscriptionNotFound diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 20b2d5b05..14ba4b884 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -28,10 +28,27 @@ class NotifyWatchSubscriptionsResponseSubscriber { let protocolMethod = NotifySubscribeProtocolMethod() networkingInteractor.responseSubscription(on: protocolMethod) - .sink { [unowned self] (payload: ResponseSubscriptionPayload) in + .sink { [unowned self] (payload: ResponseSubscriptionPayload) in Task(priority: .high) { - logger.debug("Received Notify watch Subscription response") + logger.debug("Received Notify Watch Subscriptions response") + guard + let (responsePayload, _) = try? NotifyWatchSubscriptionsResponsePayload.decodeAndVerify(from: payload.response) + else { fatalError() /* TODO: Handle error */ } + + // todo varify signature with notify server diddoc authentication key + + let subscriptions = responsePayload.subscriptions + + notifyStorage.replaceAllSubscriptions(subscriptions) + + var properties = [String: String]() + for (index, subscription) in subscriptions.enumerated() { + let key = "subscription_\(index + 1)" + properties[key] = subscription.topic + } + + logger.debug("Updated Subscriptions by Watch Subscriptions Update", properties: properties) } }.store(in: &publishers) diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift index 3e43bfc21..be4f25729 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift @@ -1,6 +1,6 @@ import Foundation -class NotifyWatchSubscriptionsRersponsePayload: JWTClaimsCodable { +class NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { struct Claims: JWTClaims { /// Timestamp when JWT was issued let iat: UInt64 From 6d23f4ba6896d6941022bced48abcd99e46b0ef5 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 6 Sep 2023 23:21:32 +0200 Subject: [PATCH 12/91] savepoint --- .../Client/Wallet/NotifyClient.swift | 8 ++++- .../Client/Wallet/NotifyClientFactory.swift | 7 +++- .../NotifySubscriptionChangedResponder.swift | 5 +++ ...ubscriptionsChangedRequestSubscriber.swift | 31 ++++++++++++++++ ...WatchSubscriptionsResponseSubscriber.swift | 36 ++++++++++++++++--- .../Wallet/SubscriptionScopeProvider.swift | 15 ++++++-- .../NotifyServerSubscription.swift | 10 ++++++ ...ifyWatchSubscriptionsResponsePayload.swift | 4 +-- 8 files changed, 106 insertions(+), 10 deletions(-) create mode 100644 Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionChangedResponder.swift create mode 100644 Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift create mode 100644 Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 96fa0374d..6d73f6369 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -46,6 +46,8 @@ public class NotifyClient { private let notifyUpdateRequester: NotifyUpdateRequester private let notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber private let subscriptionsAutoUpdater: SubscriptionsAutoUpdater + private let notifyWatchSubscriptionsRequester: NotifyWatchSubscriptionsRequester + private let notifyWatchSubscriptionsResponseSubscriber: NotifyWatchSubscriptionsResponseSubscriber init(logger: ConsoleLogging, kms: KeyManagementServiceProtocol, @@ -60,7 +62,9 @@ public class NotifyClient { deleteNotifySubscriptionSubscriber: DeleteNotifySubscriptionSubscriber, notifyUpdateRequester: NotifyUpdateRequester, notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber, - subscriptionsAutoUpdater: SubscriptionsAutoUpdater + subscriptionsAutoUpdater: SubscriptionsAutoUpdater, + notifyWatchSubscriptionsRequester: NotifyWatchSubscriptionsRequester, + notifyWatchSubscriptionsResponseSubscriber: NotifyWatchSubscriptionsResponseSubscriber ) { self.logger = logger self.pushClient = pushClient @@ -75,6 +79,8 @@ public class NotifyClient { self.notifyUpdateRequester = notifyUpdateRequester self.notifyUpdateResponseSubscriber = notifyUpdateResponseSubscriber self.subscriptionsAutoUpdater = subscriptionsAutoUpdater + self.notifyWatchSubscriptionsRequester = notifyWatchSubscriptionsRequester + self.notifyWatchSubscriptionsResponseSubscriber = notifyWatchSubscriptionsResponseSubscriber } public func register(account: Account, onSign: @escaping SigningCallback) async throws { diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index 436cb724d..26ba92d20 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -58,6 +58,9 @@ public struct NotifyClientFactory { let subscriptionsAutoUpdater = SubscriptionsAutoUpdater(notifyUpdateRequester: notifyUpdateRequester, logger: logger, notifyStorage: notifyStorage) + let notifyWatchSubscriptionsRequester = NotifyWatchSubscriptionsRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, webDidResolver: webDidResolver) + let notifyWatchSubscriptionsResponseSubscriber = NotifyWatchSubscriptionsResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage, subscriptionScopeProvider: subscriptionScopeProvider) + return NotifyClient( logger: logger, kms: kms, @@ -72,7 +75,9 @@ public struct NotifyClientFactory { deleteNotifySubscriptionSubscriber: deleteNotifySubscriptionSubscriber, notifyUpdateRequester: notifyUpdateRequester, notifyUpdateResponseSubscriber: notifyUpdateResponseSubscriber, - subscriptionsAutoUpdater: subscriptionsAutoUpdater + subscriptionsAutoUpdater: subscriptionsAutoUpdater, + notifyWatchSubscriptionsRequester: notifyWatchSubscriptionsRequester, + notifyWatchSubscriptionsResponseSubscriber: notifyWatchSubscriptionsResponseSubscriber ) } } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionChangedResponder.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionChangedResponder.swift new file mode 100644 index 000000000..ada5f01ef --- /dev/null +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionChangedResponder.swift @@ -0,0 +1,5 @@ +import Foundation + +class NotifySubscriptionChangedResponder { + +} diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift new file mode 100644 index 000000000..cd1f6b90e --- /dev/null +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -0,0 +1,31 @@ +import Foundation +import Combine + +class NotifySubscriptionsChangedRequestSubscriber { + + private let networkingInteractor: NetworkInteracting + private let kms: KeyManagementServiceProtocol + private var publishers = [AnyCancellable]() + private let logger: ConsoleLogging + private let notifyStorage: NotifyStorage + private let subscriptionScopeProvider: SubscriptionScopeProvider + + init(networkingInteractor: NetworkInteracting, + kms: KeyManagementServiceProtocol, + logger: ConsoleLogging, + notifyStorage: NotifyStorage, + subscriptionScopeProvider: SubscriptionScopeProvider + ) { + self.networkingInteractor = networkingInteractor + self.kms = kms + self.logger = logger + self.notifyStorage = notifyStorage + self.subscriptionScopeProvider = subscriptionScopeProvider + subscribeForNofifyChangedRequests() + } + + + private func subscribeForNofifyChangedRequests() { + + } +} diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 14ba4b884..2f8a71e10 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -38,19 +38,47 @@ class NotifyWatchSubscriptionsResponseSubscriber { // todo varify signature with notify server diddoc authentication key - let subscriptions = responsePayload.subscriptions + let subscriptions = try await buildSubscriptions(responsePayload.subscriptions) notifyStorage.replaceAllSubscriptions(subscriptions) - var properties = [String: String]() + var logProperties = [String: String]() for (index, subscription) in subscriptions.enumerated() { let key = "subscription_\(index + 1)" - properties[key] = subscription.topic + logProperties[key] = subscription.topic } - logger.debug("Updated Subscriptions by Watch Subscriptions Update", properties: properties) + logger.debug("Updated Subscriptions by Watch Subscriptions Update", properties: logProperties) } }.store(in: &publishers) } + + private func buildSubscriptions(_ notifyServerSubscriptions: [NotifyServerSubscription]) async throws -> [NotifySubscription] { + var result = [NotifySubscription]() + + for subscription in notifyServerSubscriptions { + let scope = try await buildScope(selectedScope: subscription.scope, dappUrl: subscription.dappUrl) + guard let metadata = try? await subscriptionScopeProvider.getMetadata(dappUrl: subscription.dappUrl) else { continue } + + let notifySubscription = NotifySubscription(topic: subscription.topic, + account: subscription.account, + relay: RelayProtocolOptions(protocol: "irn", data: nil), + metadata: metadata, + scope: scope, + expiry: subscription.expiry, + symKey: subscription.symKey) + result.append(notifySubscription) + } + + return result + } + + + private func buildScope(selectedScope: [String], dappUrl: String) async throws -> [String: ScopeValue] { + let availableScope = try await subscriptionScopeProvider.getSubscriptionScope(dappUrl: dappUrl) + return availableScope.reduce(into: [:]) { + $0[$1.name] = ScopeValue(description: $1.description, enabled: selectedScope.contains($1.name)) + } + } } diff --git a/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift b/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift index a362dd4e6..e858cb1ff 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift @@ -12,11 +12,22 @@ class SubscriptionScopeProvider { if let availableScope = cache[dappUrl] { return availableScope } - guard let scopeUrl = URL(string: "\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } - let (data, _) = try await URLSession.shared.data(from: scopeUrl) + guard let notifyConfigUrl = URL(string: "\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } + let (data, _) = try await URLSession.shared.data(from: notifyConfigUrl) let config = try JSONDecoder().decode(NotificationConfig.self, from: data) let availableScope = Set(config.types) cache[dappUrl] = availableScope return availableScope } + + func getMetadata(dappUrl: String) async throws -> AppMetadata { + guard let notifyConfigUrl = URL(string: "\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } + let (data, _) = try await URLSession.shared.data(from: notifyConfigUrl) + let config = try JSONDecoder().decode(NotificationConfig.self, from: data) + + fatalError(" Can we add metadata to config?") + + + return config.metadata + } } diff --git a/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift new file mode 100644 index 000000000..f3a4ed630 --- /dev/null +++ b/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift @@ -0,0 +1,10 @@ +import Foundation + +class NotifyServerSubscription: Codable, Equatable { + let topic: String + let dappUrl: String + let account: Account + let scope: [String] + let symKey: String + let expiry: Date +} diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift index be4f25729..339b20c43 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift @@ -14,7 +14,7 @@ class NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { /// `did:key` of an identity key. let aud: String /// array of Notify Subscriptions - let sbs: [NotifySubscription] + let sbs: [NotifyServerSubscription] static var action: String? { return "notify_watch_subscriptions" @@ -33,7 +33,7 @@ class NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { } } - let subscriptions: [NotifySubscription] + let subscriptions: [NotifyServerSubscription] let selfIdentityKey: DIDKey required init(claims: Claims) throws { From 3e81817551880165e76ce1bf3a90d4c25a618c59 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 7 Sep 2023 12:29:42 +0200 Subject: [PATCH 13/91] add NotifySubscriptionsChangedRequest protocol method --- .../NotifySubscriptionsChangedRequestSubscriber.swift | 1 + .../ NotifySubscriptionsChangedRequest.swift | 9 +++++++++ ...wift => NotifyWatchSubscriptionsProtocolMethod.swift} | 2 -- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 Sources/WalletConnectNotify/ProtocolMethods/ NotifySubscriptionsChangedRequest.swift rename Sources/WalletConnectNotify/ProtocolMethods/{File.swift => NotifyWatchSubscriptionsProtocolMethod.swift} (97%) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index cd1f6b90e..c289ca9cc 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -26,6 +26,7 @@ class NotifySubscriptionsChangedRequestSubscriber { private func subscribeForNofifyChangedRequests() { + let protocolMethod = NotifySubscriptionsChangedRequest() } } diff --git a/Sources/WalletConnectNotify/ProtocolMethods/ NotifySubscriptionsChangedRequest.swift b/Sources/WalletConnectNotify/ProtocolMethods/ NotifySubscriptionsChangedRequest.swift new file mode 100644 index 000000000..8ad19da5d --- /dev/null +++ b/Sources/WalletConnectNotify/ProtocolMethods/ NotifySubscriptionsChangedRequest.swift @@ -0,0 +1,9 @@ +import Foundation + +struct NotifySubscriptionsChangedRequest: ProtocolMethod { + let method: String = "wc_notifySubscriptionsChanged" + + let requestConfig: RelayConfig = RelayConfig(tag: 4012, prompt: false, ttl: 300) + + let responseConfig: RelayConfig = RelayConfig(tag: 4013, prompt: false, ttl: 300) +} diff --git a/Sources/WalletConnectNotify/ProtocolMethods/File.swift b/Sources/WalletConnectNotify/ProtocolMethods/NotifyWatchSubscriptionsProtocolMethod.swift similarity index 97% rename from Sources/WalletConnectNotify/ProtocolMethods/File.swift rename to Sources/WalletConnectNotify/ProtocolMethods/NotifyWatchSubscriptionsProtocolMethod.swift index 36166bd66..479538836 100644 --- a/Sources/WalletConnectNotify/ProtocolMethods/File.swift +++ b/Sources/WalletConnectNotify/ProtocolMethods/NotifyWatchSubscriptionsProtocolMethod.swift @@ -1,5 +1,3 @@ -// - import Foundation struct NotifyWatchSubscriptionsProtocolMethod: ProtocolMethod { From 670b4126dcd2335de9cc795fc47d73e1bf5e51a0 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 7 Sep 2023 19:19:34 +0200 Subject: [PATCH 14/91] Update notify payloads --- ...ubscriptionsChangedRequestSubscriber.swift | 3 + .../Types/DataStructures/NotifyError.swift | 14 ----- .../NotifyServerSubscription.swift | 1 - .../JWTPayloads/NotifyMessagePayload.swift | 8 +-- ...fySubscriptionsChangedRequestPayload.swift | 48 +++++++++++++++ ...ySubscriptionsChangedResponsePayload.swift | 59 +++++++++++++++++++ .../NotifyWatchSubscriptionsPayload.swift | 10 ++-- ...ifyWatchSubscriptionsResponsePayload.swift | 10 ++-- 8 files changed, 124 insertions(+), 29 deletions(-) create mode 100644 Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift create mode 100644 Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index c289ca9cc..5c72e94a7 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -28,5 +28,8 @@ class NotifySubscriptionsChangedRequestSubscriber { private func subscribeForNofifyChangedRequests() { let protocolMethod = NotifySubscriptionsChangedRequest() + networkingInteractor.requestSubscription(on: protocolMethod).sink { [unowned self] (payload: RequestSubscriptionPayload) in + <#code#> + } } } diff --git a/Sources/WalletConnectNotify/Types/DataStructures/NotifyError.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotifyError.swift index 31d567893..d7aeeaf8f 100644 --- a/Sources/WalletConnectNotify/Types/DataStructures/NotifyError.swift +++ b/Sources/WalletConnectNotify/Types/DataStructures/NotifyError.swift @@ -1,8 +1,6 @@ import Foundation public enum NotifyError: Codable, Equatable, Error { - case userRejeted - case userHasExistingSubscription case methodUnsupported case registerSignatureRejected } @@ -11,10 +9,6 @@ extension NotifyError: Reason { init?(code: Int) { switch code { - case Self.userRejeted.code: - self = .userRejeted - case Self.userHasExistingSubscription.code: - self = .userHasExistingSubscription case Self.methodUnsupported.code: self = .methodUnsupported case Self.registerSignatureRejected.code: @@ -27,10 +21,6 @@ extension NotifyError: Reason { switch self { case .methodUnsupported: return 10001 - case .userRejeted: - return 5000 - case .userHasExistingSubscription: - return 6001 case .registerSignatureRejected: return 1501 } @@ -40,10 +30,6 @@ extension NotifyError: Reason { switch self { case .methodUnsupported: return "Method Unsupported" - case .userRejeted: - return "Notify request rejected" - case .userHasExistingSubscription: - return "User Has Existing Subscription" case .registerSignatureRejected: return "Register signature rejected" } diff --git a/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift index f3a4ed630..500b9cb5d 100644 --- a/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift +++ b/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift @@ -1,7 +1,6 @@ import Foundation class NotifyServerSubscription: Codable, Equatable { - let topic: String let dappUrl: String let account: Account let scope: [String] diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift index cf7b5687e..8d220a5c0 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift @@ -38,14 +38,14 @@ struct NotifyMessagePayload: JWTClaimsCodable { } } - let castServerPubKey: DIDKey + let dappAuthenticationKey: DIDKey let account: Account let subscriptionId: String let app: String let message: NotifyMessage init(claims: Claims) throws { - self.castServerPubKey = try DIDKey(did: claims.iss) + self.dappAuthenticationKey = try DIDKey(did: claims.iss) self.account = try DIDPKH(did: claims.aud).account self.subscriptionId = claims.sub self.app = claims.app @@ -57,7 +57,7 @@ struct NotifyMessagePayload: JWTClaimsCodable { iat: defaultIat(), exp: expiry(days: 1), act: Claims.action, - iss: castServerPubKey.multibase(variant: .ED25519), + iss: dappAuthenticationKey.multibase(variant: .ED25519), aud: account.did, sub: subscriptionId, app: app, @@ -65,4 +65,4 @@ struct NotifyMessagePayload: JWTClaimsCodable { ) } -} +} \ No newline at end of file diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift new file mode 100644 index 000000000..70be480be --- /dev/null +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift @@ -0,0 +1,48 @@ +import Foundation + +struct NotifySubscriptionsChangedRequestPayload: JWTClaimsCodable { + struct Claims: JWTClaims { + /// Timestamp when JWT was issued + let iat: UInt64 + /// Timestamp when JWT must expire + let exp: UInt64 + /// Action intent (must be `notify_subscriptions_changed`) + let act: String? + + /// `did:key` of an identity key. Enables to resolve associated Dapp domain used. diddoc authentication key + let iss: String + /// Blockchain account `did:pkh` + let aud: String + /// array of Notify Server Subscriptions + let sbs: [NotifyServerSubscription] + + static var action: String? { + return "subscriptionsChangedAuth" + } + } + + struct Wrapper: JWTWrapper { + let messageAuth: String + + init(jwtString: String) { + self.messageAuth = jwtString + } + + var jwtString: String { + return messageAuth + } + } + + let notifyServerAuthenticationKey: DIDKey + let subscriptions: [NotifyServerSubscription] + + + init(claims: Claims) throws { + self.notifyServerAuthenticationKey = try DIDKey(did: claims.iss) + self.subscriptions = claims.sbs + } + + func encode(iss: String) throws -> Claims { + fatalError("Client is not supposed to encode this JWT payload") + } +} diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift new file mode 100644 index 000000000..fd8782a8f --- /dev/null +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift @@ -0,0 +1,59 @@ +import Foundation + +struct NotifySubscriptionsChangedResponsePayload: JWTClaimsCodable { + struct Claims: JWTClaims { + /// Timestamp when JWT was issued + let iat: UInt64 + /// Timestamp when JWT must expire + let exp: UInt64 + /// Key server URL + let ksu: String + /// Description of action intent. Must be equal to `notify_subscriptions_changed_response` + let act: String? + + /// `did:key` of client identity key + let iss: String + /// `did:key` of Notify Server authentication key + let aud: String + + static var action: String? { + return "notify_watch_subscriptions" + } + } + + struct Wrapper: JWTWrapper { + let responseAuth: String + + init(jwtString: String) { + self.responseAuth = jwtString + } + + var jwtString: String { + return responseAuth + } + } + + init(keyserver: URL) { + self.keyserver = keyserver + } + + let selfIdentityKey: DIDKey + let keyserver: URL + + init(claims: Claims) throws { + fatalError("Method not expected to be called by the client") + } + + func encode(iss: String) throws -> Claims { + return Claims( + iat: defaultIat(), + exp: expiry(days: 30), + ksu: keyserver.absoluteString, + act: Claims.action, + iss: iss, + aud: selfIdentityKey.did(variant: .ED25519) + ) + } + +} + diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsPayload.swift index 021195cc5..fd92b9c79 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsPayload.swift @@ -1,6 +1,6 @@ import Foundation -class NotifyWatchSubscriptionsPayload: JWTClaimsCodable { +struct NotifyWatchSubscriptionsPayload: JWTClaimsCodable { struct Claims: JWTClaims { /// Timestamp when JWT was issued let iat: UInt64 @@ -24,14 +24,14 @@ class NotifyWatchSubscriptionsPayload: JWTClaimsCodable { } struct Wrapper: JWTWrapper { - let subscriptionAuth: String + let watchSubscriptionsAuth: String init(jwtString: String) { - self.subscriptionAuth = jwtString + self.watchSubscriptionsAuth = jwtString } var jwtString: String { - return subscriptionAuth + return watchSubscriptionsAuth } } @@ -45,7 +45,7 @@ class NotifyWatchSubscriptionsPayload: JWTClaimsCodable { self.subscriptionAccount = subscriptionAccount } - required init(claims: Claims) throws { + init(claims: Claims) throws { self.notifyServerIdentityKey = try DIDKey(did: claims.aud) self.keyserver = try claims.ksu.asURL() self.subscriptionAccount = try Account(DIDPKHString: claims.sub) diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift index 339b20c43..526c3a13b 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift @@ -1,6 +1,6 @@ import Foundation -class NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { +struct NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { struct Claims: JWTClaims { /// Timestamp when JWT was issued let iat: UInt64 @@ -22,21 +22,21 @@ class NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { } struct Wrapper: JWTWrapper { - let subscriptionAuth: String + let responseAuth: String init(jwtString: String) { - self.subscriptionAuth = jwtString + self.responseAuth = jwtString } var jwtString: String { - return subscriptionAuth + return responseAuth } } let subscriptions: [NotifyServerSubscription] let selfIdentityKey: DIDKey - required init(claims: Claims) throws { + init(claims: Claims) throws { self.selfIdentityKey = try DIDKey(did: claims.aud) self.subscriptions = claims.sbs } From 8ff9d5fde86526dbb162b469ceb4ce5b9d014262 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 7 Sep 2023 19:46:26 +0200 Subject: [PATCH 15/91] derive topic from sym key --- Sources/WalletConnectKMS/Crypto/SymmetricKey.swift | 4 ++++ .../NotifyWatchSubscriptionsResponseSubscriber.swift | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectKMS/Crypto/SymmetricKey.swift b/Sources/WalletConnectKMS/Crypto/SymmetricKey.swift index 7e2863f3c..0bfbe12a9 100644 --- a/Sources/WalletConnectKMS/Crypto/SymmetricKey.swift +++ b/Sources/WalletConnectKMS/Crypto/SymmetricKey.swift @@ -25,6 +25,10 @@ public struct SymmetricKey: Equatable { try self.init(rawRepresentation: data) } + public func derivedTopic() -> String { + rawRepresentation.sha256().toHexString() + } + } extension SymmetricKey: GenericPasswordConvertible { diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 2f8a71e10..01ca74d6e 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -59,9 +59,10 @@ class NotifyWatchSubscriptionsResponseSubscriber { for subscription in notifyServerSubscriptions { let scope = try await buildScope(selectedScope: subscription.scope, dappUrl: subscription.dappUrl) - guard let metadata = try? await subscriptionScopeProvider.getMetadata(dappUrl: subscription.dappUrl) else { continue } + guard let metadata = try? await subscriptionScopeProvider.getMetadata(dappUrl: subscription.dappUrl), + let topic = try? SymmetricKey(hex: subscription.symKey).derivedTopic() else { continue } - let notifySubscription = NotifySubscription(topic: subscription.topic, + let notifySubscription = NotifySubscription(topic: topic, account: subscription.account, relay: RelayProtocolOptions(protocol: "irn", data: nil), metadata: metadata, From af8ce8866fd0cf450b9d610e5d0b436bbe9aa724 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 7 Sep 2023 19:57:52 +0200 Subject: [PATCH 16/91] implement NotifySubscriptionsChangedRequestSubscriber add NotifySubscriptionsBuilder add metadata to notify config --- .../Wallet/NotifySubscriptionsBuilder.swift | 37 +++++++++++++++++++ ...ubscriptionsChangedRequestSubscriber.swift | 35 +++++++++++++++--- ...WatchSubscriptionsResponseSubscriber.swift | 36 ++---------------- .../DataStructures/NotificationConfig.swift | 1 + 4 files changed, 72 insertions(+), 37 deletions(-) create mode 100644 Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift new file mode 100644 index 000000000..58f74ac59 --- /dev/null +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift @@ -0,0 +1,37 @@ +import Foundation + +class NotifySubscriptionsBuilder { + private let subscriptionScopeProvider: SubscriptionScopeProvider + + init(subscriptionScopeProvider: SubscriptionScopeProvider) { + self.subscriptionScopeProvider = subscriptionScopeProvider + } + + func buildSubscriptions(_ notifyServerSubscriptions: [NotifyServerSubscription]) async throws -> [NotifySubscription] { + var result = [NotifySubscription]() + + for subscription in notifyServerSubscriptions { + let scope = try await buildScope(selectedScope: subscription.scope, dappUrl: subscription.dappUrl) + guard let metadata = try? await subscriptionScopeProvider.getMetadata(dappUrl: subscription.dappUrl), + let topic = try? SymmetricKey(hex: subscription.symKey).derivedTopic() else { continue } + + let notifySubscription = NotifySubscription(topic: topic, + account: subscription.account, + relay: RelayProtocolOptions(protocol: "irn", data: nil), + metadata: metadata, + scope: scope, + expiry: subscription.expiry, + symKey: subscription.symKey) + result.append(notifySubscription) + } + + return result + } + + private func buildScope(selectedScope: [String], dappUrl: String) async throws -> [String: ScopeValue] { + let availableScope = try await subscriptionScopeProvider.getSubscriptionScope(dappUrl: dappUrl) + return availableScope.reduce(into: [:]) { + $0[$1.name] = ScopeValue(description: $1.description, enabled: selectedScope.contains($1.name)) + } + } +} diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 5c72e94a7..9a15eca8d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -8,19 +8,19 @@ class NotifySubscriptionsChangedRequestSubscriber { private var publishers = [AnyCancellable]() private let logger: ConsoleLogging private let notifyStorage: NotifyStorage - private let subscriptionScopeProvider: SubscriptionScopeProvider + private let notifySubscriptionsBuilder: NotifySubscriptionsBuilder init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, notifyStorage: NotifyStorage, - subscriptionScopeProvider: SubscriptionScopeProvider + notifySubscriptionsBuilder: NotifySubscriptionsBuilder ) { self.networkingInteractor = networkingInteractor self.kms = kms self.logger = logger self.notifyStorage = notifyStorage - self.subscriptionScopeProvider = subscriptionScopeProvider + self.notifySubscriptionsBuilder = notifySubscriptionsBuilder subscribeForNofifyChangedRequests() } @@ -29,7 +29,32 @@ class NotifySubscriptionsChangedRequestSubscriber { let protocolMethod = NotifySubscriptionsChangedRequest() networkingInteractor.requestSubscription(on: protocolMethod).sink { [unowned self] (payload: RequestSubscriptionPayload) in - <#code#> - } + + + Task(priority: .high) { + logger.debug("Received Subscriptions Changed Request") + + guard + let (responsePayload, _) = try? NotifySubscriptionsChangedRequestPayload.decodeAndVerify(from: payload.request) + else { fatalError() /* TODO: Handle error */ } + + // todo varify signature with notify server diddoc authentication key + + let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions) + + notifyStorage.replaceAllSubscriptions(subscriptions) + + var logProperties = [String: String]() + for (index, subscription) in subscriptions.enumerated() { + let key = "subscription_\(index + 1)" + logProperties[key] = subscription.topic + } + + logger.debug("Updated Subscriptions by Subscriptions Changed Request", properties: logProperties) + + } + + }.store(in: &publishers) } + } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 01ca74d6e..71e12cbcf 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -7,19 +7,19 @@ class NotifyWatchSubscriptionsResponseSubscriber { private var publishers = [AnyCancellable]() private let logger: ConsoleLogging private let notifyStorage: NotifyStorage - private let subscriptionScopeProvider: SubscriptionScopeProvider + private let notifySubscriptionsBuilder: NotifySubscriptionsBuilder init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, notifyStorage: NotifyStorage, - subscriptionScopeProvider: SubscriptionScopeProvider + notifySubscriptionsBuilder: NotifySubscriptionsBuilder ) { self.networkingInteractor = networkingInteractor self.kms = kms self.logger = logger self.notifyStorage = notifyStorage - self.subscriptionScopeProvider = subscriptionScopeProvider + self.notifySubscriptionsBuilder = notifySubscriptionsBuilder subscribeForWatchSubscriptionsResponse() } @@ -38,7 +38,7 @@ class NotifyWatchSubscriptionsResponseSubscriber { // todo varify signature with notify server diddoc authentication key - let subscriptions = try await buildSubscriptions(responsePayload.subscriptions) + let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions) notifyStorage.replaceAllSubscriptions(subscriptions) @@ -54,32 +54,4 @@ class NotifyWatchSubscriptionsResponseSubscriber { }.store(in: &publishers) } - private func buildSubscriptions(_ notifyServerSubscriptions: [NotifyServerSubscription]) async throws -> [NotifySubscription] { - var result = [NotifySubscription]() - - for subscription in notifyServerSubscriptions { - let scope = try await buildScope(selectedScope: subscription.scope, dappUrl: subscription.dappUrl) - guard let metadata = try? await subscriptionScopeProvider.getMetadata(dappUrl: subscription.dappUrl), - let topic = try? SymmetricKey(hex: subscription.symKey).derivedTopic() else { continue } - - let notifySubscription = NotifySubscription(topic: topic, - account: subscription.account, - relay: RelayProtocolOptions(protocol: "irn", data: nil), - metadata: metadata, - scope: scope, - expiry: subscription.expiry, - symKey: subscription.symKey) - result.append(notifySubscription) - } - - return result - } - - - private func buildScope(selectedScope: [String], dappUrl: String) async throws -> [String: ScopeValue] { - let availableScope = try await subscriptionScopeProvider.getSubscriptionScope(dappUrl: dappUrl) - return availableScope.reduce(into: [:]) { - $0[$1.name] = ScopeValue(description: $1.description, enabled: selectedScope.contains($1.name)) - } - } } diff --git a/Sources/WalletConnectNotify/Types/DataStructures/NotificationConfig.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotificationConfig.swift index f17133c93..7fc0881c3 100644 --- a/Sources/WalletConnectNotify/Types/DataStructures/NotificationConfig.swift +++ b/Sources/WalletConnectNotify/Types/DataStructures/NotificationConfig.swift @@ -5,4 +5,5 @@ struct NotificationConfig: Codable { let version: Int let lastModified: TimeInterval let types: [NotificationType] + let metadata: AppMetadata } From c69f7bcd2e74b0587ea83c72f9ea51f23c37fd6d Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 7 Sep 2023 20:00:30 +0200 Subject: [PATCH 17/91] update files structure --- .../Client/{Common => Wallet}/NotifyDecryptionService.swift | 0 .../Client/{Common => Wallet}/NotifyResubscribeService.swift | 0 .../wc_notifyDelete/DeleteNotifySubscriptionRequester.swift} | 2 +- .../wc_notifyDelete}/DeleteNotifySubscriptionSubscriber.swift | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename Sources/WalletConnectNotify/Client/{Common => Wallet}/NotifyDecryptionService.swift (100%) rename Sources/WalletConnectNotify/Client/{Common => Wallet}/NotifyResubscribeService.swift (100%) rename Sources/WalletConnectNotify/Client/{Common/DeleteNotifySubscriptionService.swift => Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift} (98%) rename Sources/WalletConnectNotify/Client/{Common => Wallet/ProtocolEngine/wc_notifyDelete}/DeleteNotifySubscriptionSubscriber.swift (100%) diff --git a/Sources/WalletConnectNotify/Client/Common/NotifyDecryptionService.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyDecryptionService.swift similarity index 100% rename from Sources/WalletConnectNotify/Client/Common/NotifyDecryptionService.swift rename to Sources/WalletConnectNotify/Client/Wallet/NotifyDecryptionService.swift diff --git a/Sources/WalletConnectNotify/Client/Common/NotifyResubscribeService.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyResubscribeService.swift similarity index 100% rename from Sources/WalletConnectNotify/Client/Common/NotifyResubscribeService.swift rename to Sources/WalletConnectNotify/Client/Wallet/NotifyResubscribeService.swift diff --git a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift similarity index 98% rename from Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift rename to Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift index 0ddfefbdd..254c61977 100644 --- a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift @@ -1,6 +1,6 @@ import Foundation -class DeleteNotifySubscriptionService { +class DeleteNotifySubscriptionRequester { enum Errors: Error { case notifySubscriptionNotFound } diff --git a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionSubscriber.swift similarity index 100% rename from Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionSubscriber.swift rename to Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionSubscriber.swift From f02b07e5fefa242933e11baccd267d4d3769b39c Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 7 Sep 2023 20:25:20 +0200 Subject: [PATCH 18/91] Add response to NotifySubscriptionsChangedRequestSubscriber --- .../NotifySubscriptionChangedResponder.swift | 5 ---- ...ubscriptionsChangedRequestSubscriber.swift | 30 ++++++++++++++++--- .../ NotifySubscriptionsChangedRequest.swift | 2 +- ...fySubscriptionsChangedRequestPayload.swift | 4 +++ 4 files changed, 31 insertions(+), 10 deletions(-) delete mode 100644 Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionChangedResponder.swift diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionChangedResponder.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionChangedResponder.swift deleted file mode 100644 index ada5f01ef..000000000 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionChangedResponder.swift +++ /dev/null @@ -1,5 +0,0 @@ -import Foundation - -class NotifySubscriptionChangedResponder { - -} diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 9a15eca8d..537af15c1 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -2,8 +2,9 @@ import Foundation import Combine class NotifySubscriptionsChangedRequestSubscriber { - + private let keyserver: URL private let networkingInteractor: NetworkInteracting + private let identityClient: IdentityClient private let kms: KeyManagementServiceProtocol private var publishers = [AnyCancellable]() private let logger: ConsoleLogging @@ -12,6 +13,7 @@ class NotifySubscriptionsChangedRequestSubscriber { init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, + identityClient: IdentityClient, logger: ConsoleLogging, notifyStorage: NotifyStorage, notifySubscriptionsBuilder: NotifySubscriptionsBuilder @@ -19,6 +21,7 @@ class NotifySubscriptionsChangedRequestSubscriber { self.networkingInteractor = networkingInteractor self.kms = kms self.logger = logger + self.identityClient = identityClient self.notifyStorage = notifyStorage self.notifySubscriptionsBuilder = notifySubscriptionsBuilder subscribeForNofifyChangedRequests() @@ -26,7 +29,7 @@ class NotifySubscriptionsChangedRequestSubscriber { private func subscribeForNofifyChangedRequests() { - let protocolMethod = NotifySubscriptionsChangedRequest() + let protocolMethod = NotifySubscriptionsChangedProtocolMethod() networkingInteractor.requestSubscription(on: protocolMethod).sink { [unowned self] (payload: RequestSubscriptionPayload) in @@ -35,12 +38,12 @@ class NotifySubscriptionsChangedRequestSubscriber { logger.debug("Received Subscriptions Changed Request") guard - let (responsePayload, _) = try? NotifySubscriptionsChangedRequestPayload.decodeAndVerify(from: payload.request) + let (jwtPayload, _) = try? NotifySubscriptionsChangedRequestPayload.decodeAndVerify(from: payload.request) else { fatalError() /* TODO: Handle error */ } // todo varify signature with notify server diddoc authentication key - let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions) + let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(jwtPayload.subscriptions) notifyStorage.replaceAllSubscriptions(subscriptions) @@ -52,9 +55,28 @@ class NotifySubscriptionsChangedRequestSubscriber { logger.debug("Updated Subscriptions by Subscriptions Changed Request", properties: logProperties) + try await respond(topic: payload.topic, account: jwtPayload.account, rpcId: payload.id) + } }.store(in: &publishers) } + private func respond(topic: String, account: Account, rpcId: RPCID) async throws { + + let receiptPayload = NotifySubscriptionsChangedResponsePayload(keyserver: keyserver) + + let wrapper = try identityClient.signAndCreateWrapper( + payload: receiptPayload, + account: account + ) + + let response = RPCResponse(id: rpcId, result: wrapper) + try await networkingInteractor.respond( + topic: topic, + response: response, + protocolMethod: NotifySubscriptionsChangedProtocolMethod() + ) + } + } diff --git a/Sources/WalletConnectNotify/ProtocolMethods/ NotifySubscriptionsChangedRequest.swift b/Sources/WalletConnectNotify/ProtocolMethods/ NotifySubscriptionsChangedRequest.swift index 8ad19da5d..6f5d28e22 100644 --- a/Sources/WalletConnectNotify/ProtocolMethods/ NotifySubscriptionsChangedRequest.swift +++ b/Sources/WalletConnectNotify/ProtocolMethods/ NotifySubscriptionsChangedRequest.swift @@ -1,6 +1,6 @@ import Foundation -struct NotifySubscriptionsChangedRequest: ProtocolMethod { +struct NotifySubscriptionsChangedProtocolMethod: ProtocolMethod { let method: String = "wc_notifySubscriptionsChanged" let requestConfig: RelayConfig = RelayConfig(tag: 4012, prompt: false, ttl: 300) diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift index 70be480be..13142767f 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift @@ -35,11 +35,15 @@ struct NotifySubscriptionsChangedRequestPayload: JWTClaimsCodable { let notifyServerAuthenticationKey: DIDKey let subscriptions: [NotifyServerSubscription] + let account: Account + + init(claims: Claims) throws { self.notifyServerAuthenticationKey = try DIDKey(did: claims.iss) self.subscriptions = claims.sbs + self.account = try DIDPKH(did: claims.aud).account } func encode(iss: String) throws -> Claims { From 5c8918885fe07be0b99ee0a1cd23fdc7637241dd Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 7 Sep 2023 20:54:42 +0200 Subject: [PATCH 19/91] savepoint --- .../Client/Wallet/NotifyClient.swift | 8 +++--- .../Client/Wallet/NotifyClientFactory.swift | 7 +++-- .../Client/Wallet/NotifyStorage.swift | 2 +- .../DeleteNotifySubscriptionRequester.swift | 2 +- ...ubscriptionsChangedRequestSubscriber.swift | 28 +++++++++++-------- .../Wallet/SubscriptionScopeProvider.swift | 6 +--- .../NotifyServerSubscription.swift | 2 +- ...fySubscriptionsChangedRequestPayload.swift | 3 -- ...ySubscriptionsChangedResponsePayload.swift | 7 +++-- 9 files changed, 33 insertions(+), 32 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 6d73f6369..7ddae75da 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -31,7 +31,7 @@ public class NotifyClient { .eraseToAnyPublisher() } - private let deleteNotifySubscriptionService: DeleteNotifySubscriptionService + private let deleteNotifySubscriptionRequester: DeleteNotifySubscriptionRequester private let notifySubscribeRequester: NotifySubscribeRequester public let logger: ConsoleLogging @@ -55,7 +55,7 @@ public class NotifyClient { pushClient: PushClient, notifyMessageSubscriber: NotifyMessageSubscriber, notifyStorage: NotifyStorage, - deleteNotifySubscriptionService: DeleteNotifySubscriptionService, + deleteNotifySubscriptionRequester: DeleteNotifySubscriptionRequester, resubscribeService: NotifyResubscribeService, notifySubscribeRequester: NotifySubscribeRequester, notifySubscribeResponseSubscriber: NotifySubscribeResponseSubscriber, @@ -71,7 +71,7 @@ public class NotifyClient { self.identityClient = identityClient self.notifyMessageSubscriber = notifyMessageSubscriber self.notifyStorage = notifyStorage - self.deleteNotifySubscriptionService = deleteNotifySubscriptionService + self.deleteNotifySubscriptionRequester = deleteNotifySubscriptionRequester self.resubscribeService = resubscribeService self.notifySubscribeRequester = notifySubscribeRequester self.notifySubscribeResponseSubscriber = notifySubscribeResponseSubscriber @@ -108,7 +108,7 @@ public class NotifyClient { } public func deleteSubscription(topic: String) async throws { - try await deleteNotifySubscriptionService.delete(topic: topic) + try await deleteNotifySubscriptionRequester.delete(topic: topic) } public func deleteNotifyMessage(id: String) { diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index 26ba92d20..ea25761a2 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -40,7 +40,7 @@ public struct NotifyClientFactory { let identityClient = IdentityClientFactory.create(keyserver: keyserverURL, keychain: keychainStorage, logger: logger) let notifyMessageSubscriber = NotifyMessageSubscriber(keyserver: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, notifyStorage: notifyStorage, crypto: crypto, logger: logger) let webDidResolver = WebDidResolver() - let deleteNotifySubscriptionService = DeleteNotifySubscriptionService(keyserver: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, webDidResolver: webDidResolver, kms: kms, logger: logger, notifyStorage: notifyStorage) + let deleteNotifySubscriptionRequester = DeleteNotifySubscriptionRequester(keyserver: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, webDidResolver: webDidResolver, kms: kms, logger: logger, notifyStorage: notifyStorage) let resubscribeService = NotifyResubscribeService(networkInteractor: networkInteractor, notifyStorage: notifyStorage, logger: logger) let dappsMetadataStore = CodableStore(defaults: keyValueStorage, identifier: NotifyStorageIdntifiers.dappsMetadataStore) @@ -59,7 +59,8 @@ public struct NotifyClientFactory { let subscriptionsAutoUpdater = SubscriptionsAutoUpdater(notifyUpdateRequester: notifyUpdateRequester, logger: logger, notifyStorage: notifyStorage) let notifyWatchSubscriptionsRequester = NotifyWatchSubscriptionsRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, webDidResolver: webDidResolver) - let notifyWatchSubscriptionsResponseSubscriber = NotifyWatchSubscriptionsResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage, subscriptionScopeProvider: subscriptionScopeProvider) + let notifySubscriptionsBuilder = NotifySubscriptionsBuilder(subscriptionScopeProvider: subscriptionScopeProvider) + let notifyWatchSubscriptionsResponseSubscriber = NotifyWatchSubscriptionsResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) return NotifyClient( logger: logger, @@ -68,7 +69,7 @@ public struct NotifyClientFactory { pushClient: pushClient, notifyMessageSubscriber: notifyMessageSubscriber, notifyStorage: notifyStorage, - deleteNotifySubscriptionService: deleteNotifySubscriptionService, + deleteNotifySubscriptionRequester: deleteNotifySubscriptionRequester, resubscribeService: resubscribeService, notifySubscribeRequester: notifySubscribeRequester, notifySubscribeResponseSubscriber: notifySubscribeResponseSubscriber, diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift index 9afcdad80..511333fc8 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift @@ -65,7 +65,7 @@ final class NotifyStorage: NotifyStoring { func replaceAllSubscriptions(_ subscriptions: [NotifySubscription]) { fatalError("how it works?") - subscriptionStore.deleteAll(for: <#T##String#>) +// subscriptionStore.deleteAll(for: <#T##String#>) //delete messages for removed subscriptions //messages for new subscriptions are not required diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift index 254c61977..e280d63fa 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift @@ -64,7 +64,7 @@ class DeleteNotifySubscriptionRequester { } -private extension DeleteNotifySubscriptionService { +private extension DeleteNotifySubscriptionRequester { func createJWTWrapper(dappPubKey: DIDKey, reason: String, app: String, account: Account) throws -> NotifyDeletePayload.Wrapper { let jwtPayload = NotifyDeletePayload(keyserver: keyserver, dappPubKey: dappPubKey, reason: reason, app: app) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 537af15c1..c250045fb 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -10,14 +10,17 @@ class NotifySubscriptionsChangedRequestSubscriber { private let logger: ConsoleLogging private let notifyStorage: NotifyStorage private let notifySubscriptionsBuilder: NotifySubscriptionsBuilder - - init(networkingInteractor: NetworkInteracting, - kms: KeyManagementServiceProtocol, - identityClient: IdentityClient, - logger: ConsoleLogging, - notifyStorage: NotifyStorage, - notifySubscriptionsBuilder: NotifySubscriptionsBuilder + + init( + keyserver: URL, + networkingInteractor: NetworkInteracting, + kms: KeyManagementServiceProtocol, + identityClient: IdentityClient, + logger: ConsoleLogging, + notifyStorage: NotifyStorage, + notifySubscriptionsBuilder: NotifySubscriptionsBuilder ) { + self.keyserver = keyserver self.networkingInteractor = networkingInteractor self.kms = kms self.logger = logger @@ -47,7 +50,7 @@ class NotifySubscriptionsChangedRequestSubscriber { notifyStorage.replaceAllSubscriptions(subscriptions) - var logProperties = [String: String]() + var logProperties = ["rpcId": payload.id.string] for (index, subscription) in subscriptions.enumerated() { let key = "subscription_\(index + 1)" logProperties[key] = subscription.topic @@ -55,16 +58,16 @@ class NotifySubscriptionsChangedRequestSubscriber { logger.debug("Updated Subscriptions by Subscriptions Changed Request", properties: logProperties) - try await respond(topic: payload.topic, account: jwtPayload.account, rpcId: payload.id) + try await respond(topic: payload.topic, account: jwtPayload.account, rpcId: payload.id, notifyServerAuthenticationKey: jwtPayload.notifyServerAuthenticationKey) } }.store(in: &publishers) } - private func respond(topic: String, account: Account, rpcId: RPCID) async throws { + private func respond(topic: String, account: Account, rpcId: RPCID, notifyServerAuthenticationKey: DIDKey) async throws { - let receiptPayload = NotifySubscriptionsChangedResponsePayload(keyserver: keyserver) + let receiptPayload = NotifySubscriptionsChangedResponsePayload(keyserver: keyserver, notifyServerAuthenticationKey: notifyServerAuthenticationKey) let wrapper = try identityClient.signAndCreateWrapper( payload: receiptPayload, @@ -77,6 +80,9 @@ class NotifySubscriptionsChangedRequestSubscriber { response: response, protocolMethod: NotifySubscriptionsChangedProtocolMethod() ) + + let logProperties = ["rpcId": rpcId.string] + logger.debug("Responded for Subscriptions Changed Request", properties: logProperties) } } diff --git a/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift b/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift index e858cb1ff..65db81fd6 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift @@ -1,7 +1,7 @@ import Foundation -class SubscriptionScopeProvider { +actor SubscriptionScopeProvider { enum Errors: Error { case invalidUrl } @@ -24,10 +24,6 @@ class SubscriptionScopeProvider { guard let notifyConfigUrl = URL(string: "\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } let (data, _) = try await URLSession.shared.data(from: notifyConfigUrl) let config = try JSONDecoder().decode(NotificationConfig.self, from: data) - - fatalError(" Can we add metadata to config?") - - return config.metadata } } diff --git a/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift index 500b9cb5d..3ac2ecb93 100644 --- a/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift +++ b/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift @@ -1,6 +1,6 @@ import Foundation -class NotifyServerSubscription: Codable, Equatable { +struct NotifyServerSubscription: Codable, Equatable { let dappUrl: String let account: Account let scope: [String] diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift index 13142767f..41b4464dc 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift @@ -37,9 +37,6 @@ struct NotifySubscriptionsChangedRequestPayload: JWTClaimsCodable { let subscriptions: [NotifyServerSubscription] let account: Account - - - init(claims: Claims) throws { self.notifyServerAuthenticationKey = try DIDKey(did: claims.iss) self.subscriptions = claims.sbs diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift index fd8782a8f..af1b703a3 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift @@ -33,11 +33,12 @@ struct NotifySubscriptionsChangedResponsePayload: JWTClaimsCodable { } } - init(keyserver: URL) { + init(keyserver: URL, notifyServerAuthenticationKey: DIDKey) { self.keyserver = keyserver + self.notifyServerAuthenticationKey = notifyServerAuthenticationKey } - let selfIdentityKey: DIDKey + let notifyServerAuthenticationKey: DIDKey let keyserver: URL init(claims: Claims) throws { @@ -51,7 +52,7 @@ struct NotifySubscriptionsChangedResponsePayload: JWTClaimsCodable { ksu: keyserver.absoluteString, act: Claims.action, iss: iss, - aud: selfIdentityKey.did(variant: .ED25519) + aud: notifyServerAuthenticationKey.did(variant: .ED25519) ) } From bb2c5abf0bef349b3e7d110ea6c1ce3bc8e47dfc Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 7 Sep 2023 22:09:05 +0200 Subject: [PATCH 20/91] enable watch subscriptions --- Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 7ddae75da..e750ab9eb 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -85,6 +85,7 @@ public class NotifyClient { public func register(account: Account, onSign: @escaping SigningCallback) async throws { _ = try await identityClient.register(account: account, onSign: onSign) + notifyWatchSubscriptionsRequester.watchSubscriptions(account: account) } public func setLogging(level: LoggingLevel) { From 0c2d37bb4203399cbb70def607ecc2e2c1229b1b Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 7 Sep 2023 22:09:59 +0200 Subject: [PATCH 21/91] fix build --- Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index e750ab9eb..84fbbeaa3 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -85,7 +85,7 @@ public class NotifyClient { public func register(account: Account, onSign: @escaping SigningCallback) async throws { _ = try await identityClient.register(account: account, onSign: onSign) - notifyWatchSubscriptionsRequester.watchSubscriptions(account: account) + try await notifyWatchSubscriptionsRequester.watchSubscriptions(account: account) } public func setLogging(level: LoggingLevel) { From e2b0c68564f8d4abcfb94f905210e9d681b09143 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 8 Sep 2023 08:40:31 +0200 Subject: [PATCH 22/91] replace subscriptions --- .../Client/Wallet/NotifyStorage.swift | 10 ++++------ .../NotifyWatchSubscriptionsResponseSubscriber.swift | 5 +++-- .../Client/Wallet/SubscriptionScopeProvider.swift | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift index 511333fc8..f08498f21 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift @@ -63,13 +63,11 @@ final class NotifyStorage: NotifyStoring { newSubscriptionSubject.send(subscription) } - func replaceAllSubscriptions(_ subscriptions: [NotifySubscription]) { - fatalError("how it works?") -// subscriptionStore.deleteAll(for: <#T##String#>) - - //delete messages for removed subscriptions + func replaceAllSubscriptions(_ subscriptions: [NotifySubscription], account: Account) { + subscriptionStore.deleteAll(for: account.absoluteString) + // todo - compare old with new = delete messages for removed subscriptions //messages for new subscriptions are not required - subscriptions.forEach { subscriptionStore.set(element: $0, for: $0.account.absoluteString) } + subscriptionStore.set(elements: subscriptions, for: account.absoluteString) subscriptionsSubject.send(subscriptions) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 71e12cbcf..1979eb643 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -33,14 +33,15 @@ class NotifyWatchSubscriptionsResponseSubscriber { logger.debug("Received Notify Watch Subscriptions response") guard - let (responsePayload, _) = try? NotifyWatchSubscriptionsResponsePayload.decodeAndVerify(from: payload.response) + let (responsePayload, _) = try? NotifyWatchSubscriptionsResponsePayload.decodeAndVerify(from: payload.response), + let account = responsePayload.subscriptions.first?.account else { fatalError() /* TODO: Handle error */ } // todo varify signature with notify server diddoc authentication key let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions) - notifyStorage.replaceAllSubscriptions(subscriptions) + notifyStorage.replaceAllSubscriptions(subscriptions, account: account) var logProperties = [String: String]() for (index, subscription) in subscriptions.enumerated() { diff --git a/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift b/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift index 65db81fd6..be4d16931 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift @@ -24,6 +24,6 @@ actor SubscriptionScopeProvider { guard let notifyConfigUrl = URL(string: "\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } let (data, _) = try await URLSession.shared.data(from: notifyConfigUrl) let config = try JSONDecoder().decode(NotificationConfig.self, from: data) - return config.metadata + return AppMetadata(name: "", description: "", url: "", icons: []) } } From fc5d4313139ede6e05c469005acebf56490434b4 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 8 Sep 2023 10:15:39 +0200 Subject: [PATCH 23/91] savepoint --- .../NotifyWatchSubscriptionsRequester.swift | 2 +- .../Client/Wallet/SubscriptionScopeProvider.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift index 143cacf71..59cba92af 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift @@ -8,7 +8,7 @@ class NotifyWatchSubscriptionsRequester { private let kms: KeyManagementService private let logger: ConsoleLogging private let webDidResolver: WebDidResolver - private let notifyServerUrl = "https://notify.walletconnect.com/" + private let notifyServerUrl = "https://dev.notify.walletconnect.com" init(keyserverURL: URL, networkingInteractor: NetworkInteracting, diff --git a/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift b/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift index be4d16931..65db81fd6 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift @@ -24,6 +24,6 @@ actor SubscriptionScopeProvider { guard let notifyConfigUrl = URL(string: "\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } let (data, _) = try await URLSession.shared.data(from: notifyConfigUrl) let config = try JSONDecoder().decode(NotificationConfig.self, from: data) - return AppMetadata(name: "", description: "", url: "", icons: []) + return config.metadata } } From 1ef9fd778c932f1fd3bb912fa7498e54a08af2a7 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 8 Sep 2023 10:16:36 +0200 Subject: [PATCH 24/91] fix build --- .../NotifySubscriptionsChangedRequestSubscriber.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index c250045fb..9773972ba 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -41,14 +41,15 @@ class NotifySubscriptionsChangedRequestSubscriber { logger.debug("Received Subscriptions Changed Request") guard - let (jwtPayload, _) = try? NotifySubscriptionsChangedRequestPayload.decodeAndVerify(from: payload.request) + let (jwtPayload, _) = try? NotifySubscriptionsChangedRequestPayload.decodeAndVerify(from: payload.request), + let account = jwtPayload.subscriptions.first?.account else { fatalError() /* TODO: Handle error */ } // todo varify signature with notify server diddoc authentication key let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(jwtPayload.subscriptions) - notifyStorage.replaceAllSubscriptions(subscriptions) + notifyStorage.replaceAllSubscriptions(subscriptions, account: account) var logProperties = ["rpcId": payload.id.string] for (index, subscription) in subscriptions.enumerated() { From 1c7893a901ce3bb5e38d7e7a9bbaf0dd62745d41 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 8 Sep 2023 11:57:09 +0200 Subject: [PATCH 25/91] add testNotifyWatchSubscriptions --- .../IntegrationTests/Push/NotifyTests.swift | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index ff358cb99..bbf4685f8 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -16,7 +16,7 @@ final class NotifyTests: XCTestCase { var walletPairingClient: PairingClient! - var walletNotifyClient: NotifyClient! + var walletNotifyClientA: NotifyClient! let gmDappUrl = "https://notify.gm.walletconnect.com/" @@ -65,8 +65,7 @@ final class NotifyTests: XCTestCase { return (pairingClient, networkingClient, keychain, keyValueStorage) } - func makeWalletClients() { - let prefix = "🦋 Wallet: " + func makeWalletClient(prefix: String = "🦋 Wallet: ") -> NotifyClient { let (pairingClient, networkingInteractor, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) let notifyLogger = ConsoleLogger(prefix: prefix + " [Notify]", loggingLevel: .debug) walletPairingClient = pairingClient @@ -75,7 +74,7 @@ final class NotifyTests: XCTestCase { keychainStorage: keychain, environment: .sandbox) let keyserverURL = URL(string: "https://keys.walletconnect.com")! - walletNotifyClient = NotifyClientFactory.create(keyserverURL: keyserverURL, + let client = NotifyClientFactory.create(keyserverURL: keyserverURL, logger: notifyLogger, keyValueStorage: keyValueStorage, keychainStorage: keychain, @@ -84,50 +83,77 @@ final class NotifyTests: XCTestCase { pairingRegisterer: pairingClient, pushClient: pushClient, crypto: DefaultCryptoProvider()) + return client } override func setUp() { - makeWalletClients() + walletNotifyClientA = makeWalletClient() } func testWalletCreatesSubscription() async { let expectation = expectation(description: "expects to create notify subscription") let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) - walletNotifyClient.newSubscriptionPublisher + walletNotifyClientA.newSubscriptionPublisher .sink { [unowned self] subscription in Task(priority: .high) { - try! await walletNotifyClient.deleteSubscription(topic: subscription.topic) + try! await walletNotifyClientA.deleteSubscription(topic: subscription.topic) expectation.fulfill() } }.store(in: &publishers) - try! await walletNotifyClient.register(account: account, onSign: sign) - try! await walletNotifyClient.subscribe(metadata: metadata, account: account) + try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await walletNotifyClientA.subscribe(metadata: metadata, account: account) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } + + + func testNotifyWatchSubscriptions() async throws { + let expectation = expectation(description: "expects client B to receive subscription created by client A") + let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) + + try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await walletNotifyClientA.subscribe(metadata: metadata, account: account, onSign: sign) + + sleep(2) + let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ") + try! await clientB.register(account: account, onSign: sign) + + clientB.subscriptionsPublisher.sink { subscriptions in + Task(priority: .high) { + try! await clientB.deleteSubscription(topic: subscriptions.first!.topic) + expectation.fulfill() + } + }.store(in: &publishers) + + wait(for: [expectation], timeout: InputConfig.defaultTimeout) + + + } func testWalletCreatesAndUpdatesSubscription() async { let expectation = expectation(description: "expects to create and update notify subscription") let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) let updateScope: Set = ["alerts"] - try! await walletNotifyClient.register(account: account, onSign: sign) - try! await walletNotifyClient.subscribe(metadata: metadata, account: account) - walletNotifyClient.newSubscriptionPublisher + + try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await walletNotifyClientA.subscribe(metadata: metadata, account: account) + + walletNotifyClientA.newSubscriptionPublisher .sink { [unowned self] subscription in Task(priority: .high) { - try! await walletNotifyClient.update(topic: subscription.topic, scope: updateScope) + try! await walletNotifyClientA.update(topic: subscription.topic, scope: updateScope) } } .store(in: &publishers) - walletNotifyClient.updateSubscriptionPublisher + walletNotifyClientA.updateSubscriptionPublisher .sink { [unowned self] subscription in let updatedScope = Set(subscription.scope.filter{ $0.value.enabled == true }.keys) XCTAssertEqual(updatedScope, updateScope) Task(priority: .high) { - try! await walletNotifyClient.deleteSubscription(topic: subscription.topic) + try! await walletNotifyClientA.deleteSubscription(topic: subscription.topic) expectation.fulfill() } }.store(in: &publishers) @@ -141,10 +167,11 @@ final class NotifyTests: XCTestCase { let notifyMessage = NotifyMessage.stub() let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) - try! await walletNotifyClient.register(account: account, onSign: sign) - try! await walletNotifyClient.subscribe(metadata: metadata, account: account) - walletNotifyClient.newSubscriptionPublisher + try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await walletNotifyClientA.subscribe(metadata: metadata, account: account) + + walletNotifyClientA.newSubscriptionPublisher .sink { subscription in let notifier = Publisher() Task(priority: .high) { @@ -153,18 +180,19 @@ final class NotifyTests: XCTestCase { } }.store(in: &publishers) - walletNotifyClient.notifyMessagePublisher + walletNotifyClientA.notifyMessagePublisher .sink { [unowned self] notifyMessageRecord in XCTAssertEqual(notifyMessage, notifyMessageRecord.message) Task(priority: .high) { - try await walletNotifyClient.deleteSubscription(topic: notifyMessageRecord.topic) + try await walletNotifyClientA.deleteSubscription(topic: notifyMessageRecord.topic) messageExpectation.fulfill() } }.store(in: &publishers) wait(for: [subscribeExpectation, messageExpectation], timeout: InputConfig.defaultTimeout) } + } From 6b04c4024b38aaa29efda72e20c8f344772e3b78 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 8 Sep 2023 15:30:28 +0200 Subject: [PATCH 26/91] fix typos --- .../IntegrationTests/Push/NotifyTests.swift | 30 ++++++++++++++----- .../Serialiser/Serializer.swift | 6 +++- .../NetworkingClientFactory.swift | 4 +-- ...WatchSubscriptionsResponseSubscriber.swift | 8 +++-- ...ifyWatchSubscriptionsResponsePayload.swift | 4 +-- 5 files changed, 37 insertions(+), 15 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index bbf4685f8..3281f43e1 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -39,6 +39,7 @@ final class NotifyTests: XCTestCase { let relayLogger = ConsoleLogger(prefix: prefix + " [Relay]", loggingLevel: .debug) let pairingLogger = ConsoleLogger(prefix: prefix + " [Pairing]", loggingLevel: .debug) let networkingLogger = ConsoleLogger(prefix: prefix + " [Networking]", loggingLevel: .debug) + let kmsLogger = ConsoleLogger(prefix: prefix + " [KMS]", loggingLevel: .off) let relayClient = RelayClientFactory.create( relayHost: InputConfig.relayHost, @@ -52,7 +53,8 @@ final class NotifyTests: XCTestCase { relayClient: relayClient, logger: networkingLogger, keychainStorage: keychain, - keyValueStorage: keyValueStorage) + keyValueStorage: keyValueStorage, + kmsLogger: kmsLogger) let pairingClient = PairingClientFactory.create( logger: pairingLogger, @@ -113,20 +115,34 @@ final class NotifyTests: XCTestCase { let expectation = expectation(description: "expects client B to receive subscription created by client A") let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) - try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await walletNotifyClientA.subscribe(metadata: metadata, account: account, onSign: sign) - - sleep(2) let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ") + try! await walletNotifyClientA.register(account: account, onSign: sign) try! await clientB.register(account: account, onSign: sign) + sleep(2) + + clientB.subscriptionsPublisher.sink { subscriptions in Task(priority: .high) { - try! await clientB.deleteSubscription(topic: subscriptions.first!.topic) - expectation.fulfill() + print(subscriptions) + print("_________") +// try! await clientB.deleteSubscription(topic: subscriptions.first!.topic) +// expectation.fulfill() } }.store(in: &publishers) + + walletNotifyClientA.newSubscriptionPublisher + .sink { [unowned self] subscription in + Task(priority: .high) { + print(subscription) + print("_________") + } + }.store(in: &publishers) + + try! await walletNotifyClientA.subscribe(metadata: metadata, account: account, onSign: sign) + + wait(for: [expectation], timeout: InputConfig.defaultTimeout) diff --git a/Sources/WalletConnectKMS/Serialiser/Serializer.swift b/Sources/WalletConnectKMS/Serialiser/Serializer.swift index 7a3dcf739..aed1406bd 100644 --- a/Sources/WalletConnectKMS/Serialiser/Serializer.swift +++ b/Sources/WalletConnectKMS/Serialiser/Serializer.swift @@ -107,11 +107,15 @@ public class Serializer: Serializing { } private func decode(sealbox: Data, symmetricKey: Data) throws -> (T, Data) { + var decryptedData = Data() + print(T.self) do { - let decryptedData = try codec.decode(sealbox: sealbox, symmetricKey: symmetricKey) + decryptedData = try codec.decode(sealbox: sealbox, symmetricKey: symmetricKey) let decodedType = try JSONDecoder().decode(T.self, from: decryptedData) return (decodedType, decryptedData) } catch { + let str = String(decoding: decryptedData, as: UTF8.self) + print(str) logger.error("Failed to decode with error: \(error)") throw error } diff --git a/Sources/WalletConnectNetworking/NetworkingClientFactory.swift b/Sources/WalletConnectNetworking/NetworkingClientFactory.swift index 4470087d1..a5119544f 100644 --- a/Sources/WalletConnectNetworking/NetworkingClientFactory.swift +++ b/Sources/WalletConnectNetworking/NetworkingClientFactory.swift @@ -9,10 +9,10 @@ public struct NetworkingClientFactory { return NetworkingClientFactory.create(relayClient: relayClient, logger: logger, keychainStorage: keychainStorage, keyValueStorage: keyValueStorage) } - public static func create(relayClient: RelayClient, logger: ConsoleLogging, keychainStorage: KeychainStorageProtocol, keyValueStorage: KeyValueStorage) -> NetworkingInteractor { + public static func create(relayClient: RelayClient, logger: ConsoleLogging, keychainStorage: KeychainStorageProtocol, keyValueStorage: KeyValueStorage, kmsLogger: ConsoleLogging = ConsoleLogger(prefix: "🔐", loggingLevel: .off)) -> NetworkingInteractor { let kms = KeyManagementService(keychain: keychainStorage) - let serializer = Serializer(kms: kms, logger: ConsoleLogger(prefix: "🔐", loggingLevel: .off)) + let serializer = Serializer(kms: kms, logger: kmsLogger) let rpcHistory = RPCHistoryFactory.createForNetwork(keyValueStorage: keyValueStorage) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 1979eb643..cadc8045f 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -26,17 +26,19 @@ class NotifyWatchSubscriptionsResponseSubscriber { private func subscribeForWatchSubscriptionsResponse() { - let protocolMethod = NotifySubscribeProtocolMethod() + let protocolMethod = NotifyWatchSubscriptionsProtocolMethod() networkingInteractor.responseSubscription(on: protocolMethod) .sink { [unowned self] (payload: ResponseSubscriptionPayload) in Task(priority: .high) { logger.debug("Received Notify Watch Subscriptions response") + guard let (responsePayload, _) = try? NotifyWatchSubscriptionsResponsePayload.decodeAndVerify(from: payload.response), - let account = responsePayload.subscriptions.first?.account + let (watchSubscriptionPayloadRequest, _) = try? NotifyWatchSubscriptionsPayload.decodeAndVerify(from: payload.request) else { fatalError() /* TODO: Handle error */ } + let account = watchSubscriptionPayloadRequest.subscriptionAccount // todo varify signature with notify server diddoc authentication key let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions) @@ -49,7 +51,7 @@ class NotifyWatchSubscriptionsResponseSubscriber { logProperties[key] = subscription.topic } - logger.debug("Updated Subscriptions by Watch Subscriptions Update", properties: logProperties) + logger.debug("Updated Subscriptions with Watch Subscriptions Update, number of subscriptions: \(subscriptions.count)", properties: logProperties) } }.store(in: &publishers) diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift index 526c3a13b..26ad43a99 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift @@ -6,7 +6,7 @@ struct NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { let iat: UInt64 /// Timestamp when JWT must expire let exp: UInt64 - /// Description of action intent. Must be equal to `notify_watch_subscriptions` + /// Description of action intent. Must be equal to `notify_watch_subscriptions_response` let act: String? /// `did:key` of Notify Server authentication key @@ -17,7 +17,7 @@ struct NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { let sbs: [NotifyServerSubscription] static var action: String? { - return "notify_watch_subscriptions" + return "notify_watch_subscriptions_response" } } From 9562c82c1e06299131235a2c3c9c2bd0a7051a56 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 8 Sep 2023 15:55:52 +0200 Subject: [PATCH 27/91] savepoint --- .../IntegrationTests/Push/NotifyTests.swift | 21 +++++++++++-------- ...fySubscriptionsChangedRequestPayload.swift | 2 +- ...ySubscriptionsChangedResponsePayload.swift | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index 3281f43e1..818961f8e 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -18,7 +18,7 @@ final class NotifyTests: XCTestCase { var walletNotifyClientA: NotifyClient! - let gmDappUrl = "https://notify.gm.walletconnect.com/" + let gmDappUrl = "https://dev.gm.walletconnect.com/" let pk = try! EthereumPrivateKey() @@ -116,18 +116,15 @@ final class NotifyTests: XCTestCase { let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ") - try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await clientB.register(account: account, onSign: sign) - sleep(2) - - - clientB.subscriptionsPublisher.sink { subscriptions in Task(priority: .high) { print(subscriptions) + if !subscriptions.isEmpty { + expectation.fulfill() + } print("_________") -// try! await clientB.deleteSubscription(topic: subscriptions.first!.topic) -// expectation.fulfill() + // try! await clientB.deleteSubscription(topic: subscriptions.first!.topic) + // expectation.fulfill() } }.store(in: &publishers) @@ -139,6 +136,12 @@ final class NotifyTests: XCTestCase { print("_________") } }.store(in: &publishers) + try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await clientB.register(account: account, onSign: sign) + sleep(2) + + + try! await walletNotifyClientA.subscribe(metadata: metadata, account: account, onSign: sign) diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift index 41b4464dc..bc436c265 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift @@ -17,7 +17,7 @@ struct NotifySubscriptionsChangedRequestPayload: JWTClaimsCodable { let sbs: [NotifyServerSubscription] static var action: String? { - return "subscriptionsChangedAuth" + return "notify_subscriptions_changed" } } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift index af1b703a3..949a1bab8 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift @@ -17,7 +17,7 @@ struct NotifySubscriptionsChangedResponsePayload: JWTClaimsCodable { let aud: String static var action: String? { - return "notify_watch_subscriptions" + return "notify_subscriptions_changed_response" } } From e31bfc1f91ad1b27701806d9279bcda38f21efa1 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 8 Sep 2023 22:06:04 +0200 Subject: [PATCH 28/91] fix testNotifyWatchSubscriptions --- .../IntegrationTests/Push/NotifyTests.swift | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index 818961f8e..b27551b29 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -39,7 +39,7 @@ final class NotifyTests: XCTestCase { let relayLogger = ConsoleLogger(prefix: prefix + " [Relay]", loggingLevel: .debug) let pairingLogger = ConsoleLogger(prefix: prefix + " [Pairing]", loggingLevel: .debug) let networkingLogger = ConsoleLogger(prefix: prefix + " [Networking]", loggingLevel: .debug) - let kmsLogger = ConsoleLogger(prefix: prefix + " [KMS]", loggingLevel: .off) + let kmsLogger = ConsoleLogger(prefix: prefix + " [KMS]", loggingLevel: .debug) let relayClient = RelayClientFactory.create( relayHost: InputConfig.relayHost, @@ -118,37 +118,20 @@ final class NotifyTests: XCTestCase { let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ") clientB.subscriptionsPublisher.sink { subscriptions in Task(priority: .high) { - print(subscriptions) if !subscriptions.isEmpty { expectation.fulfill() } - print("_________") - // try! await clientB.deleteSubscription(topic: subscriptions.first!.topic) - // expectation.fulfill() } }.store(in: &publishers) - - walletNotifyClientA.newSubscriptionPublisher - .sink { [unowned self] subscription in - Task(priority: .high) { - print(subscription) - print("_________") - } - }.store(in: &publishers) try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await clientB.register(account: account, onSign: sign) - sleep(2) - - try! await walletNotifyClientA.subscribe(metadata: metadata, account: account, onSign: sign) - + sleep(1) + try! await clientB.register(account: account, onSign: sign) wait(for: [expectation], timeout: InputConfig.defaultTimeout) - - } func testWalletCreatesAndUpdatesSubscription() async { From 452166141c7c3273bb198c94366691a8092504b4 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 10 Sep 2023 12:19:02 +0200 Subject: [PATCH 29/91] add testNotifySubscriptionChanged --- .../IntegrationTests/Push/NotifyTests.swift | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index b27551b29..bbfb92cc6 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -110,7 +110,6 @@ final class NotifyTests: XCTestCase { wait(for: [expectation], timeout: InputConfig.defaultTimeout) } - func testNotifyWatchSubscriptions() async throws { let expectation = expectation(description: "expects client B to receive subscription created by client A") let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) @@ -133,6 +132,28 @@ final class NotifyTests: XCTestCase { wait(for: [expectation], timeout: InputConfig.defaultTimeout) } + + func testNotifySubscriptionChanged() async throws { + let expectation = expectation(description: "expects client B to receive subscription after both clients are registered and client A creates one") + let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) + + let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ") + clientB.subscriptionsPublisher.sink { subscriptions in + Task(priority: .high) { + if !subscriptions.isEmpty { + expectation.fulfill() + } + } + }.store(in: &publishers) + + try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await clientB.register(account: account, onSign: sign) + + sleep(1) + try! await walletNotifyClientA.subscribe(metadata: metadata, account: account, onSign: sign) + + wait(for: [expectation], timeout: InputConfig.defaultTimeout) + } func testWalletCreatesAndUpdatesSubscription() async { let expectation = expectation(description: "expects to create and update notify subscription") From ce6774b9aef77595f556b36099ed7be5166e8b35 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 10 Sep 2023 13:18:31 +0200 Subject: [PATCH 30/91] enable watch subscriptions --- Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift | 5 ++++- .../Client/Wallet/NotifyClientFactory.swift | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 84fbbeaa3..d754293eb 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -48,6 +48,7 @@ public class NotifyClient { private let subscriptionsAutoUpdater: SubscriptionsAutoUpdater private let notifyWatchSubscriptionsRequester: NotifyWatchSubscriptionsRequester private let notifyWatchSubscriptionsResponseSubscriber: NotifyWatchSubscriptionsResponseSubscriber + private let notifySubscriptionsChangedRequestSubscriber: NotifySubscriptionsChangedRequestSubscriber init(logger: ConsoleLogging, kms: KeyManagementServiceProtocol, @@ -64,7 +65,8 @@ public class NotifyClient { notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber, subscriptionsAutoUpdater: SubscriptionsAutoUpdater, notifyWatchSubscriptionsRequester: NotifyWatchSubscriptionsRequester, - notifyWatchSubscriptionsResponseSubscriber: NotifyWatchSubscriptionsResponseSubscriber + notifyWatchSubscriptionsResponseSubscriber: NotifyWatchSubscriptionsResponseSubscriber, + notifySubscriptionsChangedRequestSubscriber: NotifySubscriptionsChangedRequestSubscriber ) { self.logger = logger self.pushClient = pushClient @@ -81,6 +83,7 @@ public class NotifyClient { self.subscriptionsAutoUpdater = subscriptionsAutoUpdater self.notifyWatchSubscriptionsRequester = notifyWatchSubscriptionsRequester self.notifyWatchSubscriptionsResponseSubscriber = notifyWatchSubscriptionsResponseSubscriber + self.notifySubscriptionsChangedRequestSubscriber = notifySubscriptionsChangedRequestSubscriber } public func register(account: Account, onSign: @escaping SigningCallback) async throws { diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index ea25761a2..fcc250ee0 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -61,6 +61,7 @@ public struct NotifyClientFactory { let notifyWatchSubscriptionsRequester = NotifyWatchSubscriptionsRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, webDidResolver: webDidResolver) let notifySubscriptionsBuilder = NotifySubscriptionsBuilder(subscriptionScopeProvider: subscriptionScopeProvider) let notifyWatchSubscriptionsResponseSubscriber = NotifyWatchSubscriptionsResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) + let notifySubscriptionsChangedRequestSubscriber = NotifySubscriptionsChangedRequestSubscriber(keyserver: keyserverURL, networkingInteractor: networkInteractor, kms: kms, identityClient: identityClient, logger: logger, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) return NotifyClient( logger: logger, @@ -78,7 +79,8 @@ public struct NotifyClientFactory { notifyUpdateResponseSubscriber: notifyUpdateResponseSubscriber, subscriptionsAutoUpdater: subscriptionsAutoUpdater, notifyWatchSubscriptionsRequester: notifyWatchSubscriptionsRequester, - notifyWatchSubscriptionsResponseSubscriber: notifyWatchSubscriptionsResponseSubscriber + notifyWatchSubscriptionsResponseSubscriber: notifyWatchSubscriptionsResponseSubscriber, + notifySubscriptionsChangedRequestSubscriber: notifySubscriptionsChangedRequestSubscriber ) } } From 7b12498b878dff017231cad84916363bb5cc2d06 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 10 Sep 2023 17:01:18 +0200 Subject: [PATCH 31/91] fix sub changed test --- Example/IntegrationTests/Push/NotifyTests.swift | 1 + ...NotifySubscriptionsChangedRequestSubscriber.swift | 4 ++-- .../NotifySubscriptionsChangedRequestPayload.swift | 12 +++++++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index bbfb92cc6..225db9a78 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -135,6 +135,7 @@ final class NotifyTests: XCTestCase { func testNotifySubscriptionChanged() async throws { let expectation = expectation(description: "expects client B to receive subscription after both clients are registered and client A creates one") + expectation.assertForOverFulfill = true let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ") diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 9773972ba..6e068dfb2 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -41,9 +41,9 @@ class NotifySubscriptionsChangedRequestSubscriber { logger.debug("Received Subscriptions Changed Request") guard - let (jwtPayload, _) = try? NotifySubscriptionsChangedRequestPayload.decodeAndVerify(from: payload.request), - let account = jwtPayload.subscriptions.first?.account + let (jwtPayload, _) = try? NotifySubscriptionsChangedRequestPayload.decodeAndVerify(from: payload.request) else { fatalError() /* TODO: Handle error */ } + let account = jwtPayload.account // todo varify signature with notify server diddoc authentication key diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift index bc436c265..f3dbc3f3c 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift @@ -6,13 +6,15 @@ struct NotifySubscriptionsChangedRequestPayload: JWTClaimsCodable { let iat: UInt64 /// Timestamp when JWT must expire let exp: UInt64 - /// Action intent (must be `notify_subscriptions_changed`) + /// Action intent (must be `notify_subscriptions_changed_request`) let act: String? /// `did:key` of an identity key. Enables to resolve associated Dapp domain used. diddoc authentication key let iss: String /// Blockchain account `did:pkh` let aud: String + /// message sent by the author account + let sub: String /// array of Notify Server Subscriptions let sbs: [NotifyServerSubscription] @@ -22,14 +24,14 @@ struct NotifySubscriptionsChangedRequestPayload: JWTClaimsCodable { } struct Wrapper: JWTWrapper { - let messageAuth: String + let subscriptionsChangedAuth: String init(jwtString: String) { - self.messageAuth = jwtString + self.subscriptionsChangedAuth = jwtString } var jwtString: String { - return messageAuth + return subscriptionsChangedAuth } } @@ -40,7 +42,7 @@ struct NotifySubscriptionsChangedRequestPayload: JWTClaimsCodable { init(claims: Claims) throws { self.notifyServerAuthenticationKey = try DIDKey(did: claims.iss) self.subscriptions = claims.sbs - self.account = try DIDPKH(did: claims.aud).account + self.account = try DIDPKH(did: claims.sub).account } func encode(iss: String) throws -> Claims { From b0ee927f4abab4a5a4a01453fc3c46969bd43a88 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 09:28:56 +0200 Subject: [PATCH 32/91] fix tests --- Example/IntegrationTests/Push/NotifyTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index 225db9a78..22ceefa28 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -112,6 +112,7 @@ final class NotifyTests: XCTestCase { func testNotifyWatchSubscriptions() async throws { let expectation = expectation(description: "expects client B to receive subscription created by client A") + expectation.assertForOverFulfill = false let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ") @@ -135,7 +136,7 @@ final class NotifyTests: XCTestCase { func testNotifySubscriptionChanged() async throws { let expectation = expectation(description: "expects client B to receive subscription after both clients are registered and client A creates one") - expectation.assertForOverFulfill = true + expectation.assertForOverFulfill = false let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ") From 0f0b388d893821df7565e92b1704c2fbb3b965dc Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 10:02:26 +0200 Subject: [PATCH 33/91] update act in notify message --- .../Types/JWTPayloads/NotifyMessageReceiptPayload.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift index 57934d03c..b5aacf956 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift @@ -9,7 +9,7 @@ struct NotifyMessageReceiptPayload: JWTClaimsCodable { let exp: UInt64 /// Key server URL let ksu: String - /// Action intent (must be `notify_receipt`) + /// Action intent (must be `notify_message_response`) let act: String? /// `did:key` of an identity key. Enables to resolve attached blockchain account. @@ -22,7 +22,7 @@ struct NotifyMessageReceiptPayload: JWTClaimsCodable { let app: String static var action: String? { - return "notify_receipt" + return "notify_message_response" } } From 1a9e5164eecaa2abecf4671ef97bde7c150e03f7 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 11:27:34 +0200 Subject: [PATCH 34/91] savepoint --- Example/IntegrationTests/Push/NotifyTests.swift | 14 +++++--------- .../Client/Wallet/NotifyClient.swift | 4 ++-- .../Client/Wallet/NotifyClientFactory.swift | 12 ++++++------ ...peProvider.swift => NotifyConfigProvider.swift} | 2 +- .../Client/Wallet/NotifySubscriptionsBuilder.swift | 10 +++++----- .../wc_notifyUpdate/NotifyUpdateRequester.swift | 6 +++--- .../NotifyUpdateResponseSubscriber.swift | 8 ++++---- .../NotifySubscribeRequester.swift | 14 +++++++------- .../NotifySubscribeResponseSubscriber.swift | 12 +++++------- ...ift => NotifySubscriptionsChangedRequest.swift} | 0 .../NotifyWatchSubscriptionsProtocolMethod.swift | 2 +- 11 files changed, 39 insertions(+), 45 deletions(-) rename Sources/WalletConnectNotify/Client/Wallet/{SubscriptionScopeProvider.swift => NotifyConfigProvider.swift} (97%) rename Sources/WalletConnectNotify/ProtocolMethods/{ NotifySubscriptionsChangedRequest.swift => NotifySubscriptionsChangedRequest.swift} (100%) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index 22ceefa28..8bd50890a 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -94,7 +94,6 @@ final class NotifyTests: XCTestCase { func testWalletCreatesSubscription() async { let expectation = expectation(description: "expects to create notify subscription") - let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) walletNotifyClientA.newSubscriptionPublisher .sink { [unowned self] subscription in @@ -105,7 +104,7 @@ final class NotifyTests: XCTestCase { }.store(in: &publishers) try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await walletNotifyClientA.subscribe(metadata: metadata, account: account) + try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } @@ -113,7 +112,6 @@ final class NotifyTests: XCTestCase { func testNotifyWatchSubscriptions() async throws { let expectation = expectation(description: "expects client B to receive subscription created by client A") expectation.assertForOverFulfill = false - let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ") clientB.subscriptionsPublisher.sink { subscriptions in @@ -127,7 +125,7 @@ final class NotifyTests: XCTestCase { try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await walletNotifyClientA.subscribe(metadata: metadata, account: account, onSign: sign) + try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account, onSign: sign) sleep(1) try! await clientB.register(account: account, onSign: sign) @@ -137,7 +135,6 @@ final class NotifyTests: XCTestCase { func testNotifySubscriptionChanged() async throws { let expectation = expectation(description: "expects client B to receive subscription after both clients are registered and client A creates one") expectation.assertForOverFulfill = false - let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ") clientB.subscriptionsPublisher.sink { subscriptions in @@ -152,18 +149,17 @@ final class NotifyTests: XCTestCase { try! await clientB.register(account: account, onSign: sign) sleep(1) - try! await walletNotifyClientA.subscribe(metadata: metadata, account: account, onSign: sign) + try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account, onSign: sign) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } func testWalletCreatesAndUpdatesSubscription() async { let expectation = expectation(description: "expects to create and update notify subscription") - let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) let updateScope: Set = ["alerts"] try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await walletNotifyClientA.subscribe(metadata: metadata, account: account) + try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account) walletNotifyClientA.newSubscriptionPublisher .sink { [unowned self] subscription in @@ -194,7 +190,7 @@ final class NotifyTests: XCTestCase { let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await walletNotifyClientA.subscribe(metadata: metadata, account: account) + try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account walletNotifyClientA.newSubscriptionPublisher .sink { subscription in diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index d754293eb..95b624924 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -95,8 +95,8 @@ public class NotifyClient { logger.setLogging(level: level) } - public func subscribe(metadata: AppMetadata, account: Account) async throws { - try await notifySubscribeRequester.subscribe(metadata: metadata, account: account) + public func subscribe(dappUrl: String, account: Account) async throws { + try await notifySubscribeRequester.subscribe(dappUrl: dappUrl, account: account) } public func update(topic: String, scope: Set) async throws { diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index fcc250ee0..16d37908d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -44,22 +44,22 @@ public struct NotifyClientFactory { let resubscribeService = NotifyResubscribeService(networkInteractor: networkInteractor, notifyStorage: notifyStorage, logger: logger) let dappsMetadataStore = CodableStore(defaults: keyValueStorage, identifier: NotifyStorageIdntifiers.dappsMetadataStore) - let subscriptionScopeProvider = SubscriptionScopeProvider() + let notifyConfigProvider = NotifyConfigProvider() - let notifySubscribeRequester = NotifySubscribeRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, webDidResolver: webDidResolver, subscriptionScopeProvider: subscriptionScopeProvider, dappsMetadataStore: dappsMetadataStore) + let notifySubscribeRequester = NotifySubscribeRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, webDidResolver: webDidResolver, notifyConfigProvider: notifyConfigProvider, dappsMetadataStore: dappsMetadataStore) - let notifySubscribeResponseSubscriber = NotifySubscribeResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, groupKeychainStorage: groupKeychainStorage, notifyStorage: notifyStorage, dappsMetadataStore: dappsMetadataStore, subscriptionScopeProvider: subscriptionScopeProvider) + let notifySubscribeResponseSubscriber = NotifySubscribeResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, groupKeychainStorage: groupKeychainStorage, notifyStorage: notifyStorage, dappsMetadataStore: dappsMetadataStore, notifyConfigProvider: notifyConfigProvider) - let notifyUpdateRequester = NotifyUpdateRequester(keyserverURL: keyserverURL, webDidResolver: webDidResolver, identityClient: identityClient, networkingInteractor: networkInteractor, subscriptionScopeProvider: subscriptionScopeProvider, logger: logger, notifyStorage: notifyStorage) + let notifyUpdateRequester = NotifyUpdateRequester(keyserverURL: keyserverURL, webDidResolver: webDidResolver, identityClient: identityClient, networkingInteractor: networkInteractor, notifyConfigProvider: notifyConfigProvider, logger: logger, notifyStorage: notifyStorage) - let notifyUpdateResponseSubscriber = NotifyUpdateResponseSubscriber(networkingInteractor: networkInteractor, logger: logger, subscriptionScopeProvider: subscriptionScopeProvider, notifyStorage: notifyStorage) + let notifyUpdateResponseSubscriber = NotifyUpdateResponseSubscriber(networkingInteractor: networkInteractor, logger: logger, notifyConfigProvider: notifyConfigProvider, notifyStorage: notifyStorage) let deleteNotifySubscriptionSubscriber = DeleteNotifySubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage) let subscriptionsAutoUpdater = SubscriptionsAutoUpdater(notifyUpdateRequester: notifyUpdateRequester, logger: logger, notifyStorage: notifyStorage) let notifyWatchSubscriptionsRequester = NotifyWatchSubscriptionsRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, webDidResolver: webDidResolver) - let notifySubscriptionsBuilder = NotifySubscriptionsBuilder(subscriptionScopeProvider: subscriptionScopeProvider) + let notifySubscriptionsBuilder = NotifySubscriptionsBuilder(notifyConfigProvider: notifyConfigProvider) let notifyWatchSubscriptionsResponseSubscriber = NotifyWatchSubscriptionsResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) let notifySubscriptionsChangedRequestSubscriber = NotifySubscriptionsChangedRequestSubscriber(keyserver: keyserverURL, networkingInteractor: networkInteractor, kms: kms, identityClient: identityClient, logger: logger, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) diff --git a/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift similarity index 97% rename from Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift rename to Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift index 65db81fd6..4646f5f76 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/SubscriptionScopeProvider.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift @@ -1,7 +1,7 @@ import Foundation -actor SubscriptionScopeProvider { +actor NotifyConfigProvider { enum Errors: Error { case invalidUrl } diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift index 58f74ac59..24cc45cff 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift @@ -1,10 +1,10 @@ import Foundation class NotifySubscriptionsBuilder { - private let subscriptionScopeProvider: SubscriptionScopeProvider + private let notifyConfigProvider: NotifyConfigProvider - init(subscriptionScopeProvider: SubscriptionScopeProvider) { - self.subscriptionScopeProvider = subscriptionScopeProvider + init(notifyConfigProvider: NotifyConfigProvider) { + self.notifyConfigProvider = notifyConfigProvider } func buildSubscriptions(_ notifyServerSubscriptions: [NotifyServerSubscription]) async throws -> [NotifySubscription] { @@ -12,7 +12,7 @@ class NotifySubscriptionsBuilder { for subscription in notifyServerSubscriptions { let scope = try await buildScope(selectedScope: subscription.scope, dappUrl: subscription.dappUrl) - guard let metadata = try? await subscriptionScopeProvider.getMetadata(dappUrl: subscription.dappUrl), + guard let metadata = try? await notifyConfigProvider.getMetadata(dappUrl: subscription.dappUrl), let topic = try? SymmetricKey(hex: subscription.symKey).derivedTopic() else { continue } let notifySubscription = NotifySubscription(topic: topic, @@ -29,7 +29,7 @@ class NotifySubscriptionsBuilder { } private func buildScope(selectedScope: [String], dappUrl: String) async throws -> [String: ScopeValue] { - let availableScope = try await subscriptionScopeProvider.getSubscriptionScope(dappUrl: dappUrl) + let availableScope = try await notifyConfigProvider.getSubscriptionScope(dappUrl: dappUrl) return availableScope.reduce(into: [:]) { $0[$1.name] = ScopeValue(description: $1.description, enabled: selectedScope.contains($1.name)) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift index 21c3c87c0..33b850f4d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift @@ -13,7 +13,7 @@ class NotifyUpdateRequester: NotifyUpdateRequesting { private let webDidResolver: WebDidResolver private let identityClient: IdentityClient private let networkingInteractor: NetworkInteracting - private let subscriptionScopeProvider: SubscriptionScopeProvider + private let notifyConfigProvider: NotifyConfigProvider private let logger: ConsoleLogging private let notifyStorage: NotifyStorage @@ -22,7 +22,7 @@ class NotifyUpdateRequester: NotifyUpdateRequesting { webDidResolver: WebDidResolver, identityClient: IdentityClient, networkingInteractor: NetworkInteracting, - subscriptionScopeProvider: SubscriptionScopeProvider, + notifyConfigProvider: NotifyConfigProvider, logger: ConsoleLogging, notifyStorage: NotifyStorage ) { @@ -30,7 +30,7 @@ class NotifyUpdateRequester: NotifyUpdateRequesting { self.webDidResolver = webDidResolver self.identityClient = identityClient self.networkingInteractor = networkingInteractor - self.subscriptionScopeProvider = subscriptionScopeProvider + self.notifyConfigProvider = notifyConfigProvider self.logger = logger self.notifyStorage = notifyStorage } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift index 2b489618b..cd612dc24 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift @@ -6,17 +6,17 @@ class NotifyUpdateResponseSubscriber { private var publishers = [AnyCancellable]() private let logger: ConsoleLogging private let notifyStorage: NotifyStorage - private let subscriptionScopeProvider: SubscriptionScopeProvider + private let nofityConfigProvider: NotifyConfigProvider init(networkingInteractor: NetworkInteracting, logger: ConsoleLogging, - subscriptionScopeProvider: SubscriptionScopeProvider, + notifyConfigProvider: NotifyConfigProvider, notifyStorage: NotifyStorage ) { self.networkingInteractor = networkingInteractor self.logger = logger self.notifyStorage = notifyStorage - self.subscriptionScopeProvider = subscriptionScopeProvider + self.nofityConfigProvider = notifyConfigProvider subscribeForUpdateResponse() } @@ -58,7 +58,7 @@ private extension NotifyUpdateResponseSubscriber { func buildScope(selected: String, dappUrl: String) async throws -> [String: ScopeValue] { let selectedScope = selected.components(separatedBy: " ") - let availableScope = try await subscriptionScopeProvider.getSubscriptionScope(dappUrl: dappUrl) + let availableScope = try await nofityConfigProvider.getSubscriptionScope(dappUrl: dappUrl) return availableScope.reduce(into: [:]) { $0[$1.name] = ScopeValue(description: $1.description, enabled: selectedScope.contains($1.name)) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift index c61efb603..f532dbc30 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift @@ -14,7 +14,7 @@ class NotifySubscribeRequester { private let logger: ConsoleLogging private let webDidResolver: WebDidResolver private let dappsMetadataStore: CodableStore - private let subscriptionScopeProvider: SubscriptionScopeProvider + private let notifyConfigProvider: NotifyConfigProvider init(keyserverURL: URL, networkingInteractor: NetworkInteracting, @@ -22,7 +22,7 @@ class NotifySubscribeRequester { logger: ConsoleLogging, kms: KeyManagementService, webDidResolver: WebDidResolver, - subscriptionScopeProvider: SubscriptionScopeProvider, + notifyConfigProvider: NotifyConfigProvider, dappsMetadataStore: CodableStore ) { self.keyserverURL = keyserverURL @@ -31,16 +31,16 @@ class NotifySubscribeRequester { self.logger = logger self.kms = kms self.webDidResolver = webDidResolver - self.subscriptionScopeProvider = subscriptionScopeProvider self.dappsMetadataStore = dappsMetadataStore + self.notifyConfigProvider = notifyConfigProvider } - @discardableResult func subscribe(metadata: AppMetadata, account: Account) async throws -> NotifySubscriptionPayload.Wrapper { - - let dappUrl = metadata.url + @discardableResult func subscribe(dappUrl: String, account: Account) async throws -> NotifySubscriptionPayload.Wrapper { logger.debug("Subscribing for Notify, dappUrl: \(dappUrl)") + let metadata = try await notifyConfigProvider.getMetadata(dappUrl: dappUrl) + let peerPublicKey = try await webDidResolver.resolveAgreementKey(domain: metadata.url) let subscribeTopic = peerPublicKey.rawRepresentation.sha256().toHexString() @@ -80,7 +80,7 @@ class NotifySubscribeRequester { } private func createJWTWrapper(dappPubKey: DIDKey, subscriptionAccount: Account, dappUrl: String) async throws -> NotifySubscriptionPayload.Wrapper { - let types = try await subscriptionScopeProvider.getSubscriptionScope(dappUrl: dappUrl) + let types = try await notifyConfigProvider.getSubscriptionScope(dappUrl: dappUrl) let scope = types.map{$0.name}.joined(separator: " ") let jwtPayload = NotifySubscriptionPayload(dappPubKey: dappPubKey, keyserver: keyserverURL, subscriptionAccount: subscriptionAccount, dappUrl: dappUrl, scope: scope) return try identityClient.signAndCreateWrapper( diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift index 3642d3420..9fb7e080f 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift @@ -13,7 +13,7 @@ class NotifySubscribeResponseSubscriber { private let notifyStorage: NotifyStorage private let groupKeychainStorage: KeychainStorageProtocol private let dappsMetadataStore: CodableStore - private let subscriptionScopeProvider: SubscriptionScopeProvider + private let notifyConfigProvider: NotifyConfigProvider init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, @@ -21,7 +21,7 @@ class NotifySubscribeResponseSubscriber { groupKeychainStorage: KeychainStorageProtocol, notifyStorage: NotifyStorage, dappsMetadataStore: CodableStore, - subscriptionScopeProvider: SubscriptionScopeProvider + notifyConfigProvider: NotifyConfigProvider ) { self.networkingInteractor = networkingInteractor self.kms = kms @@ -29,7 +29,7 @@ class NotifySubscribeResponseSubscriber { self.groupKeychainStorage = groupKeychainStorage self.notifyStorage = notifyStorage self.dappsMetadataStore = dappsMetadataStore - self.subscriptionScopeProvider = subscriptionScopeProvider + self.notifyConfigProvider = notifyConfigProvider subscribeForSubscriptionResponse() } @@ -42,9 +42,7 @@ class NotifySubscribeResponseSubscriber { ) { [unowned self] payload in logger.debug("Received Notify Subscribe response") - guard - let (responsePayload, _) = try? NotifySubscriptionResponsePayload.decodeAndVerify(from: payload.response) - else { fatalError() /* TODO: Handle error */ } + let (responsePayload, _) = try NotifySubscriptionResponsePayload.decodeAndVerify(from: payload.response) guard let responseKeys = kms.getAgreementSecret(for: payload.topic) else { logger.debug("No symmetric key for topic \(payload.topic)") @@ -71,7 +69,7 @@ class NotifySubscribeResponseSubscriber { try groupKeychainStorage.add(agreementKeysP, forKey: notifySubscriptionTopic) account = try Account(DIDPKHString: claims.sub) metadata = try dappsMetadataStore.get(key: payload.topic) - let availableTypes = try await subscriptionScopeProvider.getSubscriptionScope(dappUrl: metadata!.url) + let availableTypes = try await notifyConfigProvider.getSubscriptionScope(dappUrl: metadata!.url) subscribedTypes = availableTypes.filter{subscribedScope.contains($0.name)} logger.debug("NotifySubscribeResponseSubscriber: subscribing notify subscription topic: \(notifySubscriptionTopic!)") try await networkingInteractor.subscribe(topic: notifySubscriptionTopic) diff --git a/Sources/WalletConnectNotify/ProtocolMethods/ NotifySubscriptionsChangedRequest.swift b/Sources/WalletConnectNotify/ProtocolMethods/NotifySubscriptionsChangedRequest.swift similarity index 100% rename from Sources/WalletConnectNotify/ProtocolMethods/ NotifySubscriptionsChangedRequest.swift rename to Sources/WalletConnectNotify/ProtocolMethods/NotifySubscriptionsChangedRequest.swift diff --git a/Sources/WalletConnectNotify/ProtocolMethods/NotifyWatchSubscriptionsProtocolMethod.swift b/Sources/WalletConnectNotify/ProtocolMethods/NotifyWatchSubscriptionsProtocolMethod.swift index 479538836..a1a4db3a2 100644 --- a/Sources/WalletConnectNotify/ProtocolMethods/NotifyWatchSubscriptionsProtocolMethod.swift +++ b/Sources/WalletConnectNotify/ProtocolMethods/NotifyWatchSubscriptionsProtocolMethod.swift @@ -3,7 +3,7 @@ import Foundation struct NotifyWatchSubscriptionsProtocolMethod: ProtocolMethod { let method: String = "wc_notifyWatchSubscriptions" - let requestConfig: RelayConfig = RelayConfig(tag: 4010, prompt: false, ttl: 30) + let requestConfig: RelayConfig = RelayConfig(tag: 4010, prompt: false, ttl: 300) let responseConfig: RelayConfig = RelayConfig(tag: 4011, prompt: false, ttl: 300) } From 8583b75776bd7dd04e260f2ec9284746bfdfe8b9 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 11 Sep 2023 18:30:19 +0800 Subject: [PATCH 35/91] Web3Inbox repaired --- Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift index 51481a2b7..c3f837559 100644 --- a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift +++ b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift @@ -25,7 +25,7 @@ final class NotifyClientProxy { try await respond(request: request) case .subscribe: let params = try parse(SubscribeRequest.self, params: request.params) - try await client.subscribe(metadata: params.metadata, account: params.account) + try await client.subscribe(dappUrl: params.dappUrl, account: params.account) try await respond(request: request) case .getActiveSubscriptions: let subscriptions = client.getActiveSubscriptions() @@ -73,7 +73,7 @@ private extension NotifyClientProxy { } struct SubscribeRequest: Codable { - let metadata: AppMetadata + let dappUrl: String let account: Account } From 335a66701152f1407a554f9fc359e7e4a383f5b8 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 11 Sep 2023 17:18:25 +0800 Subject: [PATCH 36/91] Apply new networking changes --- ...ubscriptionsChangedRequestSubscriber.swift | 18 +++----- ...WatchSubscriptionsResponseSubscriber.swift | 44 ++++++++----------- 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 6e068dfb2..1f05e7126 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -6,7 +6,6 @@ class NotifySubscriptionsChangedRequestSubscriber { private let networkingInteractor: NetworkInteracting private let identityClient: IdentityClient private let kms: KeyManagementServiceProtocol - private var publishers = [AnyCancellable]() private let logger: ConsoleLogging private let notifyStorage: NotifyStorage private let notifySubscriptionsBuilder: NotifySubscriptionsBuilder @@ -32,17 +31,13 @@ class NotifySubscriptionsChangedRequestSubscriber { private func subscribeForNofifyChangedRequests() { - let protocolMethod = NotifySubscriptionsChangedProtocolMethod() - - networkingInteractor.requestSubscription(on: protocolMethod).sink { [unowned self] (payload: RequestSubscriptionPayload) in - - - Task(priority: .high) { + networkingInteractor.subscribeOnRequest( + protocolMethod: NotifySubscriptionsChangedProtocolMethod(), + requestOfType: NotifySubscriptionsChangedRequestPayload.Wrapper.self, + errorHandler: logger) { [unowned self] payload in logger.debug("Received Subscriptions Changed Request") - guard - let (jwtPayload, _) = try? NotifySubscriptionsChangedRequestPayload.decodeAndVerify(from: payload.request) - else { fatalError() /* TODO: Handle error */ } + let (jwtPayload, _) = try NotifySubscriptionsChangedRequestPayload.decodeAndVerify(from: payload.request) let account = jwtPayload.account // todo varify signature with notify server diddoc authentication key @@ -60,10 +55,7 @@ class NotifySubscriptionsChangedRequestSubscriber { logger.debug("Updated Subscriptions by Subscriptions Changed Request", properties: logProperties) try await respond(topic: payload.topic, account: jwtPayload.account, rpcId: payload.id, notifyServerAuthenticationKey: jwtPayload.notifyServerAuthenticationKey) - } - - }.store(in: &publishers) } private func respond(topic: String, account: Account, rpcId: RPCID, notifyServerAuthenticationKey: DIDKey) async throws { diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index cadc8045f..44a2697c6 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -4,7 +4,6 @@ import Combine class NotifyWatchSubscriptionsResponseSubscriber { private let networkingInteractor: NetworkInteracting private let kms: KeyManagementServiceProtocol - private var publishers = [AnyCancellable]() private let logger: ConsoleLogging private let notifyStorage: NotifyStorage private let notifySubscriptionsBuilder: NotifySubscriptionsBuilder @@ -25,36 +24,31 @@ class NotifyWatchSubscriptionsResponseSubscriber { private func subscribeForWatchSubscriptionsResponse() { + networkingInteractor.subscribeOnResponse( + protocolMethod: NotifyWatchSubscriptionsProtocolMethod(), + requestOfType: NotifyWatchSubscriptionsPayload.Wrapper.self, + responseOfType: NotifyWatchSubscriptionsResponsePayload.Wrapper.self, + errorHandler: logger) { [unowned self] payload in + logger.debug("Received Notify Watch Subscriptions response") - let protocolMethod = NotifyWatchSubscriptionsProtocolMethod() - networkingInteractor.responseSubscription(on: protocolMethod) - .sink { [unowned self] (payload: ResponseSubscriptionPayload) in - Task(priority: .high) { - logger.debug("Received Notify Watch Subscriptions response") + let (responsePayload, _) = try NotifyWatchSubscriptionsResponsePayload.decodeAndVerify(from: payload.response) + let (watchSubscriptionPayloadRequest, _) = try NotifyWatchSubscriptionsPayload.decodeAndVerify(from: payload.request) + let account = watchSubscriptionPayloadRequest.subscriptionAccount + // todo varify signature with notify server diddoc authentication key - guard - let (responsePayload, _) = try? NotifyWatchSubscriptionsResponsePayload.decodeAndVerify(from: payload.response), - let (watchSubscriptionPayloadRequest, _) = try? NotifyWatchSubscriptionsPayload.decodeAndVerify(from: payload.request) - else { fatalError() /* TODO: Handle error */ } + let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions) - let account = watchSubscriptionPayloadRequest.subscriptionAccount - // todo varify signature with notify server diddoc authentication key - - let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions) - - notifyStorage.replaceAllSubscriptions(subscriptions, account: account) - - var logProperties = [String: String]() - for (index, subscription) in subscriptions.enumerated() { - let key = "subscription_\(index + 1)" - logProperties[key] = subscription.topic - } - - logger.debug("Updated Subscriptions with Watch Subscriptions Update, number of subscriptions: \(subscriptions.count)", properties: logProperties) + notifyStorage.replaceAllSubscriptions(subscriptions, account: account) + var logProperties = [String: String]() + for (index, subscription) in subscriptions.enumerated() { + let key = "subscription_\(index + 1)" + logProperties[key] = subscription.topic } - }.store(in: &publishers) + + logger.debug("Updated Subscriptions with Watch Subscriptions Update, number of subscriptions: \(subscriptions.count)", properties: logProperties) + } } } From cc0348d2bb61dfb3b47abd9b4b8f831fb5695ad5 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 11 Sep 2023 18:35:54 +0800 Subject: [PATCH 37/91] Integration tests fixed --- Example/IntegrationTests/Push/NotifyTests.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index 8bd50890a..d3ee4da62 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -123,10 +123,10 @@ final class NotifyTests: XCTestCase { }.store(in: &publishers) try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account) - - try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account, onSign: sign) sleep(1) + try! await clientB.register(account: account, onSign: sign) wait(for: [expectation], timeout: InputConfig.defaultTimeout) @@ -149,7 +149,8 @@ final class NotifyTests: XCTestCase { try! await clientB.register(account: account, onSign: sign) sleep(1) - try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account, onSign: sign) + + try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } @@ -190,7 +191,7 @@ final class NotifyTests: XCTestCase { let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account + try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account) walletNotifyClientA.newSubscriptionPublisher .sink { subscription in From 4e1f942ef08b9df68cf45de28ec40a3463ca393a Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 15:09:07 +0200 Subject: [PATCH 38/91] fix notify config --- .../Client/Wallet/NotifyConfigProvider.swift | 2 +- .../Types/DataStructures/NotificationConfig.swift | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift index 4646f5f76..0789c0964 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift @@ -24,6 +24,6 @@ actor NotifyConfigProvider { guard let notifyConfigUrl = URL(string: "\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } let (data, _) = try await URLSession.shared.data(from: notifyConfigUrl) let config = try JSONDecoder().decode(NotificationConfig.self, from: data) - return config.metadata + return AppMetadata(name: config.name, description: config.description, url: dappUrl, icons: config.icons) } } diff --git a/Sources/WalletConnectNotify/Types/DataStructures/NotificationConfig.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotificationConfig.swift index 7fc0881c3..f5d138793 100644 --- a/Sources/WalletConnectNotify/Types/DataStructures/NotificationConfig.swift +++ b/Sources/WalletConnectNotify/Types/DataStructures/NotificationConfig.swift @@ -2,8 +2,9 @@ import Foundation struct NotificationConfig: Codable { - let version: Int - let lastModified: TimeInterval + let schemaVersion: Int + let name: String + let description: String + let icons: [String] let types: [NotificationType] - let metadata: AppMetadata } From a1c592ea1557b44f9affedde9c89207cbfd5d80c Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 15:34:12 +0200 Subject: [PATCH 39/91] replace dapUrl with app domain --- Example/IntegrationTests/Push/NotifyTests.swift | 14 +++++++------- .../Client/Wallet/NotifyClient.swift | 4 ++-- .../Client/Wallet/NotifyConfigProvider.swift | 8 ++++---- .../Client/Wallet/NotifySubscriptionsBuilder.swift | 2 +- .../NotifyWatchSubscriptionsRequester.swift | 2 +- .../NotifySubscribeRequester.swift | 8 ++++---- .../Client/Wallet/WebDidResolver.swift | 2 +- .../DataStructures/NotifyServerSubscription.swift | 2 +- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index d3ee4da62..ad12b24bd 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -18,7 +18,7 @@ final class NotifyTests: XCTestCase { var walletNotifyClientA: NotifyClient! - let gmDappUrl = "https://dev.gm.walletconnect.com/" + let gmDappDomain = "dev.gm.walletconnect.com" let pk = try! EthereumPrivateKey() @@ -104,7 +104,7 @@ final class NotifyTests: XCTestCase { }.store(in: &publishers) try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account) + try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } @@ -123,7 +123,7 @@ final class NotifyTests: XCTestCase { }.store(in: &publishers) try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account) + try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) sleep(1) @@ -150,7 +150,7 @@ final class NotifyTests: XCTestCase { sleep(1) - try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account) + try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } @@ -160,7 +160,7 @@ final class NotifyTests: XCTestCase { let updateScope: Set = ["alerts"] try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account) + try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) walletNotifyClientA.newSubscriptionPublisher .sink { [unowned self] subscription in @@ -188,10 +188,10 @@ final class NotifyTests: XCTestCase { let messageExpectation = expectation(description: "receives a notify message") let notifyMessage = NotifyMessage.stub() - let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappUrl, icons: []) + let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappDomain, icons: []) try! await walletNotifyClientA.register(account: account, onSign: sign) - try! await walletNotifyClientA.subscribe(dappUrl: gmDappUrl, account: account) + try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) walletNotifyClientA.newSubscriptionPublisher .sink { subscription in diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 95b624924..6872d829a 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -95,8 +95,8 @@ public class NotifyClient { logger.setLogging(level: level) } - public func subscribe(dappUrl: String, account: Account) async throws { - try await notifySubscribeRequester.subscribe(dappUrl: dappUrl, account: account) + public func subscribe(appDomain: String, account: Account) async throws { + try await notifySubscribeRequester.subscribe(appDomain: appDomain, account: account) } public func update(topic: String, scope: Set) async throws { diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift index 0789c0964..9833c8fd5 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift @@ -12,7 +12,7 @@ actor NotifyConfigProvider { if let availableScope = cache[dappUrl] { return availableScope } - guard let notifyConfigUrl = URL(string: "\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } + guard let notifyConfigUrl = URL(string: "https://\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } let (data, _) = try await URLSession.shared.data(from: notifyConfigUrl) let config = try JSONDecoder().decode(NotificationConfig.self, from: data) let availableScope = Set(config.types) @@ -20,10 +20,10 @@ actor NotifyConfigProvider { return availableScope } - func getMetadata(dappUrl: String) async throws -> AppMetadata { - guard let notifyConfigUrl = URL(string: "\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } + func getMetadata(appDomain: String) async throws -> AppMetadata { + guard let notifyConfigUrl = URL(string: "https://\(appDomain)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } let (data, _) = try await URLSession.shared.data(from: notifyConfigUrl) let config = try JSONDecoder().decode(NotificationConfig.self, from: data) - return AppMetadata(name: config.name, description: config.description, url: dappUrl, icons: config.icons) + return AppMetadata(name: config.name, description: config.description, url: appDomain, icons: config.icons) } } diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift index 24cc45cff..8977c3c32 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift @@ -12,7 +12,7 @@ class NotifySubscriptionsBuilder { for subscription in notifyServerSubscriptions { let scope = try await buildScope(selectedScope: subscription.scope, dappUrl: subscription.dappUrl) - guard let metadata = try? await notifyConfigProvider.getMetadata(dappUrl: subscription.dappUrl), + guard let metadata = try? await notifyConfigProvider.getMetadata(appDomain: subscription.dappUrl), let topic = try? SymmetricKey(hex: subscription.symKey).derivedTopic() else { continue } let notifySubscription = NotifySubscription(topic: topic, diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift index 59cba92af..dd22cfa06 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift @@ -8,7 +8,7 @@ class NotifyWatchSubscriptionsRequester { private let kms: KeyManagementService private let logger: ConsoleLogging private let webDidResolver: WebDidResolver - private let notifyServerUrl = "https://dev.notify.walletconnect.com" + private let notifyServerUrl = "dev.notify.walletconnect.com" init(keyserverURL: URL, networkingInteractor: NetworkInteracting, diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift index f532dbc30..6b9be2fb9 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift @@ -35,11 +35,11 @@ class NotifySubscribeRequester { self.notifyConfigProvider = notifyConfigProvider } - @discardableResult func subscribe(dappUrl: String, account: Account) async throws -> NotifySubscriptionPayload.Wrapper { + @discardableResult func subscribe(appDomain: String, account: Account) async throws -> NotifySubscriptionPayload.Wrapper { - logger.debug("Subscribing for Notify, dappUrl: \(dappUrl)") + logger.debug("Subscribing for Notify, dappUrl: \(appDomain)") - let metadata = try await notifyConfigProvider.getMetadata(dappUrl: dappUrl) + let metadata = try await notifyConfigProvider.getMetadata(appDomain: appDomain) let peerPublicKey = try await webDidResolver.resolveAgreementKey(domain: metadata.url) let subscribeTopic = peerPublicKey.rawRepresentation.sha256().toHexString() @@ -60,7 +60,7 @@ class NotifySubscribeRequester { let subscriptionAuthWrapper = try await createJWTWrapper( dappPubKey: DIDKey(did: peerPublicKey.did), subscriptionAccount: account, - dappUrl: dappUrl + dappUrl: appDomain ) let request = RPCRequest(method: protocolMethod.method, params: subscriptionAuthWrapper) diff --git a/Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift b/Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift index 9d642ff07..700bd4a80 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift @@ -36,7 +36,7 @@ private extension WebDidResolver { } func resolveDidDoc(domainUrl: String) async throws -> WebDidDoc { - guard let didDocUrl = URL(string: "\(domainUrl)/.well-known/did.json") else { throw Errors.invalidUrl } + guard let didDocUrl = URL(string: "https://\(domainUrl)/.well-known/did.json") else { throw Errors.invalidUrl } let (data, _) = try await URLSession.shared.data(from: didDocUrl) return try JSONDecoder().decode(WebDidDoc.self, from: data) } diff --git a/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift b/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift index 3ac2ecb93..56ebbd352 100644 --- a/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift +++ b/Sources/WalletConnectNotify/Types/DataStructures/NotifyServerSubscription.swift @@ -1,7 +1,7 @@ import Foundation struct NotifyServerSubscription: Codable, Equatable { - let dappUrl: String + let appDomain: String let account: Account let scope: [String] let symKey: String From 682c3c6a03dd9c9c4316958949b7f2fe284444a4 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 11 Sep 2023 21:59:26 +0800 Subject: [PATCH 40/91] Identity client refactor --- Example/IntegrationTests/Chat/ChatTests.swift | 4 +- Sources/Chat/ChatClient.swift | 10 ++++- .../IdentityClient.swift | 4 +- .../IdentityService.swift | 27 ++++++++----- .../Client/Wallet/NotifyClient.swift | 12 +++--- .../Client/Wallet/NotifyClientFactory.swift | 4 +- .../Client/Wallet/NotifyIdentityService.swift | 40 +++++++++++++++++++ .../ChatClient/ChatClientProxy.swift | 3 +- .../NotifyClientProxy/NotifyClientProxy.swift | 4 +- 9 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 Sources/WalletConnectNotify/Client/Wallet/NotifyIdentityService.swift diff --git a/Example/IntegrationTests/Chat/ChatTests.swift b/Example/IntegrationTests/Chat/ChatTests.swift index 54d2381c8..0d44be8b6 100644 --- a/Example/IntegrationTests/Chat/ChatTests.swift +++ b/Example/IntegrationTests/Chat/ChatTests.swift @@ -38,10 +38,10 @@ final class ChatTests: XCTestCase { invitee1 = makeClient(prefix: "🦖 Invitee", account: inviteeAccount) inviter1 = makeClient(prefix: "🍄 Inviter", account: inviterAccount) - try await invitee1.register(account: inviteeAccount) { message in + try await invitee1.register(account: inviteeAccount, domain: "") { message in return self.sign(message, privateKey: self.privateKey1) } - try await inviter1.register(account: inviterAccount) { message in + try await inviter1.register(account: inviterAccount, domain: "") { message in return self.sign(message, privateKey: self.privateKey2) } } diff --git a/Sources/Chat/ChatClient.swift b/Sources/Chat/ChatClient.swift index 7d0f8ed5a..445c96ab8 100644 --- a/Sources/Chat/ChatClient.swift +++ b/Sources/Chat/ChatClient.swift @@ -89,10 +89,16 @@ public class ChatClient { @discardableResult public func register(account: Account, isPrivate: Bool = false, + domain: String, onSign: @escaping SigningCallback ) async throws -> String { - let publicKey = try await identityClient.register(account: account, onSign: onSign) - + let publicKey = try await identityClient.register( + account: account, + domain: domain, + statement: "statement", + resources: ["https://keys.walletconnect.com"], + onSign: onSign + ) if !syncRegisterService.isRegistered(account: account) { try await chatStorage.initializeHistory(account: account) try await syncRegisterService.register(account: account, onSign: onSign) diff --git a/Sources/WalletConnectIdentity/IdentityClient.swift b/Sources/WalletConnectIdentity/IdentityClient.swift index 57335fb79..3fb32c92a 100644 --- a/Sources/WalletConnectIdentity/IdentityClient.swift +++ b/Sources/WalletConnectIdentity/IdentityClient.swift @@ -22,8 +22,8 @@ public final class IdentityClient { self.logger = logger } - public func register(account: Account, onSign: SigningCallback) async throws -> String { - let pubKey = try await identityService.registerIdentity(account: account, onSign: onSign) + public func register(account: Account, domain: String, statement: String, resources: [String], onSign: SigningCallback) async throws -> String { + let pubKey = try await identityService.registerIdentity(account: account, domain: domain, statement: statement, resources: resources, onSign: onSign) logger.debug("Did register an account: \(account)") return pubKey } diff --git a/Sources/WalletConnectIdentity/IdentityService.swift b/Sources/WalletConnectIdentity/IdentityService.swift index 5f7fc0431..f9c174be2 100644 --- a/Sources/WalletConnectIdentity/IdentityService.swift +++ b/Sources/WalletConnectIdentity/IdentityService.swift @@ -26,6 +26,9 @@ actor IdentityService { } func registerIdentity(account: Account, + domain: String, + statement: String, + resources: [String], onSign: SigningCallback ) async throws -> String { @@ -34,7 +37,7 @@ actor IdentityService { } let identityKey = SigningPrivateKey() - let cacao = try await makeCacao(DIDKey: identityKey.publicKey.did, account: account, onSign: onSign) + let cacao = try await makeCacao(account: account, domain: domain, statement: statement, resources: resources, onSign: onSign) try await networkService.registerIdentity(cacao: cacao) return try storage.saveIdentityKey(identityKey, for: account).publicKey.hexRepresentation @@ -85,22 +88,25 @@ actor IdentityService { private extension IdentityService { - func makeCacao( - DIDKey: String, - account: Account, + func makeCacao(account: Account, + domain: String, + statement: String, + resources: [String], onSign: SigningCallback ) async throws -> Cacao { let cacaoHeader = CacaoHeader(t: "eip4361") let cacaoPayload = CacaoPayload( iss: account.did, - domain: keyserverURL.host!, - aud: getAudience(), + domain: domain, + aud: try getAudience(account: account), version: getVersion(), nonce: getNonce(), iat: iatProvader.iat, - nbf: nil, exp: nil, statement: "statement", requestId: nil, - resources: [DIDKey] + nbf: nil, exp: nil, + statement: statement, + requestId: nil, + resources: resources ) let result = await onSign(try messageFormatter.formatMessage(from: cacaoPayload)) @@ -133,7 +139,8 @@ private extension IdentityService { return "1" } - private func getAudience() -> String { - return keyserverURL.absoluteString + private func getAudience(account: Account) throws -> String { + let identityKey = try storage.getIdentityKey(for: account) + return identityKey.publicKey.did } } diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 95b624924..8194ffa6a 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -37,7 +37,7 @@ public class NotifyClient { public let logger: ConsoleLogging private let pushClient: PushClient - private let identityClient: IdentityClient + private let identityService: NotifyIdentityService private let notifyStorage: NotifyStorage private let notifyMessageSubscriber: NotifyMessageSubscriber private let resubscribeService: NotifyResubscribeService @@ -52,7 +52,7 @@ public class NotifyClient { init(logger: ConsoleLogging, kms: KeyManagementServiceProtocol, - identityClient: IdentityClient, + identityService: NotifyIdentityService, pushClient: PushClient, notifyMessageSubscriber: NotifyMessageSubscriber, notifyStorage: NotifyStorage, @@ -70,7 +70,7 @@ public class NotifyClient { ) { self.logger = logger self.pushClient = pushClient - self.identityClient = identityClient + self.identityService = identityService self.notifyMessageSubscriber = notifyMessageSubscriber self.notifyStorage = notifyStorage self.deleteNotifySubscriptionRequester = deleteNotifySubscriptionRequester @@ -86,8 +86,8 @@ public class NotifyClient { self.notifySubscriptionsChangedRequestSubscriber = notifySubscriptionsChangedRequestSubscriber } - public func register(account: Account, onSign: @escaping SigningCallback) async throws { - _ = try await identityClient.register(account: account, onSign: onSign) + public func register(account: Account, domain: String, isLimited: Bool, onSign: @escaping SigningCallback) async throws { + try await identityService.register(account: account, domain: domain, isLimited: isLimited, onSign: onSign) try await notifyWatchSubscriptionsRequester.watchSubscriptions(account: account) } @@ -124,7 +124,7 @@ public class NotifyClient { } public func isIdentityRegistered(account: Account) -> Bool { - return identityClient.isIdentityRegistered(account: account) + return identityService.isIdentityRegistered(account: account) } public func messagesPublisher(topic: String) -> AnyPublisher<[NotifyMessageRecord], Never> { diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index 16d37908d..795724d0a 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -63,10 +63,12 @@ public struct NotifyClientFactory { let notifyWatchSubscriptionsResponseSubscriber = NotifyWatchSubscriptionsResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) let notifySubscriptionsChangedRequestSubscriber = NotifySubscriptionsChangedRequestSubscriber(keyserver: keyserverURL, networkingInteractor: networkInteractor, kms: kms, identityClient: identityClient, logger: logger, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) + let identityService = NotifyIdentityService(keyserverURL: keyserverURL, identityClient: identityClient, logger: logger) + return NotifyClient( logger: logger, kms: kms, - identityClient: identityClient, + identityService: identityService, pushClient: pushClient, notifyMessageSubscriber: notifyMessageSubscriber, notifyStorage: notifyStorage, diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyIdentityService.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyIdentityService.swift new file mode 100644 index 000000000..fc8091317 --- /dev/null +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyIdentityService.swift @@ -0,0 +1,40 @@ +import Foundation + +final class NotifyIdentityService { + + private let keyserverURL: URL + private let identityClient: IdentityClient + private let logger: ConsoleLogging + + init(keyserverURL: URL, identityClient: IdentityClient, logger: ConsoleLogging) { + self.keyserverURL = keyserverURL + self.identityClient = identityClient + self.logger = logger + } + + public func register(account: Account, domain: String, isLimited: Bool, onSign: @escaping SigningCallback) async throws { + let statement = makeStatement(isLimited: isLimited, domain: domain, keyserverHost: keyserverURL.host!) + let pubKey = try await identityClient.register(account: account, + domain: domain, + statement: statement, + resources: [keyserverURL.absoluteString], + onSign: onSign) + logger.debug("Did register an account: \(account)") + } + + func isIdentityRegistered(account: Account) -> Bool { + return identityClient.isIdentityRegistered(account: account) + } +} + +private extension NotifyIdentityService { + + func makeStatement(isLimited: Bool, domain: String, keyserverHost: String) -> String { + switch isLimited { + case true: + return "I further authorize this DAPP to send and receive messages on my behalf for this domain and manage my identity at \(keyserverHost)." + case false: + return "I further authorize this WALLET to send and receive messages on my behalf for ALL domains and manage my identity at \(keyserverHost)." + } + } +} diff --git a/Sources/Web3Inbox/ChatClient/ChatClientProxy.swift b/Sources/Web3Inbox/ChatClient/ChatClientProxy.swift index b6fd91d00..62d8a60c0 100644 --- a/Sources/Web3Inbox/ChatClient/ChatClientProxy.swift +++ b/Sources/Web3Inbox/ChatClient/ChatClientProxy.swift @@ -34,7 +34,7 @@ final class ChatClientProxy { case .register: let params = try parse(RegisterRequest.self, params: request.params) - try await client.register(account: params.account, onSign: onSign) + try await client.register(account: params.account, domain: params.domain, onSign: onSign) try await respond(request: request) case .resolve: @@ -81,6 +81,7 @@ private extension ChatClientProxy { struct RegisterRequest: Codable { let account: Account + let domain: String } struct ResolveRequest: Codable { diff --git a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift index c3f837559..3ff1c0ce5 100644 --- a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift +++ b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift @@ -44,7 +44,7 @@ final class NotifyClientProxy { try await respond(request: request) case .register: let params = try parse(RegisterRequest.self, params: request.params) - try await client.register(account: params.account, onSign: onSign) + try await client.register(account: params.account, domain: params.domain, isLimited: params.isLimited, onSign: onSign) try await respond(request: request) } } @@ -91,6 +91,8 @@ private extension NotifyClientProxy { struct RegisterRequest: Codable { let account: Account + let domain: String + let isLimited: Bool } func parse(_ type: Request.Type, params: AnyCodable?) throws -> Request { From 5bfde7faf63a7d2755ef20dedbffa0dc263a2e30 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 11 Sep 2023 22:03:56 +0800 Subject: [PATCH 41/91] Integration tests fixed --- Example/IntegrationTests/Push/NotifyTests.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index ad12b24bd..b6f349584 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -103,7 +103,7 @@ final class NotifyTests: XCTestCase { } }.store(in: &publishers) - try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) wait(for: [expectation], timeout: InputConfig.defaultTimeout) @@ -122,7 +122,7 @@ final class NotifyTests: XCTestCase { } }.store(in: &publishers) - try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) sleep(1) @@ -145,7 +145,7 @@ final class NotifyTests: XCTestCase { } }.store(in: &publishers) - try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) try! await clientB.register(account: account, onSign: sign) sleep(1) @@ -159,7 +159,7 @@ final class NotifyTests: XCTestCase { let expectation = expectation(description: "expects to create and update notify subscription") let updateScope: Set = ["alerts"] - try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) walletNotifyClientA.newSubscriptionPublisher @@ -190,7 +190,7 @@ final class NotifyTests: XCTestCase { let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappDomain, icons: []) - try! await walletNotifyClientA.register(account: account, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) walletNotifyClientA.newSubscriptionPublisher From 22b67c9c63ae0ddbbd5bdc3b270756ce4969c49e Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 16:06:58 +0200 Subject: [PATCH 42/91] Update notify web did resolver --- .../Client/Wallet/NotifyClientFactory.swift | 2 +- .../Wallet/NotifySubscriptionsBuilder.swift | 4 ++-- ...dResolver.swift => NotifyWebDidResolver.swift} | 15 +++++++-------- .../DeleteNotifySubscriptionRequester.swift | 4 ++-- .../wc_notifyUpdate/NotifyUpdateRequester.swift | 4 ++-- .../NotifyWatchSubscriptionsRequester.swift | 4 ++-- .../NotifySubscribeRequester.swift | 4 ++-- .../Types/DataStructures/WebDidDoc.swift | 4 +--- 8 files changed, 19 insertions(+), 22 deletions(-) rename Sources/WalletConnectNotify/Client/Wallet/{WebDidResolver.swift => NotifyWebDidResolver.swift} (69%) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index 16d37908d..458aa2506 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -39,7 +39,7 @@ public struct NotifyClientFactory { let notifyStorage = NotifyStorage(subscriptionStore: subscriptionStore, messagesStore: messagesStore) let identityClient = IdentityClientFactory.create(keyserver: keyserverURL, keychain: keychainStorage, logger: logger) let notifyMessageSubscriber = NotifyMessageSubscriber(keyserver: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, notifyStorage: notifyStorage, crypto: crypto, logger: logger) - let webDidResolver = WebDidResolver() + let webDidResolver = NotifyWebDidResolver() let deleteNotifySubscriptionRequester = DeleteNotifySubscriptionRequester(keyserver: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, webDidResolver: webDidResolver, kms: kms, logger: logger, notifyStorage: notifyStorage) let resubscribeService = NotifyResubscribeService(networkInteractor: networkInteractor, notifyStorage: notifyStorage, logger: logger) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift index 8977c3c32..e0c452ec9 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift @@ -11,8 +11,8 @@ class NotifySubscriptionsBuilder { var result = [NotifySubscription]() for subscription in notifyServerSubscriptions { - let scope = try await buildScope(selectedScope: subscription.scope, dappUrl: subscription.dappUrl) - guard let metadata = try? await notifyConfigProvider.getMetadata(appDomain: subscription.dappUrl), + let scope = try await buildScope(selectedScope: subscription.scope, dappUrl: subscription.appDomain) + guard let metadata = try? await notifyConfigProvider.getMetadata(appDomain: subscription.appDomain), let topic = try? SymmetricKey(hex: subscription.symKey).derivedTopic() else { continue } let notifySubscription = NotifySubscription(topic: topic, diff --git a/Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyWebDidResolver.swift similarity index 69% rename from Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift rename to Sources/WalletConnectNotify/Client/Wallet/NotifyWebDidResolver.swift index 700bd4a80..c412d6ca3 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/WebDidResolver.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyWebDidResolver.swift @@ -1,11 +1,13 @@ import Foundation -final class WebDidResolver { +final class NotifyWebDidResolver { + + private static var subscribeKey = "wc-notify-subscribe-key" + private static var authenticationKey = "wc-notify-authentication-key" func resolveAgreementKey(domain: String) async throws -> AgreementPublicKey { let didDoc = try await resolveDidDoc(domainUrl: domain) - guard let keyAgreement = didDoc.keyAgreement.first else { throw Errors.didDocDoesNotContainKeyAgreement } - guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == keyAgreement }) else { throw Errors.noVerificationMethodForKey } + guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == Self.subscribeKey }) else { throw Errors.noVerificationMethodForKey } guard verificationMethod.publicKeyJwk.crv == .X25519 else { throw Errors.unsupportedCurve} let pubKeyBase64Url = verificationMethod.publicKeyJwk.x return try AgreementPublicKey(base64url: pubKeyBase64Url) @@ -15,8 +17,7 @@ final class WebDidResolver { func resolveAuthenticationKey(domain: String) async throws -> Data { let didDoc = try await resolveDidDoc(domainUrl: domain) - guard let authentication = didDoc.authentication?.first else { throw Errors.didDocDoesNotContainAuthenticationKey } - guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == authentication }) else { throw Errors.noVerificationMethodForKey } + guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == Self.authenticationKey }) else { throw Errors.noVerificationMethodForKey } guard verificationMethod.publicKeyJwk.crv == .Ed25519 else { throw Errors.unsupportedCurve} let pubKeyBase64Url = verificationMethod.publicKeyJwk.x guard let raw = Data(base64url: pubKeyBase64Url) else { throw Errors.invalidBase64urlString } @@ -24,13 +25,11 @@ final class WebDidResolver { } } -private extension WebDidResolver { +private extension NotifyWebDidResolver { enum Errors: Error { case invalidUrl case invalidBase64urlString - case didDocDoesNotContainKeyAgreement - case didDocDoesNotContainAuthenticationKey case noVerificationMethodForKey case unsupportedCurve } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift index e280d63fa..e23ae9d61 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift @@ -7,7 +7,7 @@ class DeleteNotifySubscriptionRequester { private let keyserver: URL private let networkingInteractor: NetworkInteracting private let identityClient: IdentityClient - private let webDidResolver: WebDidResolver + private let webDidResolver: NotifyWebDidResolver private let kms: KeyManagementServiceProtocol private let logger: ConsoleLogging private let notifyStorage: NotifyStorage @@ -16,7 +16,7 @@ class DeleteNotifySubscriptionRequester { keyserver: URL, networkingInteractor: NetworkInteracting, identityClient: IdentityClient, - webDidResolver: WebDidResolver, + webDidResolver: NotifyWebDidResolver, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, notifyStorage: NotifyStorage diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift index 33b850f4d..18876c53e 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift @@ -10,7 +10,7 @@ class NotifyUpdateRequester: NotifyUpdateRequesting { } private let keyserverURL: URL - private let webDidResolver: WebDidResolver + private let webDidResolver: NotifyWebDidResolver private let identityClient: IdentityClient private let networkingInteractor: NetworkInteracting private let notifyConfigProvider: NotifyConfigProvider @@ -19,7 +19,7 @@ class NotifyUpdateRequester: NotifyUpdateRequesting { init( keyserverURL: URL, - webDidResolver: WebDidResolver, + webDidResolver: NotifyWebDidResolver, identityClient: IdentityClient, networkingInteractor: NetworkInteracting, notifyConfigProvider: NotifyConfigProvider, diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift index dd22cfa06..c8500b416 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift @@ -7,7 +7,7 @@ class NotifyWatchSubscriptionsRequester { private let networkingInteractor: NetworkInteracting private let kms: KeyManagementService private let logger: ConsoleLogging - private let webDidResolver: WebDidResolver + private let webDidResolver: NotifyWebDidResolver private let notifyServerUrl = "dev.notify.walletconnect.com" init(keyserverURL: URL, @@ -15,7 +15,7 @@ class NotifyWatchSubscriptionsRequester { identityClient: IdentityClient, logger: ConsoleLogging, kms: KeyManagementService, - webDidResolver: WebDidResolver + webDidResolver: NotifyWebDidResolver ) { self.keyserverURL = keyserverURL self.identityClient = identityClient diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift index 6b9be2fb9..17981e646 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift @@ -12,7 +12,7 @@ class NotifySubscribeRequester { private let networkingInteractor: NetworkInteracting private let kms: KeyManagementService private let logger: ConsoleLogging - private let webDidResolver: WebDidResolver + private let webDidResolver: NotifyWebDidResolver private let dappsMetadataStore: CodableStore private let notifyConfigProvider: NotifyConfigProvider @@ -21,7 +21,7 @@ class NotifySubscribeRequester { identityClient: IdentityClient, logger: ConsoleLogging, kms: KeyManagementService, - webDidResolver: WebDidResolver, + webDidResolver: NotifyWebDidResolver, notifyConfigProvider: NotifyConfigProvider, dappsMetadataStore: CodableStore ) { diff --git a/Sources/WalletConnectNotify/Types/DataStructures/WebDidDoc.swift b/Sources/WalletConnectNotify/Types/DataStructures/WebDidDoc.swift index adf0c17f9..a31333b0c 100644 --- a/Sources/WalletConnectNotify/Types/DataStructures/WebDidDoc.swift +++ b/Sources/WalletConnectNotify/Types/DataStructures/WebDidDoc.swift @@ -5,12 +5,10 @@ struct WebDidDoc: Codable { let context: [String] let id: String let verificationMethod: [VerificationMethod] - let authentication: [String]? - let keyAgreement: [String] enum CodingKeys: String, CodingKey { case context = "@context" - case id, verificationMethod, authentication, keyAgreement + case id, verificationMethod } } extension WebDidDoc { From 32d6ba6d548e2a479e25fa3014cd447a3c804c87 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 16:09:49 +0200 Subject: [PATCH 43/91] rename --- .../Client/Wallet/NotifySubscriptionsBuilder.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift index e0c452ec9..4cd2fbc34 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift @@ -11,7 +11,7 @@ class NotifySubscriptionsBuilder { var result = [NotifySubscription]() for subscription in notifyServerSubscriptions { - let scope = try await buildScope(selectedScope: subscription.scope, dappUrl: subscription.appDomain) + let scope = try await buildScope(selectedScope: subscription.scope, appDomain: subscription.appDomain) guard let metadata = try? await notifyConfigProvider.getMetadata(appDomain: subscription.appDomain), let topic = try? SymmetricKey(hex: subscription.symKey).derivedTopic() else { continue } @@ -28,8 +28,8 @@ class NotifySubscriptionsBuilder { return result } - private func buildScope(selectedScope: [String], dappUrl: String) async throws -> [String: ScopeValue] { - let availableScope = try await notifyConfigProvider.getSubscriptionScope(dappUrl: dappUrl) + private func buildScope(selectedScope: [String], appDomain: String) async throws -> [String: ScopeValue] { + let availableScope = try await notifyConfigProvider.getSubscriptionScope(dappUrl: appDomain) return availableScope.reduce(into: [:]) { $0[$1.name] = ScopeValue(description: $1.description, enabled: selectedScope.contains($1.name)) } From 6c2f158fecffd1ce111413f9f742f7693e7c1f76 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 16:15:32 +0200 Subject: [PATCH 44/91] rename receiptAuth to responseAuth --- .../Types/JWTPayloads/NotifyMessageReceiptPayload.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift index b5aacf956..c3bdf466c 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift @@ -27,14 +27,14 @@ struct NotifyMessageReceiptPayload: JWTClaimsCodable { } struct Wrapper: JWTWrapper { - let receiptAuth: String + let responseAuth: String init(jwtString: String) { - self.receiptAuth = jwtString + self.responseAuth = jwtString } var jwtString: String { - return receiptAuth + return responseAuth } } From 7e92ad87fc109ce69a9c572bb08ed58034866ef5 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 16:21:13 +0200 Subject: [PATCH 45/91] fix wallet app build --- Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift index c3f837559..54590a4ea 100644 --- a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift +++ b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift @@ -25,7 +25,7 @@ final class NotifyClientProxy { try await respond(request: request) case .subscribe: let params = try parse(SubscribeRequest.self, params: request.params) - try await client.subscribe(dappUrl: params.dappUrl, account: params.account) + try await client.subscribe(appDomain: params.appDomain, account: params.account) try await respond(request: request) case .getActiveSubscriptions: let subscriptions = client.getActiveSubscriptions() @@ -73,7 +73,7 @@ private extension NotifyClientProxy { } struct SubscribeRequest: Codable { - let dappUrl: String + let appDomain: String let account: Account } From b87c0cdcf75ca48cacd3d9addee3864e517cfd4d Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 11 Sep 2023 22:45:44 +0800 Subject: [PATCH 46/91] web3inbox fixed --- Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift index 3ff1c0ce5..9319d23ad 100644 --- a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift +++ b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift @@ -25,7 +25,7 @@ final class NotifyClientProxy { try await respond(request: request) case .subscribe: let params = try parse(SubscribeRequest.self, params: request.params) - try await client.subscribe(dappUrl: params.dappUrl, account: params.account) + try await client.subscribe(appDomain: params.appDomain, account: params.account) try await respond(request: request) case .getActiveSubscriptions: let subscriptions = client.getActiveSubscriptions() @@ -73,7 +73,7 @@ private extension NotifyClientProxy { } struct SubscribeRequest: Codable { - let dappUrl: String + let appDomain: String let account: Account } From 59ceb9cad0356275a141fbe7d0b921fa056bc901 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 17:05:05 +0200 Subject: [PATCH 47/91] update diddoc resolver --- .../Client/Wallet/NotifyWebDidResolver.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyWebDidResolver.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyWebDidResolver.swift index c412d6ca3..5312e28bd 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyWebDidResolver.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyWebDidResolver.swift @@ -7,7 +7,8 @@ final class NotifyWebDidResolver { func resolveAgreementKey(domain: String) async throws -> AgreementPublicKey { let didDoc = try await resolveDidDoc(domainUrl: domain) - guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == Self.subscribeKey }) else { throw Errors.noVerificationMethodForKey } + let subscribeKeyPath = "\(didDoc.id)#\(Self.subscribeKey)" + guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == subscribeKeyPath }) else { throw Errors.noVerificationMethodForKey } guard verificationMethod.publicKeyJwk.crv == .X25519 else { throw Errors.unsupportedCurve} let pubKeyBase64Url = verificationMethod.publicKeyJwk.x return try AgreementPublicKey(base64url: pubKeyBase64Url) @@ -17,7 +18,8 @@ final class NotifyWebDidResolver { func resolveAuthenticationKey(domain: String) async throws -> Data { let didDoc = try await resolveDidDoc(domainUrl: domain) - guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == Self.authenticationKey }) else { throw Errors.noVerificationMethodForKey } + let authenticationKeyPath = "\(didDoc.id)#\(Self.authenticationKey)" + guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == authenticationKeyPath }) else { throw Errors.noVerificationMethodForKey } guard verificationMethod.publicKeyJwk.crv == .Ed25519 else { throw Errors.unsupportedCurve} let pubKeyBase64Url = verificationMethod.publicKeyJwk.x guard let raw = Data(base64url: pubKeyBase64Url) else { throw Errors.invalidBase64urlString } From 43954c125a67d6881ac0fb241b7ac83f7f10d4dd Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 11 Sep 2023 23:08:31 +0800 Subject: [PATCH 48/91] Notify tests updated --- Example/IntegrationTests/Push/NotifyTests.swift | 4 ++-- Sources/WalletConnectIdentity/IdentityService.swift | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index b6f349584..e7944060c 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -127,7 +127,7 @@ final class NotifyTests: XCTestCase { sleep(1) - try! await clientB.register(account: account, onSign: sign) + try! await clientB.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } @@ -146,7 +146,7 @@ final class NotifyTests: XCTestCase { }.store(in: &publishers) try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) - try! await clientB.register(account: account, onSign: sign) + try! await clientB.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) sleep(1) diff --git a/Sources/WalletConnectIdentity/IdentityService.swift b/Sources/WalletConnectIdentity/IdentityService.swift index f9c174be2..a267a6a1b 100644 --- a/Sources/WalletConnectIdentity/IdentityService.swift +++ b/Sources/WalletConnectIdentity/IdentityService.swift @@ -37,7 +37,8 @@ actor IdentityService { } let identityKey = SigningPrivateKey() - let cacao = try await makeCacao(account: account, domain: domain, statement: statement, resources: resources, onSign: onSign) + let audience = identityKey.publicKey.did + let cacao = try await makeCacao(account: account, domain: domain, statement: statement, resources: resources, audience: audience, onSign: onSign) try await networkService.registerIdentity(cacao: cacao) return try storage.saveIdentityKey(identityKey, for: account).publicKey.hexRepresentation @@ -92,6 +93,7 @@ private extension IdentityService { domain: String, statement: String, resources: [String], + audience: String, onSign: SigningCallback ) async throws -> Cacao { @@ -99,7 +101,7 @@ private extension IdentityService { let cacaoPayload = CacaoPayload( iss: account.did, domain: domain, - aud: try getAudience(account: account), + aud: audience, version: getVersion(), nonce: getNonce(), iat: iatProvader.iat, @@ -138,9 +140,4 @@ private extension IdentityService { private func getVersion() -> String { return "1" } - - private func getAudience(account: Account) throws -> String { - let identityKey = try storage.getIdentityKey(for: account) - return identityKey.publicKey.did - } } From b43876738cb7a4b3088a2c9870b791685f73112e Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 18:14:56 +0200 Subject: [PATCH 49/91] generate keyPairY only once --- .../Crypto/KeyManagementService.swift | 12 ++++++ .../NotifyWatchSubscriptionsRequester.swift | 39 +++++++++++++------ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/Sources/WalletConnectKMS/Crypto/KeyManagementService.swift b/Sources/WalletConnectKMS/Crypto/KeyManagementService.swift index a5b6d359d..90a6455fa 100644 --- a/Sources/WalletConnectKMS/Crypto/KeyManagementService.swift +++ b/Sources/WalletConnectKMS/Crypto/KeyManagementService.swift @@ -59,6 +59,10 @@ public class KeyManagementService: KeyManagementServiceProtocol { try keychain.add(agreementSecret, forKey: topic) } + public func setTopic(_ topic: String, for key: String) throws { + try keychain.add(topic, forKey: key) + } + public func getSymmetricKey(for topic: String) -> SymmetricKey? { do { return try keychain.read(key: topic) as SymmetricKey @@ -85,6 +89,14 @@ public class KeyManagementService: KeyManagementServiceProtocol { } } + public func getTopic(for key: String) -> String? { + do { + return try keychain.read(key: key) as String + } catch { + return nil + } + } + public func getAgreementSecret(for topic: String) -> AgreementKeys? { do { return try keychain.read(key: topic) as AgreementKeys diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift index c8500b416..710e163a0 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift @@ -29,18 +29,14 @@ class NotifyWatchSubscriptionsRequester { logger.debug("Watching subscriptions") - let notifyServerAgreementKey = try await webDidResolver.resolveAgreementKey(domain: notifyServerUrl) + let notifyServerPublicKey = try await webDidResolver.resolveAgreementKey(domain: notifyServerUrl) let notifyServerAuthenticationKey = try await webDidResolver.resolveAuthenticationKey(domain: notifyServerUrl) let notifyServerAuthenticationDidKey = DIDKey(rawData: notifyServerAuthenticationKey) - let watchSubscriptionsTopic = notifyServerAgreementKey.rawRepresentation.sha256().toHexString() + let watchSubscriptionsTopic = notifyServerPublicKey.rawRepresentation.sha256().toHexString() - // todo - generate keypair only once - let keysY = try generateAgreementKeys(peerPublicKey: notifyServerAgreementKey) + let (responseTopic, selfPubKeyY) = try generateAgreementKeysIfNeeded(notifyServerPublicKey: notifyServerPublicKey, account: account) - let responseTopic = keysY.derivedTopic() - try kms.setSymmetricKey(keysY.sharedKey, for: watchSubscriptionsTopic) - try kms.setAgreementSecret(keysY, topic: responseTopic) logger.debug("setting symm key for response topic \(responseTopic)") @@ -58,15 +54,34 @@ class NotifyWatchSubscriptionsRequester { try await networkingInteractor.subscribe(topic: responseTopic) - try await networkingInteractor.request(request, topic: watchSubscriptionsTopic, protocolMethod: protocolMethod, envelopeType: .type1(pubKey: keysY.publicKey.rawRepresentation)) + try await networkingInteractor.request(request, topic: watchSubscriptionsTopic, protocolMethod: protocolMethod, envelopeType: .type1(pubKey: selfPubKeyY)) } - private func generateAgreementKeys(peerPublicKey: AgreementPublicKey) throws -> AgreementKeys { - let selfPubKey = try kms.createX25519KeyPair() + private func generateAgreementKeysIfNeeded(notifyServerPublicKey: AgreementPublicKey, account: Account) throws -> (responseTopic: String, selfPubKeyY: Data) { - let keys = try kms.performKeyAgreement(selfPublicKey: selfPubKey, peerPublicKey: peerPublicKey.hexRepresentation) - return keys + let keyYStorageKey = "\(account)_\(notifyServerPublicKey.hexRepresentation)" + + if let responseTopic = kms.getTopic(for: keyYStorageKey), + let selfPubKeyY = kms.getPublicKey(for: responseTopic) { + return (responseTopic: responseTopic, selfPubKeyY: selfPubKeyY.rawRepresentation) + } else { + let selfPubKeyY = try kms.createX25519KeyPair() + + let watchSubscriptionsTopic = notifyServerPublicKey.rawRepresentation.sha256().toHexString() + + let agreementKeys = try kms.performKeyAgreement(selfPublicKey: selfPubKeyY, peerPublicKey: notifyServerPublicKey.hexRepresentation) + + try kms.setSymmetricKey(agreementKeys.sharedKey, for: watchSubscriptionsTopic) + let responseTopic = agreementKeys.derivedTopic() + + try kms.setAgreementSecret(agreementKeys, topic: responseTopic) + + // save for later under dapp's accout + pub key + try kms.setTopic(responseTopic, for: keyYStorageKey) + + return (responseTopic: responseTopic, selfPubKeyY: selfPubKeyY.rawRepresentation) + } } private func createJWTWrapper(notifyServerAuthenticationDidKey: DIDKey, subscriptionAccount: Account) async throws -> NotifyWatchSubscriptionsPayload.Wrapper { From 16733b23a01e1dfd0d49dd5077fff18318e23dda Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 18:32:51 +0200 Subject: [PATCH 50/91] rename appdomain --- .../Client/Wallet/NotifyConfigProvider.swift | 8 ++++---- .../Client/Wallet/NotifySubscriptionsBuilder.swift | 2 +- .../wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift | 2 +- .../wc_pushSubscribe/NotifySubscribeRequester.swift | 2 +- .../NotifySubscribeResponseSubscriber.swift | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift index 9833c8fd5..99a292a6d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyConfigProvider.swift @@ -8,15 +8,15 @@ actor NotifyConfigProvider { private var cache = [String: Set]() - func getSubscriptionScope(dappUrl: String) async throws -> Set { - if let availableScope = cache[dappUrl] { + func getSubscriptionScope(appDomain: String) async throws -> Set { + if let availableScope = cache[appDomain] { return availableScope } - guard let notifyConfigUrl = URL(string: "https://\(dappUrl)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } + guard let notifyConfigUrl = URL(string: "https://\(appDomain)/.well-known/wc-notify-config.json") else { throw Errors.invalidUrl } let (data, _) = try await URLSession.shared.data(from: notifyConfigUrl) let config = try JSONDecoder().decode(NotificationConfig.self, from: data) let availableScope = Set(config.types) - cache[dappUrl] = availableScope + cache[appDomain] = availableScope return availableScope } diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift index 4cd2fbc34..fb1d0a325 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionsBuilder.swift @@ -29,7 +29,7 @@ class NotifySubscriptionsBuilder { } private func buildScope(selectedScope: [String], appDomain: String) async throws -> [String: ScopeValue] { - let availableScope = try await notifyConfigProvider.getSubscriptionScope(dappUrl: appDomain) + let availableScope = try await notifyConfigProvider.getSubscriptionScope(appDomain: appDomain) return availableScope.reduce(into: [:]) { $0[$1.name] = ScopeValue(description: $1.description, enabled: selectedScope.contains($1.name)) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift index cd612dc24..549ede05d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift @@ -58,7 +58,7 @@ private extension NotifyUpdateResponseSubscriber { func buildScope(selected: String, dappUrl: String) async throws -> [String: ScopeValue] { let selectedScope = selected.components(separatedBy: " ") - let availableScope = try await nofityConfigProvider.getSubscriptionScope(dappUrl: dappUrl) + let availableScope = try await nofityConfigProvider.getSubscriptionScope(appDomain: dappUrl) return availableScope.reduce(into: [:]) { $0[$1.name] = ScopeValue(description: $1.description, enabled: selectedScope.contains($1.name)) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift index 17981e646..932c71f90 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift @@ -80,7 +80,7 @@ class NotifySubscribeRequester { } private func createJWTWrapper(dappPubKey: DIDKey, subscriptionAccount: Account, dappUrl: String) async throws -> NotifySubscriptionPayload.Wrapper { - let types = try await notifyConfigProvider.getSubscriptionScope(dappUrl: dappUrl) + let types = try await notifyConfigProvider.getSubscriptionScope(appDomain: dappUrl) let scope = types.map{$0.name}.joined(separator: " ") let jwtPayload = NotifySubscriptionPayload(dappPubKey: dappPubKey, keyserver: keyserverURL, subscriptionAccount: subscriptionAccount, dappUrl: dappUrl, scope: scope) return try identityClient.signAndCreateWrapper( diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift index 9fb7e080f..ab8620684 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift @@ -69,7 +69,7 @@ class NotifySubscribeResponseSubscriber { try groupKeychainStorage.add(agreementKeysP, forKey: notifySubscriptionTopic) account = try Account(DIDPKHString: claims.sub) metadata = try dappsMetadataStore.get(key: payload.topic) - let availableTypes = try await notifyConfigProvider.getSubscriptionScope(dappUrl: metadata!.url) + let availableTypes = try await notifyConfigProvider.getSubscriptionScope(appDomain: metadata!.url) subscribedTypes = availableTypes.filter{subscribedScope.contains($0.name)} logger.debug("NotifySubscribeResponseSubscriber: subscribing notify subscription topic: \(notifySubscriptionTopic!)") try await networkingInteractor.subscribe(topic: notifySubscriptionTopic) From c5b8b0cc10cf5b03604b7b6935aa79e38d5ee129 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Sep 2023 18:50:09 +0200 Subject: [PATCH 51/91] fix typo --- .../NotifyWatchSubscriptionsRequester.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift index 710e163a0..170b390bc 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift @@ -77,7 +77,7 @@ class NotifyWatchSubscriptionsRequester { try kms.setAgreementSecret(agreementKeys, topic: responseTopic) - // save for later under dapp's accout + pub key + // save for later under dapp's account + pub key try kms.setTopic(responseTopic, for: keyYStorageKey) return (responseTopic: responseTopic, selfPubKeyY: selfPubKeyY.rawRepresentation) From 578d1e8c6043087ad686919e169d71f780f30750 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 09:26:32 +0200 Subject: [PATCH 52/91] set self pub key Y for response topic --- .../NotifyWatchSubscriptionsRequester.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift index 170b390bc..5f5c9c3d2 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift @@ -67,7 +67,6 @@ class NotifyWatchSubscriptionsRequester { return (responseTopic: responseTopic, selfPubKeyY: selfPubKeyY.rawRepresentation) } else { let selfPubKeyY = try kms.createX25519KeyPair() - let watchSubscriptionsTopic = notifyServerPublicKey.rawRepresentation.sha256().toHexString() let agreementKeys = try kms.performKeyAgreement(selfPublicKey: selfPubKeyY, peerPublicKey: notifyServerPublicKey.hexRepresentation) @@ -79,6 +78,7 @@ class NotifyWatchSubscriptionsRequester { // save for later under dapp's account + pub key try kms.setTopic(responseTopic, for: keyYStorageKey) + try kms.setPublicKey(publicKey: selfPubKeyY, for: responseTopic) return (responseTopic: responseTopic, selfPubKeyY: selfPubKeyY.rawRepresentation) } From 1297766d9ad281552ddfb37dff5648827bb2e02b Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Tue, 12 Sep 2023 15:55:18 +0800 Subject: [PATCH 53/91] isLimited false by default --- Example/IntegrationTests/Push/NotifyTests.swift | 14 +++++++------- .../Client/Wallet/NotifyClient.swift | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index e7944060c..da71d5b71 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -103,7 +103,7 @@ final class NotifyTests: XCTestCase { } }.store(in: &publishers) - try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) wait(for: [expectation], timeout: InputConfig.defaultTimeout) @@ -122,12 +122,12 @@ final class NotifyTests: XCTestCase { } }.store(in: &publishers) - try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) sleep(1) - try! await clientB.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) + try! await clientB.register(account: account, domain: gmDappDomain, onSign: sign) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } @@ -145,8 +145,8 @@ final class NotifyTests: XCTestCase { } }.store(in: &publishers) - try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) - try! await clientB.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, onSign: sign) + try! await clientB.register(account: account, domain: gmDappDomain, onSign: sign) sleep(1) @@ -159,7 +159,7 @@ final class NotifyTests: XCTestCase { let expectation = expectation(description: "expects to create and update notify subscription") let updateScope: Set = ["alerts"] - try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) walletNotifyClientA.newSubscriptionPublisher @@ -190,7 +190,7 @@ final class NotifyTests: XCTestCase { let metadata = AppMetadata(name: "GM Dapp", description: "", url: gmDappDomain, icons: []) - try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, isLimited: false, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) walletNotifyClientA.newSubscriptionPublisher diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 4d23691d4..b1742a9dc 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -86,7 +86,7 @@ public class NotifyClient { self.notifySubscriptionsChangedRequestSubscriber = notifySubscriptionsChangedRequestSubscriber } - public func register(account: Account, domain: String, isLimited: Bool, onSign: @escaping SigningCallback) async throws { + public func register(account: Account, domain: String, isLimited: Bool = false, onSign: @escaping SigningCallback) async throws { try await identityService.register(account: account, domain: domain, isLimited: isLimited, onSign: onSign) try await notifyWatchSubscriptionsRequester.watchSubscriptions(account: account) } From d2b4088040f9276c58f003393886770173aaca5f Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 09:59:51 +0200 Subject: [PATCH 54/91] fix tests --- .../NotifyWatchSubscriptionsRequester.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift index 5f5c9c3d2..afb178f92 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift @@ -63,7 +63,7 @@ class NotifyWatchSubscriptionsRequester { let keyYStorageKey = "\(account)_\(notifyServerPublicKey.hexRepresentation)" if let responseTopic = kms.getTopic(for: keyYStorageKey), - let selfPubKeyY = kms.getPublicKey(for: responseTopic) { + let selfPubKeyY = kms.getAgreementSecret(for: responseTopic)?.publicKey { return (responseTopic: responseTopic, selfPubKeyY: selfPubKeyY.rawRepresentation) } else { let selfPubKeyY = try kms.createX25519KeyPair() @@ -78,7 +78,6 @@ class NotifyWatchSubscriptionsRequester { // save for later under dapp's account + pub key try kms.setTopic(responseTopic, for: keyYStorageKey) - try kms.setPublicKey(publicKey: selfPubKeyY, for: responseTopic) return (responseTopic: responseTopic, selfPubKeyY: selfPubKeyY.rawRepresentation) } From 6c64b424b1325c4d0e08288c5efd11ce0b681d49 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Tue, 12 Sep 2023 00:34:59 +0800 Subject: [PATCH 55/91] App to did:web --- .../DeleteNotifySubscriptionRequester.swift | 4 +-- .../NotifyUpdateRequester.swift | 7 ++-- .../NotifyUpdateResponseSubscriber.swift | 6 ++-- .../NotifySubscribeRequester.swift | 9 +++--- .../JWTPayloads/NotifyDeletePayload.swift | 8 ++--- .../NotifyDeleteResponsePayload.swift | 6 ++-- .../JWTPayloads/NotifyMessagePayload.swift | 8 ++--- .../NotifyMessageReceiptPayload.swift | 8 ++--- .../NotifySubscriptionPayload.swift | 10 +++--- .../JWTPayloads/NotifyUpdatePayload.swift | 10 +++--- .../NotifyUpdateResponsePayload.swift | 6 ++-- Sources/WalletConnectUtils/DID/DIDWeb.swift | 32 +++++++++++++++++++ 12 files changed, 74 insertions(+), 40 deletions(-) create mode 100644 Sources/WalletConnectUtils/DID/DIDWeb.swift diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift index e23ae9d61..c52fd40cb 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift @@ -42,7 +42,7 @@ class DeleteNotifySubscriptionRequester { let wrapper = try createJWTWrapper( dappPubKey: DIDKey(rawData: dappAuthenticationKey), reason: NotifyDeleteParams.userDisconnected.message, - app: subscription.metadata.url, + app: DIDWeb(host: subscription.metadata.url), account: subscription.account ) @@ -66,7 +66,7 @@ class DeleteNotifySubscriptionRequester { private extension DeleteNotifySubscriptionRequester { - func createJWTWrapper(dappPubKey: DIDKey, reason: String, app: String, account: Account) throws -> NotifyDeletePayload.Wrapper { + func createJWTWrapper(dappPubKey: DIDKey, reason: String, app: DIDWeb, account: Account) throws -> NotifyDeletePayload.Wrapper { let jwtPayload = NotifyDeletePayload(keyserver: keyserver, dappPubKey: dappPubKey, reason: reason, app: app) return try identityClient.signAndCreateWrapper( payload: jwtPayload, diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift index 18876c53e..7ddb67379 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateRequester.swift @@ -45,7 +45,7 @@ class NotifyUpdateRequester: NotifyUpdateRequesting { let request = try createJWTRequest( dappPubKey: DIDKey(rawData: dappAuthenticationKey), subscriptionAccount: subscription.account, - dappUrl: subscription.metadata.url, scope: scope + appDomain: subscription.metadata.url, scope: scope ) let protocolMethod = NotifyUpdateProtocolMethod() @@ -53,10 +53,11 @@ class NotifyUpdateRequester: NotifyUpdateRequesting { try await networkingInteractor.request(request, topic: topic, protocolMethod: protocolMethod) } - private func createJWTRequest(dappPubKey: DIDKey, subscriptionAccount: Account, dappUrl: String, scope: Set) throws -> RPCRequest { + private func createJWTRequest(dappPubKey: DIDKey, subscriptionAccount: Account, appDomain: String, scope: Set) throws -> RPCRequest { let protocolMethod = NotifyUpdateProtocolMethod().method let scopeClaim = scope.joined(separator: " ") - let jwtPayload = NotifyUpdatePayload(dappPubKey: dappPubKey, keyserver: keyserverURL, subscriptionAccount: subscriptionAccount, dappUrl: dappUrl, scope: scopeClaim) + let app = DIDWeb(host: appDomain) + let jwtPayload = NotifyUpdatePayload(dappPubKey: dappPubKey, keyserver: keyserverURL, subscriptionAccount: subscriptionAccount, app: app, scope: scopeClaim) let wrapper = try identityClient.signAndCreateWrapper( payload: jwtPayload, account: subscriptionAccount diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift index 549ede05d..a6f60cab6 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift @@ -43,7 +43,7 @@ private extension NotifyUpdateResponseSubscriber { let (requestPayload, requestClaims) = try NotifyUpdatePayload.decodeAndVerify(from: payload.request) let (_, _) = try NotifyUpdateResponsePayload.decodeAndVerify(from: payload.response) - let scope = try await buildScope(selected: requestPayload.scope, dappUrl: requestPayload.dappUrl) + let scope = try await buildScope(selected: requestPayload.scope, appDomain: requestPayload.app.host) guard let oldSubscription = notifyStorage.getSubscription(topic: subscriptionTopic) else { logger.debug("NotifyUpdateResponseSubscriber Subscription does not exist") @@ -56,9 +56,9 @@ private extension NotifyUpdateResponseSubscriber { } } - func buildScope(selected: String, dappUrl: String) async throws -> [String: ScopeValue] { + func buildScope(selected: String, appDomain: String) async throws -> [String: ScopeValue] { let selectedScope = selected.components(separatedBy: " ") - let availableScope = try await nofityConfigProvider.getSubscriptionScope(appDomain: dappUrl) + let availableScope = try await nofityConfigProvider.getSubscriptionScope(appDomain: appDomain) return availableScope.reduce(into: [:]) { $0[$1.name] = ScopeValue(description: $1.description, enabled: selectedScope.contains($1.name)) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift index 932c71f90..6601d77b7 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeRequester.swift @@ -60,7 +60,7 @@ class NotifySubscribeRequester { let subscriptionAuthWrapper = try await createJWTWrapper( dappPubKey: DIDKey(did: peerPublicKey.did), subscriptionAccount: account, - dappUrl: appDomain + appDomain: appDomain ) let request = RPCRequest(method: protocolMethod.method, params: subscriptionAuthWrapper) @@ -79,10 +79,11 @@ class NotifySubscribeRequester { return keys } - private func createJWTWrapper(dappPubKey: DIDKey, subscriptionAccount: Account, dappUrl: String) async throws -> NotifySubscriptionPayload.Wrapper { - let types = try await notifyConfigProvider.getSubscriptionScope(appDomain: dappUrl) + private func createJWTWrapper(dappPubKey: DIDKey, subscriptionAccount: Account, appDomain: String) async throws -> NotifySubscriptionPayload.Wrapper { + let types = try await notifyConfigProvider.getSubscriptionScope(appDomain: appDomain) let scope = types.map{$0.name}.joined(separator: " ") - let jwtPayload = NotifySubscriptionPayload(dappPubKey: dappPubKey, keyserver: keyserverURL, subscriptionAccount: subscriptionAccount, dappUrl: dappUrl, scope: scope) + let app = DIDWeb(host: appDomain) + let jwtPayload = NotifySubscriptionPayload(dappPubKey: dappPubKey, keyserver: keyserverURL, subscriptionAccount: subscriptionAccount, app: app, scope: scope) return try identityClient.signAndCreateWrapper( payload: jwtPayload, account: subscriptionAccount diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeletePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeletePayload.swift index 62aa74204..454b79fa5 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeletePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeletePayload.swift @@ -41,13 +41,13 @@ struct NotifyDeletePayload: JWTClaimsCodable { let keyserver: URL let dappPubKey: DIDKey let reason: String - let app: String + let app: DIDWeb init( keyserver: URL, dappPubKey: DIDKey, reason: String, - app: String + app: DIDWeb ) { self.keyserver = keyserver self.dappPubKey = dappPubKey @@ -59,7 +59,7 @@ struct NotifyDeletePayload: JWTClaimsCodable { self.keyserver = try claims.ksu.asURL() self.dappPubKey = try DIDKey(did: claims.aud) self.reason = claims.sub - self.app = claims.app + self.app = try DIDWeb(did: claims.app) } func encode(iss: String) throws -> Claims { @@ -71,7 +71,7 @@ struct NotifyDeletePayload: JWTClaimsCodable { iss: iss, aud: dappPubKey.did(variant: .ED25519), sub: reason, - app: app + app: app.did ) } } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeleteResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeleteResponsePayload.swift index 83be1586c..ed5d897a3 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeleteResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeleteResponsePayload.swift @@ -38,12 +38,12 @@ struct NotifyDeleteResponsePayload: JWTClaimsCodable { let selfPubKey: DIDKey let subscriptionHash: String - let app: String + let app: DIDWeb init(claims: Claims) throws { self.selfPubKey = try DIDKey(did: claims.aud) self.subscriptionHash = claims.sub - self.app = claims.app + self.app = try DIDWeb(did: claims.app) } func encode(iss: String) throws -> Claims { @@ -54,7 +54,7 @@ struct NotifyDeleteResponsePayload: JWTClaimsCodable { iss: iss, aud: selfPubKey.did(variant: .ED25519), sub: subscriptionHash, - app: app + app: app.did ) } } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift index 8d220a5c0..916757b18 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift @@ -41,14 +41,14 @@ struct NotifyMessagePayload: JWTClaimsCodable { let dappAuthenticationKey: DIDKey let account: Account let subscriptionId: String - let app: String + let app: DIDWeb let message: NotifyMessage init(claims: Claims) throws { self.dappAuthenticationKey = try DIDKey(did: claims.iss) self.account = try DIDPKH(did: claims.aud).account self.subscriptionId = claims.sub - self.app = claims.app + self.app = try DIDWeb(did: claims.app) self.message = claims.msg } @@ -60,9 +60,9 @@ struct NotifyMessagePayload: JWTClaimsCodable { iss: dappAuthenticationKey.multibase(variant: .ED25519), aud: account.did, sub: subscriptionId, - app: app, + app: app.did, msg: message ) } -} \ No newline at end of file +} diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift index c3bdf466c..f31fa1f5a 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift @@ -41,13 +41,13 @@ struct NotifyMessageReceiptPayload: JWTClaimsCodable { let keyserver: URL let dappPubKey: DIDKey let messageHash: String - let app: String + let app: DIDWeb init( keyserver: URL, dappPubKey: DIDKey, messageHash: String, - app: String + app: DIDWeb ) { self.keyserver = keyserver self.dappPubKey = dappPubKey @@ -59,7 +59,7 @@ struct NotifyMessageReceiptPayload: JWTClaimsCodable { self.keyserver = try claims.ksu.asURL() self.dappPubKey = try DIDKey(did: claims.aud) self.messageHash = claims.sub - self.app = claims.app + self.app = try DIDWeb(did: claims.app) } func encode(iss: String) throws -> Claims { @@ -71,7 +71,7 @@ struct NotifyMessageReceiptPayload: JWTClaimsCodable { iss: iss, aud: dappPubKey.did(variant: .ED25519), sub: messageHash, - app: app + app: app.did ) } } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionPayload.swift index 847635da0..03e1d065a 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionPayload.swift @@ -43,14 +43,14 @@ struct NotifySubscriptionPayload: JWTClaimsCodable { let dappPubKey: DIDKey let keyserver: URL let subscriptionAccount: Account - let dappUrl: String + let app: DIDWeb let scope: String - init(dappPubKey: DIDKey, keyserver: URL, subscriptionAccount: Account, dappUrl: String, scope: String) { + init(dappPubKey: DIDKey, keyserver: URL, subscriptionAccount: Account, app: DIDWeb, scope: String) { self.dappPubKey = dappPubKey self.keyserver = keyserver self.subscriptionAccount = subscriptionAccount - self.dappUrl = dappUrl + self.app = app self.scope = scope } @@ -58,7 +58,7 @@ struct NotifySubscriptionPayload: JWTClaimsCodable { self.dappPubKey = try DIDKey(did: claims.aud) self.keyserver = try claims.ksu.asURL() self.subscriptionAccount = try Account(DIDPKHString: claims.sub) - self.dappUrl = claims.app + self.app = try DIDWeb(did: claims.app) self.scope = claims.scp } @@ -72,7 +72,7 @@ struct NotifySubscriptionPayload: JWTClaimsCodable { aud: dappPubKey.did(variant: .ED25519), sub: subscriptionAccount.did, scp: scope, - app: dappUrl + app: app.did ) } } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdatePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdatePayload.swift index ef88ebc87..c3195c7d6 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdatePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdatePayload.swift @@ -43,14 +43,14 @@ struct NotifyUpdatePayload: JWTClaimsCodable { let dappPubKey: DIDKey let keyserver: URL let subscriptionAccount: Account - let dappUrl: String + let app: DIDWeb let scope: String - init(dappPubKey: DIDKey, keyserver: URL, subscriptionAccount: Account, dappUrl: String, scope: String) { + init(dappPubKey: DIDKey, keyserver: URL, subscriptionAccount: Account, app: DIDWeb, scope: String) { self.dappPubKey = dappPubKey self.keyserver = keyserver self.subscriptionAccount = subscriptionAccount - self.dappUrl = dappUrl + self.app = app self.scope = scope } @@ -58,7 +58,7 @@ struct NotifyUpdatePayload: JWTClaimsCodable { self.dappPubKey = try DIDKey(did: claims.aud) self.keyserver = try claims.ksu.asURL() self.subscriptionAccount = try Account(DIDPKHString: claims.sub) - self.dappUrl = claims.app + self.app = try DIDWeb(did: claims.app) self.scope = claims.scp } @@ -72,7 +72,7 @@ struct NotifyUpdatePayload: JWTClaimsCodable { aud: dappPubKey.did(variant: .ED25519), sub: subscriptionAccount.did, scp: scope, - app: dappUrl + app: app.did ) } } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdateResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdateResponsePayload.swift index 2153c7f9b..08accba0b 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdateResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdateResponsePayload.swift @@ -38,12 +38,12 @@ struct NotifyUpdateResponsePayload: JWTClaimsCodable { let selfPubKey: DIDKey let subscriptionHash: String - let app: String + let app: DIDWeb init(claims: Claims) throws { self.selfPubKey = try DIDKey(did: claims.aud) self.subscriptionHash = claims.sub - self.app = claims.app + self.app = try DIDWeb(did: claims.app) } func encode(iss: String) throws -> Claims { @@ -54,7 +54,7 @@ struct NotifyUpdateResponsePayload: JWTClaimsCodable { iss: iss, aud: selfPubKey.did(variant: .ED25519), sub: subscriptionHash, - app: app + app: app.did ) } } diff --git a/Sources/WalletConnectUtils/DID/DIDWeb.swift b/Sources/WalletConnectUtils/DID/DIDWeb.swift new file mode 100644 index 000000000..61d46ab9b --- /dev/null +++ b/Sources/WalletConnectUtils/DID/DIDWeb.swift @@ -0,0 +1,32 @@ +import Foundation + +public struct DIDWeb { + + public let host: String + + public init(url: URL) throws { + guard let host = url.host else { throw Errors.invalidUrl } + self.host = host + } + + public init(did: String) throws { + guard let host = did.components(separatedBy: ":").last else { throw Errors.invalidDid } + self.host = host + } + + public init(host: String) { + self.host = host + } + + public var did: String { + return "did:web:\(host)" + } +} + +extension DIDWeb { + + enum Errors: Error { + case invalidUrl + case invalidDid + } +} From 0b13da788095b3ba6f42831441bb110b20d28536 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Tue, 12 Sep 2023 17:02:17 +0800 Subject: [PATCH 56/91] sub updated in JWT's --- .../IntegrationTests/Auth/Signer/SignerTests.swift | 2 +- Sources/Auth/Types/AuthPayload.swift | 2 +- Sources/Chat/Types/Payloads/MessagePayload.swift | 2 +- Sources/Chat/Types/Payloads/ReceiptPayload.swift | 2 +- .../Types/JWTPayloads/NotifyDeletePayload.swift | 12 ++++++------ .../JWTPayloads/NotifyDeleteResponsePayload.swift | 8 ++++---- .../Types/JWTPayloads/NotifyMessagePayload.swift | 10 ++++------ .../JWTPayloads/NotifyMessageReceiptPayload.swift | 12 ++++++------ .../NotifySubscriptionResponsePayload.swift | 8 ++++---- .../JWTPayloads/NotifyUpdateResponsePayload.swift | 8 ++++---- .../NotifySubscriptionsChangedRequestPayload.swift | 6 +++--- .../NotifySubscriptionsChangedResponsePayload.swift | 9 +++++++-- .../NotifyWatchSubscriptionsResponsePayload.swift | 7 ++++++- Sources/WalletConnectUtils/DID/DIDPKH.swift | 8 ++++---- 14 files changed, 52 insertions(+), 44 deletions(-) diff --git a/Example/IntegrationTests/Auth/Signer/SignerTests.swift b/Example/IntegrationTests/Auth/Signer/SignerTests.swift index 568dd2c82..8f6381237 100644 --- a/Example/IntegrationTests/Auth/Signer/SignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/SignerTests.swift @@ -32,6 +32,6 @@ class SignerTest: XCTestCase { func testSignerAddressFromAccount() throws { let account = Account("eip155:1:0xBAc675C310721717Cd4A37F6cbeA1F081b1C2a07")! - XCTAssertEqual(DIDPKH(account: account).string, "did:pkh:eip155:1:0xBAc675C310721717Cd4A37F6cbeA1F081b1C2a07") + XCTAssertEqual(account.did, "did:pkh:eip155:1:0xBAc675C310721717Cd4A37F6cbeA1F081b1C2a07") } } diff --git a/Sources/Auth/Types/AuthPayload.swift b/Sources/Auth/Types/AuthPayload.swift index 23338434f..33ba49756 100644 --- a/Sources/Auth/Types/AuthPayload.swift +++ b/Sources/Auth/Types/AuthPayload.swift @@ -36,7 +36,7 @@ public struct AuthPayload: Codable, Equatable { throw Errors.invalidChainID } return CacaoPayload( - iss: DIDPKH(account: account).string, + iss: account.did, domain: domain, aud: aud, version: version, diff --git a/Sources/Chat/Types/Payloads/MessagePayload.swift b/Sources/Chat/Types/Payloads/MessagePayload.swift index 445612dc9..1452b2160 100644 --- a/Sources/Chat/Types/Payloads/MessagePayload.swift +++ b/Sources/Chat/Types/Payloads/MessagePayload.swift @@ -54,7 +54,7 @@ struct MessagePayload: JWTClaimsCodable { iat: defaultIatMilliseconds(), exp: expiry(days: 30), ksu: keyserver.absoluteString, - aud: DIDPKH(account: recipientAccount).string, + aud: recipientAccount.did, sub: message, act: Claims.action ) diff --git a/Sources/Chat/Types/Payloads/ReceiptPayload.swift b/Sources/Chat/Types/Payloads/ReceiptPayload.swift index 90362b305..304b4662a 100644 --- a/Sources/Chat/Types/Payloads/ReceiptPayload.swift +++ b/Sources/Chat/Types/Payloads/ReceiptPayload.swift @@ -52,7 +52,7 @@ struct ReceiptPayload: JWTClaimsCodable { exp: expiry(days: 30), ksu: keyserver.absoluteString, sub: messageHash, - aud: DIDPKH(account: senderAccount).string, + aud: senderAccount.did, act: Claims.action ) } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeletePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeletePayload.swift index 454b79fa5..5b6898d6f 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeletePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeletePayload.swift @@ -16,7 +16,7 @@ struct NotifyDeletePayload: JWTClaimsCodable { let iss: String /// `did:key` of an identity key. Enables to resolve associated Dapp domain used. let aud: String - /// Reason for deleting the subscription + /// Blockchain account that notify subscription has been proposed for -`did:pkh` let sub: String /// Dapp's domain url let app: String @@ -38,27 +38,27 @@ struct NotifyDeletePayload: JWTClaimsCodable { } } + let account: Account let keyserver: URL let dappPubKey: DIDKey - let reason: String let app: DIDWeb init( + account: Account, keyserver: URL, dappPubKey: DIDKey, - reason: String, app: DIDWeb ) { + self.account = account self.keyserver = keyserver self.dappPubKey = dappPubKey - self.reason = reason self.app = app } init(claims: Claims) throws { + self.account = try Account(DIDPKHString: claims.sub) self.keyserver = try claims.ksu.asURL() self.dappPubKey = try DIDKey(did: claims.aud) - self.reason = claims.sub self.app = try DIDWeb(did: claims.app) } @@ -70,7 +70,7 @@ struct NotifyDeletePayload: JWTClaimsCodable { act: Claims.action, iss: iss, aud: dappPubKey.did(variant: .ED25519), - sub: reason, + sub: account.did, app: app.did ) } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeleteResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeleteResponsePayload.swift index ed5d897a3..b9f97cc43 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeleteResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyDeleteResponsePayload.swift @@ -14,7 +14,7 @@ struct NotifyDeleteResponsePayload: JWTClaimsCodable { let iss: String /// `did:key` of an identity key. Enables to resolve attached blockchain account. let aud: String - /// Hash of the existing subscription payload + /// Blockchain account that notify subscription has been proposed for -`did:pkh` let sub: String /// Dapp's domain url let app: String @@ -36,13 +36,13 @@ struct NotifyDeleteResponsePayload: JWTClaimsCodable { } } + let account: Account let selfPubKey: DIDKey - let subscriptionHash: String let app: DIDWeb init(claims: Claims) throws { + self.account = try Account(DIDPKHString: claims.sub) self.selfPubKey = try DIDKey(did: claims.aud) - self.subscriptionHash = claims.sub self.app = try DIDWeb(did: claims.app) } @@ -53,7 +53,7 @@ struct NotifyDeleteResponsePayload: JWTClaimsCodable { act: Claims.action, iss: iss, aud: selfPubKey.did(variant: .ED25519), - sub: subscriptionHash, + sub: account.did, app: app.did ) } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift index 916757b18..34bfee51e 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift @@ -14,7 +14,7 @@ struct NotifyMessagePayload: JWTClaimsCodable { let iss: String /// Blockchain account `did:pkh` let aud: String - /// Subscription ID (sha256 hash of subscriptionAuth) + /// Blockchain account that notify subscription has been proposed for -`did:pkh` let sub: String /// Dapp domain url let app: String @@ -40,14 +40,12 @@ struct NotifyMessagePayload: JWTClaimsCodable { let dappAuthenticationKey: DIDKey let account: Account - let subscriptionId: String let app: DIDWeb let message: NotifyMessage init(claims: Claims) throws { self.dappAuthenticationKey = try DIDKey(did: claims.iss) - self.account = try DIDPKH(did: claims.aud).account - self.subscriptionId = claims.sub + self.account = try DIDPKH(did: claims.sub).account self.app = try DIDWeb(did: claims.app) self.message = claims.msg } @@ -58,8 +56,8 @@ struct NotifyMessagePayload: JWTClaimsCodable { exp: expiry(days: 1), act: Claims.action, iss: dappAuthenticationKey.multibase(variant: .ED25519), - aud: account.did, - sub: subscriptionId, + aud: account.did, // TODO: Should we remove or merge with msg? + sub: account.did, app: app.did, msg: message ) diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift index f31fa1f5a..985473cf5 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessageReceiptPayload.swift @@ -16,7 +16,7 @@ struct NotifyMessageReceiptPayload: JWTClaimsCodable { let iss: String /// `did:key` of an identity key. Enables to resolve associated Dapp domain used. let aud: String - /// Hash of the stringified notify message object received + /// Blockchain account that notify subscription has been proposed for -`did:pkh` let sub: String /// Dapp's domain url let app: String @@ -38,27 +38,27 @@ struct NotifyMessageReceiptPayload: JWTClaimsCodable { } } + let account: Account let keyserver: URL let dappPubKey: DIDKey - let messageHash: String let app: DIDWeb init( + account: Account, keyserver: URL, dappPubKey: DIDKey, - messageHash: String, app: DIDWeb ) { + self.account = account self.keyserver = keyserver self.dappPubKey = dappPubKey - self.messageHash = messageHash self.app = app } init(claims: Claims) throws { + self.account = try Account(DIDPKHString: claims.sub) self.keyserver = try claims.ksu.asURL() self.dappPubKey = try DIDKey(did: claims.aud) - self.messageHash = claims.sub self.app = try DIDWeb(did: claims.app) } @@ -70,7 +70,7 @@ struct NotifyMessageReceiptPayload: JWTClaimsCodable { act: Claims.action, iss: iss, aud: dappPubKey.did(variant: .ED25519), - sub: messageHash, + sub: account.did, app: app.did ) } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift index f972f345b..8ed7e775e 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift @@ -14,7 +14,7 @@ struct NotifySubscriptionResponsePayload: JWTClaimsCodable { let iss: String /// `did:key` of an identity key. Allows for the resolution of the attached blockchain account. let aud: String - /// `did:key` of the public key used for key agreement on the Notify topic + /// Blockchain account that notify subscription has been proposed for -`did:pkh` let sub: String /// Dapp's domain url let app: String @@ -36,13 +36,13 @@ struct NotifySubscriptionResponsePayload: JWTClaimsCodable { } } + let account: Account let selfPubKey: DIDKey - let publicKey: DIDKey let app: String init(claims: Claims) throws { + self.account = try Account(DIDPKHString: claims.sub) self.selfPubKey = try DIDKey(did: claims.aud) - self.publicKey = try DIDKey(did: claims.sub) self.app = claims.app } @@ -53,7 +53,7 @@ struct NotifySubscriptionResponsePayload: JWTClaimsCodable { act: Claims.action, iss: iss, aud: selfPubKey.did(variant: .ED25519), - sub: publicKey.did(variant: .X25519), + sub: account.did, app: app ) } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdateResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdateResponsePayload.swift index 08accba0b..a03ca61f8 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdateResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyUpdateResponsePayload.swift @@ -14,7 +14,7 @@ struct NotifyUpdateResponsePayload: JWTClaimsCodable { let iss: String /// `did:key` of an identity key. Enables to resolve attached blockchain account. let aud: String - /// Hash of the new subscription payload + /// Blockchain account that notify subscription has been proposed for -`did:pkh` let sub: String /// Dapp's domain url let app: String @@ -36,13 +36,13 @@ struct NotifyUpdateResponsePayload: JWTClaimsCodable { } } + let account: Account let selfPubKey: DIDKey - let subscriptionHash: String let app: DIDWeb init(claims: Claims) throws { + self.account = try Account(DIDPKHString: claims.sub) self.selfPubKey = try DIDKey(did: claims.aud) - self.subscriptionHash = claims.sub self.app = try DIDWeb(did: claims.app) } @@ -53,7 +53,7 @@ struct NotifyUpdateResponsePayload: JWTClaimsCodable { act: Claims.action, iss: iss, aud: selfPubKey.did(variant: .ED25519), - sub: subscriptionHash, + sub: account.did, app: app.did ) } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift index f3dbc3f3c..5dc241ecc 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedRequestPayload.swift @@ -13,10 +13,10 @@ struct NotifySubscriptionsChangedRequestPayload: JWTClaimsCodable { let iss: String /// Blockchain account `did:pkh` let aud: String - /// message sent by the author account - let sub: String /// array of Notify Server Subscriptions let sbs: [NotifyServerSubscription] + /// Blockchain account that notify subscription has been proposed for -`did:pkh` + let sub: String static var action: String? { return "notify_subscriptions_changed" @@ -42,7 +42,7 @@ struct NotifySubscriptionsChangedRequestPayload: JWTClaimsCodable { init(claims: Claims) throws { self.notifyServerAuthenticationKey = try DIDKey(did: claims.iss) self.subscriptions = claims.sbs - self.account = try DIDPKH(did: claims.sub).account + self.account = try Account(DIDPKHString: claims.sub) } func encode(iss: String) throws -> Claims { diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift index 949a1bab8..0fd37fb8a 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_subscriptions_changed/NotifySubscriptionsChangedResponsePayload.swift @@ -15,6 +15,8 @@ struct NotifySubscriptionsChangedResponsePayload: JWTClaimsCodable { let iss: String /// `did:key` of Notify Server authentication key let aud: String + /// Blockchain account that notify subscription has been proposed for -`did:pkh` + let sub: String static var action: String? { return "notify_subscriptions_changed_response" @@ -33,11 +35,13 @@ struct NotifySubscriptionsChangedResponsePayload: JWTClaimsCodable { } } - init(keyserver: URL, notifyServerAuthenticationKey: DIDKey) { + init(account: Account, keyserver: URL, notifyServerAuthenticationKey: DIDKey) { + self.account = account self.keyserver = keyserver self.notifyServerAuthenticationKey = notifyServerAuthenticationKey } + let account: Account let notifyServerAuthenticationKey: DIDKey let keyserver: URL @@ -52,7 +56,8 @@ struct NotifySubscriptionsChangedResponsePayload: JWTClaimsCodable { ksu: keyserver.absoluteString, act: Claims.action, iss: iss, - aud: notifyServerAuthenticationKey.did(variant: .ED25519) + aud: notifyServerAuthenticationKey.did(variant: .ED25519), + sub: account.did ) } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift index 26ad43a99..57e3f48f5 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/notify_watch_subscriptions/NotifyWatchSubscriptionsResponsePayload.swift @@ -15,6 +15,8 @@ struct NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { let aud: String /// array of Notify Subscriptions let sbs: [NotifyServerSubscription] + /// Blockchain account that notify subscription has been proposed for -`did:pkh` + let sub: String static var action: String? { return "notify_watch_subscriptions_response" @@ -33,10 +35,12 @@ struct NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { } } + let account: Account let subscriptions: [NotifyServerSubscription] let selfIdentityKey: DIDKey init(claims: Claims) throws { + self.account = try Account(DIDPKHString: claims.sub) self.selfIdentityKey = try DIDKey(did: claims.aud) self.subscriptions = claims.sbs } @@ -48,7 +52,8 @@ struct NotifyWatchSubscriptionsResponsePayload: JWTClaimsCodable { act: Claims.action, iss: iss, aud: selfIdentityKey.did(variant: .ED25519), - sbs: subscriptions + sbs: subscriptions, + sub: account.did ) } diff --git a/Sources/WalletConnectUtils/DID/DIDPKH.swift b/Sources/WalletConnectUtils/DID/DIDPKH.swift index ffb428234..3930d257b 100644 --- a/Sources/WalletConnectUtils/DID/DIDPKH.swift +++ b/Sources/WalletConnectUtils/DID/DIDPKH.swift @@ -10,7 +10,7 @@ public struct DIDPKH { } public let account: Account - public let string: String + public let did: String public init(did: String) throws { guard did.starts(with: DIDPKH.didPrefix) @@ -22,12 +22,12 @@ public struct DIDPKH { guard let account = Account(string) else { throw Errors.invalidAccount } - self.string = string + self.did = did self.account = account } public init(account: Account) { - self.string = "\(DIDPKH.didPrefix):\(account.absoluteString)" + self.did = "\(DIDPKH.didPrefix):\(account.absoluteString)" self.account = account } } @@ -39,6 +39,6 @@ extension Account { } public var did: String { - return DIDPKH(account: self).string + return DIDPKH(account: self).did } } From 7114823f839a6b87495377f82469bc8511ad7703 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 11:02:20 +0200 Subject: [PATCH 57/91] add notify_subscriptions_changed to w3i --- Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequest.swift | 1 + .../NotifyClientProxy/NotifyClientRequestSubscriber.swift | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequest.swift b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequest.swift index b152330ce..ddac26a48 100644 --- a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequest.swift +++ b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequest.swift @@ -5,6 +5,7 @@ enum NotifyClientRequest: String { case notifyUpdate = "notify_update" case notifyDelete = "notify_delete" case notifySubscription = "notify_subscription" + case notifySubscriptionsChanged = "notify_subscriptions_changed" var method: String { return rawValue diff --git a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequestSubscriber.swift b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequestSubscriber.swift index 8b255bd81..a9c4c1558 100644 --- a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequestSubscriber.swift +++ b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequestSubscriber.swift @@ -33,6 +33,9 @@ final class NotifyClientRequestSubscriber { client.updateSubscriptionPublisher.sink { [unowned self] subscription in handle(event: .notifyUpdate, params: subscription) }.store(in: &publishers) + client.subscriptionsPublisher.sink { [unowned self] subscriptions in + handle(event: .notifySubscriptionsChanged, params: subscriptions) + }.store(in: &publishers) } } From 8ad5a1328bc8062fc1cf637aa8efd7f0b47992ce Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Tue, 12 Sep 2023 17:25:04 +0800 Subject: [PATCH 58/91] JWT integration code updated --- .../DeleteNotifySubscriptionRequester.swift | 2 +- .../wc_notifyMessage/NotifyMessageSubscriber.swift | 9 +++++---- .../NotifySubscriptionsChangedRequestSubscriber.swift | 2 +- .../JWTPayloads/NotifySubscriptionResponsePayload.swift | 8 ++++---- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift index c52fd40cb..ea3281849 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionRequester.swift @@ -67,7 +67,7 @@ class DeleteNotifySubscriptionRequester { private extension DeleteNotifySubscriptionRequester { func createJWTWrapper(dappPubKey: DIDKey, reason: String, app: DIDWeb, account: Account) throws -> NotifyDeletePayload.Wrapper { - let jwtPayload = NotifyDeletePayload(keyserver: keyserver, dappPubKey: dappPubKey, reason: reason, app: app) + let jwtPayload = NotifyDeletePayload(account: account, keyserver: keyserver, dappPubKey: dappPubKey, app: app) return try identityClient.signAndCreateWrapper( payload: jwtPayload, account: account diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift index 5763c4b05..2ebd5125f 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift @@ -33,17 +33,18 @@ class NotifyMessageSubscriber { logger.debug("Received Notify Message on topic: \(payload.topic)", properties: ["topic": payload.topic]) let (messagePayload, claims) = try NotifyMessagePayload.decodeAndVerify(from: payload.request) + logger.debug("Decoded Notify Message: \(payload.topic)", properties: ["topic": payload.topic, "messageBody": messagePayload.message.body, "messageTitle": messagePayload.message.title, "publishedAt": payload.publishedAt.description, "id": payload.id.string]) - let dappPubKey = try DIDKey(did: claims.iss) - let messageData = try JSONEncoder().encode(messagePayload.message) + let dappPubKey = try DIDKey(did: claims.iss) let record = NotifyMessageRecord(id: payload.id.string, topic: payload.topic, message: messagePayload.message, publishedAt: payload.publishedAt) notifyStorage.setMessage(record) notifyMessagePublisherSubject.send(record) let receiptPayload = NotifyMessageReceiptPayload( - keyserver: keyserver, dappPubKey: dappPubKey, - messageHash: crypto.keccak256(messageData).toHexString(), + account: messagePayload.account, + keyserver: keyserver, + dappPubKey: dappPubKey, app: messagePayload.app ) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 1f05e7126..a00f7fe6d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -60,7 +60,7 @@ class NotifySubscriptionsChangedRequestSubscriber { private func respond(topic: String, account: Account, rpcId: RPCID, notifyServerAuthenticationKey: DIDKey) async throws { - let receiptPayload = NotifySubscriptionsChangedResponsePayload(keyserver: keyserver, notifyServerAuthenticationKey: notifyServerAuthenticationKey) + let receiptPayload = NotifySubscriptionsChangedResponsePayload(account: account, keyserver: keyserver, notifyServerAuthenticationKey: notifyServerAuthenticationKey) let wrapper = try identityClient.signAndCreateWrapper( payload: receiptPayload, diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift index 8ed7e775e..f972f345b 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift @@ -14,7 +14,7 @@ struct NotifySubscriptionResponsePayload: JWTClaimsCodable { let iss: String /// `did:key` of an identity key. Allows for the resolution of the attached blockchain account. let aud: String - /// Blockchain account that notify subscription has been proposed for -`did:pkh` + /// `did:key` of the public key used for key agreement on the Notify topic let sub: String /// Dapp's domain url let app: String @@ -36,13 +36,13 @@ struct NotifySubscriptionResponsePayload: JWTClaimsCodable { } } - let account: Account let selfPubKey: DIDKey + let publicKey: DIDKey let app: String init(claims: Claims) throws { - self.account = try Account(DIDPKHString: claims.sub) self.selfPubKey = try DIDKey(did: claims.aud) + self.publicKey = try DIDKey(did: claims.sub) self.app = claims.app } @@ -53,7 +53,7 @@ struct NotifySubscriptionResponsePayload: JWTClaimsCodable { act: Claims.action, iss: iss, aud: selfPubKey.did(variant: .ED25519), - sub: account.did, + sub: publicKey.did(variant: .X25519), app: app ) } From b534ace6d13cdc0b2ed97e4f911f506ff55cdd87 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Tue, 12 Sep 2023 17:47:58 +0800 Subject: [PATCH 59/91] Subscribe response handler updated --- .../NotifySubscribeResponseSubscriber.swift | 57 ++----------------- .../NotifySubscriptionResponsePayload.swift | 8 +-- 2 files changed, 9 insertions(+), 56 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift index ab8620684..5dc224b6c 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift @@ -40,60 +40,13 @@ class NotifySubscribeResponseSubscriber { responseOfType: NotifySubscriptionResponsePayload.Wrapper.self, errorHandler: logger ) { [unowned self] payload in - logger.debug("Received Notify Subscribe response") + logger.debug("Received Notify Subscribe response") - let (responsePayload, _) = try NotifySubscriptionResponsePayload.decodeAndVerify(from: payload.response) + let _ = try NotifySubscriptionResponsePayload.decodeAndVerify(from: payload.response) - guard let responseKeys = kms.getAgreementSecret(for: payload.topic) else { - logger.debug("No symmetric key for topic \(payload.topic)") - throw Errors.couldNotCreateSubscription - } + logger.debug("NotifySubscribeResponseSubscriber: unsubscribing from response topic: \(payload.topic)") - // get keypair Y - let pubKeyY = responseKeys.publicKey - let peerPubKeyZ = responsePayload.publicKey.hexString - - var account: Account! - var metadata: AppMetadata! - var notifySubscriptionTopic: String! - var subscribedTypes: Set! - var agreementKeysP: AgreementKeys! - let (subscriptionPayload, claims) = try NotifySubscriptionPayload.decodeAndVerify(from: payload.request) - let subscribedScope = subscriptionPayload.scope - .components(separatedBy: " ") - do { - // generate symm key P - agreementKeysP = try kms.performKeyAgreement(selfPublicKey: pubKeyY, peerPublicKey: peerPubKeyZ) - notifySubscriptionTopic = agreementKeysP.derivedTopic() - try kms.setAgreementSecret(agreementKeysP, topic: notifySubscriptionTopic) - try groupKeychainStorage.add(agreementKeysP, forKey: notifySubscriptionTopic) - account = try Account(DIDPKHString: claims.sub) - metadata = try dappsMetadataStore.get(key: payload.topic) - let availableTypes = try await notifyConfigProvider.getSubscriptionScope(appDomain: metadata!.url) - subscribedTypes = availableTypes.filter{subscribedScope.contains($0.name)} - logger.debug("NotifySubscribeResponseSubscriber: subscribing notify subscription topic: \(notifySubscriptionTopic!)") - try await networkingInteractor.subscribe(topic: notifySubscriptionTopic) - } catch { - logger.debug("NotifySubscribeResponseSubscriber: error: \(error)") - throw Errors.couldNotCreateSubscription - } - - guard let metadata = metadata else { - logger.debug("NotifySubscribeResponseSubscriber: no metadata for topic: \(notifySubscriptionTopic!)") - throw 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 notifySubscription = NotifySubscription(topic: notifySubscriptionTopic, account: account, relay: RelayProtocolOptions(protocol: "irn", data: nil), metadata: metadata, scope: scope, expiry: expiry, symKey: agreementKeysP.sharedKey.hexRepresentation) - - notifyStorage.setSubscription(notifySubscription) - - logger.debug("NotifySubscribeResponseSubscriber: unsubscribing response topic: \(payload.topic)") - networkingInteractor.unsubscribe(topic: payload.topic) - } + networkingInteractor.unsubscribe(topic: payload.topic) + } } - - // TODO: handle error response - } diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift index f972f345b..8ed7e775e 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifySubscriptionResponsePayload.swift @@ -14,7 +14,7 @@ struct NotifySubscriptionResponsePayload: JWTClaimsCodable { let iss: String /// `did:key` of an identity key. Allows for the resolution of the attached blockchain account. let aud: String - /// `did:key` of the public key used for key agreement on the Notify topic + /// Blockchain account that notify subscription has been proposed for -`did:pkh` let sub: String /// Dapp's domain url let app: String @@ -36,13 +36,13 @@ struct NotifySubscriptionResponsePayload: JWTClaimsCodable { } } + let account: Account let selfPubKey: DIDKey - let publicKey: DIDKey let app: String init(claims: Claims) throws { + self.account = try Account(DIDPKHString: claims.sub) self.selfPubKey = try DIDKey(did: claims.aud) - self.publicKey = try DIDKey(did: claims.sub) self.app = claims.app } @@ -53,7 +53,7 @@ struct NotifySubscriptionResponsePayload: JWTClaimsCodable { act: Claims.action, iss: iss, aud: selfPubKey.did(variant: .ED25519), - sub: publicKey.did(variant: .X25519), + sub: account.did, app: app ) } From c06fe10256713e1c6a43e69e658343e486ae9279 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 11:54:16 +0200 Subject: [PATCH 60/91] savepoint --- .../NotifySubscriptionsChangedRequestSubscriber.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 1f05e7126..72c01a926 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -45,6 +45,8 @@ class NotifySubscriptionsChangedRequestSubscriber { let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(jwtPayload.subscriptions) notifyStorage.replaceAllSubscriptions(subscriptions, account: account) +// add keys to group keychain +// resubscribe for all the topics batch var logProperties = ["rpcId": payload.id.string] for (index, subscription) in subscriptions.enumerated() { From 73e56d5951a879da72998d03850872508d5f34cd Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 12:04:44 +0200 Subject: [PATCH 61/91] add group keychain to watch subscription --- .../Client/Wallet/NotifyClientFactory.swift | 2 +- ...fySubscriptionsChangedRequestSubscriber.swift | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index 3e74f00bf..3f5f830e4 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -61,7 +61,7 @@ public struct NotifyClientFactory { let notifyWatchSubscriptionsRequester = NotifyWatchSubscriptionsRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, webDidResolver: webDidResolver) let notifySubscriptionsBuilder = NotifySubscriptionsBuilder(notifyConfigProvider: notifyConfigProvider) let notifyWatchSubscriptionsResponseSubscriber = NotifyWatchSubscriptionsResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) - let notifySubscriptionsChangedRequestSubscriber = NotifySubscriptionsChangedRequestSubscriber(keyserver: keyserverURL, networkingInteractor: networkInteractor, kms: kms, identityClient: identityClient, logger: logger, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) + let notifySubscriptionsChangedRequestSubscriber = NotifySubscriptionsChangedRequestSubscriber(keyserver: keyserverURL, networkingInteractor: networkInteractor, kms: kms, identityClient: identityClient, logger: logger, groupKeychainStorage: groupKeychainStorage, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) let identityService = NotifyIdentityService(keyserverURL: keyserverURL, identityClient: identityClient, logger: logger) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 0d10b9710..265747ecf 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -7,6 +7,7 @@ class NotifySubscriptionsChangedRequestSubscriber { private let identityClient: IdentityClient private let kms: KeyManagementServiceProtocol private let logger: ConsoleLogging + private let groupKeychainStorage: KeychainStorageProtocol private let notifyStorage: NotifyStorage private let notifySubscriptionsBuilder: NotifySubscriptionsBuilder @@ -16,6 +17,7 @@ class NotifySubscriptionsChangedRequestSubscriber { kms: KeyManagementServiceProtocol, identityClient: IdentityClient, logger: ConsoleLogging, + groupKeychainStorage: KeychainStorageProtocol, notifyStorage: NotifyStorage, notifySubscriptionsBuilder: NotifySubscriptionsBuilder ) { @@ -24,6 +26,7 @@ class NotifySubscriptionsChangedRequestSubscriber { self.kms = kms self.logger = logger self.identityClient = identityClient + self.groupKeychainStorage = groupKeychainStorage self.notifyStorage = notifyStorage self.notifySubscriptionsBuilder = notifySubscriptionsBuilder subscribeForNofifyChangedRequests() @@ -45,8 +48,19 @@ class NotifySubscriptionsChangedRequestSubscriber { let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(jwtPayload.subscriptions) notifyStorage.replaceAllSubscriptions(subscriptions, account: account) + + for subscription in subscriptions { + try groupKeychainStorage.add(subscription.symKey, forKey: subscription.topic) + } + + let topics = subscriptions.reduce([]) { $0 + [$1.topic] } + + try await networkingInteractor.batchSubscribe(topics: topics) + + + + // add keys to group keychain -// resubscribe for all the topics batch var logProperties = ["rpcId": payload.id.string] for (index, subscription) in subscriptions.enumerated() { From 9da3bb83318aaefac005516abab3898b1c1b7943 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 12:14:00 +0200 Subject: [PATCH 62/91] Update Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift Co-authored-by: Artur Guseinov --- .../NotifySubscriptionsChangedRequestSubscriber.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 265747ecf..fb45a9a7d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -53,7 +53,7 @@ class NotifySubscriptionsChangedRequestSubscriber { try groupKeychainStorage.add(subscription.symKey, forKey: subscription.topic) } - let topics = subscriptions.reduce([]) { $0 + [$1.topic] } + let topics = subscriptions.map { $0.topic } try await networkingInteractor.batchSubscribe(topics: topics) From e1ff5d96b9cb4676a852002713bb3d696ab888d6 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 12:16:41 +0200 Subject: [PATCH 63/91] savepoint --- .../NotifySubscriptionsChangedRequestSubscriber.swift | 5 ----- Sources/Web3Inbox/Web3InboxClientFactory.swift | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 265747ecf..b364d7ef4 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -57,11 +57,6 @@ class NotifySubscriptionsChangedRequestSubscriber { try await networkingInteractor.batchSubscribe(topics: topics) - - - -// add keys to group keychain - var logProperties = ["rpcId": payload.id.string] for (index, subscription) in subscriptions.enumerated() { let key = "subscription_\(index + 1)" diff --git a/Sources/Web3Inbox/Web3InboxClientFactory.swift b/Sources/Web3Inbox/Web3InboxClientFactory.swift index 83ce998fe..9734edd3f 100644 --- a/Sources/Web3Inbox/Web3InboxClientFactory.swift +++ b/Sources/Web3Inbox/Web3InboxClientFactory.swift @@ -40,7 +40,7 @@ final class Web3InboxClientFactory { } private static func buildUrl(account: Account, config: [ConfigParam: Bool]) -> URL { - var urlComponents = URLComponents(string: "https://web3inbox-dev-hidden.vercel.app/")! + var urlComponents = URLComponents(string: "https://web3inbox-dev-hidden-git-chore-notif-refa-effa6b-walletconnect1.vercel.app/")! var queryItems = [URLQueryItem(name: "chatProvider", value: "ios"), URLQueryItem(name: "notifyProvider", value: "ios"), URLQueryItem(name: "account", value: account.address), URLQueryItem(name: "authProvider", value: "ios")] for param in config.filter({ $0.value == false}) { From cf0d2aa19a17d5b6e6df0b3a09dca49791f9ba81 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 12:18:21 +0200 Subject: [PATCH 64/91] add same thing to watch subscriptions --- .../NotifyWatchSubscriptionsResponseSubscriber.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 44a2697c6..9c5989a27 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -40,6 +40,14 @@ class NotifyWatchSubscriptionsResponseSubscriber { let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions) notifyStorage.replaceAllSubscriptions(subscriptions, account: account) + + for subscription in subscriptions { + try groupKeychainStorage.add(subscription.symKey, forKey: subscription.topic) + } + + let topics = subscriptions.map { $0.topic } + + try await networkingInteractor.batchSubscribe(topics: topics) var logProperties = [String: String]() for (index, subscription) in subscriptions.enumerated() { From 5a738f632eeabfc6b5cf0b4ee09f48550efe3337 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 12:25:26 +0200 Subject: [PATCH 65/91] fix build --- .../Client/Wallet/NotifyClientFactory.swift | 2 +- .../NotifyWatchSubscriptionsResponseSubscriber.swift | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index 3f5f830e4..82db9661e 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -60,7 +60,7 @@ public struct NotifyClientFactory { let notifyWatchSubscriptionsRequester = NotifyWatchSubscriptionsRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, webDidResolver: webDidResolver) let notifySubscriptionsBuilder = NotifySubscriptionsBuilder(notifyConfigProvider: notifyConfigProvider) - let notifyWatchSubscriptionsResponseSubscriber = NotifyWatchSubscriptionsResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) + let notifyWatchSubscriptionsResponseSubscriber = NotifyWatchSubscriptionsResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage, groupKeychainStorage: groupKeychainStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) let notifySubscriptionsChangedRequestSubscriber = NotifySubscriptionsChangedRequestSubscriber(keyserver: keyserverURL, networkingInteractor: networkInteractor, kms: kms, identityClient: identityClient, logger: logger, groupKeychainStorage: groupKeychainStorage, notifyStorage: notifyStorage, notifySubscriptionsBuilder: notifySubscriptionsBuilder) let identityService = NotifyIdentityService(keyserverURL: keyserverURL, identityClient: identityClient, logger: logger) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 9c5989a27..bed6890bd 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -6,18 +6,21 @@ class NotifyWatchSubscriptionsResponseSubscriber { private let kms: KeyManagementServiceProtocol private let logger: ConsoleLogging private let notifyStorage: NotifyStorage + private let groupKeychainStorage: KeychainStorageProtocol private let notifySubscriptionsBuilder: NotifySubscriptionsBuilder init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, notifyStorage: NotifyStorage, + groupKeychainStorage: KeychainStorageProtocol, notifySubscriptionsBuilder: NotifySubscriptionsBuilder ) { self.networkingInteractor = networkingInteractor self.kms = kms self.logger = logger self.notifyStorage = notifyStorage + self.groupKeychainStorage = groupKeychainStorage self.notifySubscriptionsBuilder = notifySubscriptionsBuilder subscribeForWatchSubscriptionsResponse() } From 232d5fb546d5f072a49b8749ff6a4b8a61c35923 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 12:36:41 +0200 Subject: [PATCH 66/91] remove aud from message --- .../Types/JWTPayloads/NotifyMessagePayload.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift index 34bfee51e..3e3679827 100644 --- a/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift +++ b/Sources/WalletConnectNotify/Types/JWTPayloads/NotifyMessagePayload.swift @@ -12,8 +12,6 @@ struct NotifyMessagePayload: JWTClaimsCodable { /// `did:key` of an identity key. Enables to resolve associated Dapp domain used. diddoc authentication key let iss: String - /// Blockchain account `did:pkh` - let aud: String /// Blockchain account that notify subscription has been proposed for -`did:pkh` let sub: String /// Dapp domain url @@ -56,7 +54,6 @@ struct NotifyMessagePayload: JWTClaimsCodable { exp: expiry(days: 1), act: Claims.action, iss: dappAuthenticationKey.multibase(variant: .ED25519), - aud: account.did, // TODO: Should we remove or merge with msg? sub: account.did, app: app.did, msg: message From d4123c52bf7e4cab769a242607841eb166b2f61f Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Tue, 12 Sep 2023 19:04:54 +0800 Subject: [PATCH 67/91] w3i-fixed-refactor --- Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift index 9319d23ad..c67d99178 100644 --- a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift +++ b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift @@ -25,7 +25,9 @@ final class NotifyClientProxy { try await respond(request: request) case .subscribe: let params = try parse(SubscribeRequest.self, params: request.params) - try await client.subscribe(appDomain: params.appDomain, account: params.account) + // TODO: Remove after + let appDomain = params.appDomain == "notify.gm.walletconnect.com" ? "dev.gm.walletconnect.com" : params.appDomain + try await client.subscribe(appDomain: appDomain, account: params.account) try await respond(request: request) case .getActiveSubscriptions: let subscriptions = client.getActiveSubscriptions() @@ -44,6 +46,8 @@ final class NotifyClientProxy { try await respond(request: request) case .register: let params = try parse(RegisterRequest.self, params: request.params) + // TODO: Remove after + let appDomain = params.domain == "notify.gm.walletconnect.com" ? "dev.gm.walletconnect.com" : params.domain try await client.register(account: params.account, domain: params.domain, isLimited: params.isLimited, onSign: onSign) try await respond(request: request) } From 1271c5d6974bd557c9cf1df9785c840790b7359c Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 14:47:06 +0200 Subject: [PATCH 68/91] save keys on watch and change --- ...SubscriptionsChangedRequestSubscriber.swift | 16 +++++++++++----- ...yWatchSubscriptionsResponseSubscriber.swift | 18 ++++++++++++------ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index 00f456d1d..c3f2418fc 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -45,20 +45,26 @@ class NotifySubscriptionsChangedRequestSubscriber { // todo varify signature with notify server diddoc authentication key - let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(jwtPayload.subscriptions) + let oldSubscriptions = notifyStorage.getSubscriptions() + let newSubscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(jwtPayload.subscriptions) + logger.debug("number of subscriptions: \(newSubscriptions.count)") - notifyStorage.replaceAllSubscriptions(subscriptions, account: account) + guard newSubscriptions != oldSubscriptions else {return} - for subscription in subscriptions { + notifyStorage.replaceAllSubscriptions(newSubscriptions, account: account) + + for subscription in newSubscriptions { try groupKeychainStorage.add(subscription.symKey, forKey: subscription.topic) + let symKey = try SymmetricKey(hex: subscription.symKey) + try kms.setSymmetricKey(symKey, for: subscription.topic) } - let topics = subscriptions.map { $0.topic } + let topics = newSubscriptions.map { $0.topic } try await networkingInteractor.batchSubscribe(topics: topics) var logProperties = ["rpcId": payload.id.string] - for (index, subscription) in subscriptions.enumerated() { + for (index, subscription) in newSubscriptions.enumerated() { let key = "subscription_\(index + 1)" logProperties[key] = subscription.topic } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index bed6890bd..1885a30e7 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -40,25 +40,31 @@ class NotifyWatchSubscriptionsResponseSubscriber { let account = watchSubscriptionPayloadRequest.subscriptionAccount // todo varify signature with notify server diddoc authentication key - let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions) + let oldSubscriptions = notifyStorage.getSubscriptions() + let newSubscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions) - notifyStorage.replaceAllSubscriptions(subscriptions, account: account) + logger.debug("number of subscriptions: \(newSubscriptions.count)") + + guard newSubscriptions != oldSubscriptions else {return} + notifyStorage.replaceAllSubscriptions(newSubscriptions, account: account) - for subscription in subscriptions { + for subscription in newSubscriptions { try groupKeychainStorage.add(subscription.symKey, forKey: subscription.topic) + let symKey = try SymmetricKey(hex: subscription.symKey) + try kms.setSymmetricKey(symKey, for: subscription.topic) } - let topics = subscriptions.map { $0.topic } + let topics = newSubscriptions.map { $0.topic } try await networkingInteractor.batchSubscribe(topics: topics) var logProperties = [String: String]() - for (index, subscription) in subscriptions.enumerated() { + for (index, subscription) in newSubscriptions.enumerated() { let key = "subscription_\(index + 1)" logProperties[key] = subscription.topic } - logger.debug("Updated Subscriptions with Watch Subscriptions Update, number of subscriptions: \(subscriptions.count)", properties: logProperties) + logger.debug("Updated Subscriptions with Watch Subscriptions Update, number of subscriptions: \(newSubscriptions.count)", properties: logProperties) } } From 45d8a3de8ff8f87d745e5d9c96c08ad166fe9685 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 16:15:38 +0200 Subject: [PATCH 69/91] remove DeleteNotifySubscriptionSubscriber --- .../Client/Wallet/NotifyClient.swift | 3 -- .../Client/Wallet/NotifyClientFactory.swift | 3 -- .../DeleteNotifySubscriptionSubscriber.swift | 32 ------------------- 3 files changed, 38 deletions(-) delete mode 100644 Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionSubscriber.swift diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index b1742a9dc..77b1aa604 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -42,7 +42,6 @@ public class NotifyClient { private let notifyMessageSubscriber: NotifyMessageSubscriber private let resubscribeService: NotifyResubscribeService private let notifySubscribeResponseSubscriber: NotifySubscribeResponseSubscriber - private let deleteNotifySubscriptionSubscriber: DeleteNotifySubscriptionSubscriber private let notifyUpdateRequester: NotifyUpdateRequester private let notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber private let subscriptionsAutoUpdater: SubscriptionsAutoUpdater @@ -60,7 +59,6 @@ public class NotifyClient { resubscribeService: NotifyResubscribeService, notifySubscribeRequester: NotifySubscribeRequester, notifySubscribeResponseSubscriber: NotifySubscribeResponseSubscriber, - deleteNotifySubscriptionSubscriber: DeleteNotifySubscriptionSubscriber, notifyUpdateRequester: NotifyUpdateRequester, notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber, subscriptionsAutoUpdater: SubscriptionsAutoUpdater, @@ -77,7 +75,6 @@ public class NotifyClient { self.resubscribeService = resubscribeService self.notifySubscribeRequester = notifySubscribeRequester self.notifySubscribeResponseSubscriber = notifySubscribeResponseSubscriber - self.deleteNotifySubscriptionSubscriber = deleteNotifySubscriptionSubscriber self.notifyUpdateRequester = notifyUpdateRequester self.notifyUpdateResponseSubscriber = notifyUpdateResponseSubscriber self.subscriptionsAutoUpdater = subscriptionsAutoUpdater diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index 82db9661e..c38db543e 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -54,8 +54,6 @@ public struct NotifyClientFactory { let notifyUpdateResponseSubscriber = NotifyUpdateResponseSubscriber(networkingInteractor: networkInteractor, logger: logger, notifyConfigProvider: notifyConfigProvider, notifyStorage: notifyStorage) - let deleteNotifySubscriptionSubscriber = DeleteNotifySubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage) - let subscriptionsAutoUpdater = SubscriptionsAutoUpdater(notifyUpdateRequester: notifyUpdateRequester, logger: logger, notifyStorage: notifyStorage) let notifyWatchSubscriptionsRequester = NotifyWatchSubscriptionsRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, webDidResolver: webDidResolver) @@ -76,7 +74,6 @@ public struct NotifyClientFactory { resubscribeService: resubscribeService, notifySubscribeRequester: notifySubscribeRequester, notifySubscribeResponseSubscriber: notifySubscribeResponseSubscriber, - deleteNotifySubscriptionSubscriber: deleteNotifySubscriptionSubscriber, notifyUpdateRequester: notifyUpdateRequester, notifyUpdateResponseSubscriber: notifyUpdateResponseSubscriber, subscriptionsAutoUpdater: subscriptionsAutoUpdater, diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionSubscriber.swift deleted file mode 100644 index 2ae697d7d..000000000 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyDelete/DeleteNotifySubscriptionSubscriber.swift +++ /dev/null @@ -1,32 +0,0 @@ -import Foundation -import Combine - -class DeleteNotifySubscriptionSubscriber { - private let networkingInteractor: NetworkInteracting - private let kms: KeyManagementServiceProtocol - private let logger: ConsoleLogging - private let notifyStorage: NotifyStorage - - init(networkingInteractor: NetworkInteracting, - kms: KeyManagementServiceProtocol, - logger: ConsoleLogging, - notifyStorage: NotifyStorage - ) { - self.networkingInteractor = networkingInteractor - self.kms = kms - self.logger = logger - self.notifyStorage = notifyStorage - subscribeForDeleteSubscription() - } - - private func subscribeForDeleteSubscription() { - networkingInteractor.subscribeOnRequest( - protocolMethod: NotifyDeleteProtocolMethod(), - requestOfType: NotifyDeleteResponsePayload.Wrapper.self, - errorHandler: logger - ) { [unowned self] payload in - let (_, _) = try NotifyDeleteResponsePayload.decodeAndVerify(from: payload.request) - logger.debug("Peer deleted subscription") - } - } -} From bfa9a770e7afe4c08419b4da8a18983afa0e4491 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 13 Sep 2023 11:14:49 +0200 Subject: [PATCH 70/91] watch subscriptions on socket connection --- .../Client/Wallet/NotifyClient.swift | 2 +- .../NotifyWatchSubscriptionsRequester.swift | 22 ++++++++++++++++++- ...WatchSubscriptionsResponseSubscriber.swift | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 77b1aa604..9bd35e7f8 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -85,7 +85,7 @@ public class NotifyClient { public func register(account: Account, domain: String, isLimited: Bool = false, onSign: @escaping SigningCallback) async throws { try await identityService.register(account: account, domain: domain, isLimited: isLimited, onSign: onSign) - try await notifyWatchSubscriptionsRequester.watchSubscriptions(account: account) + notifyWatchSubscriptionsRequester.setAccount(account) } public func setLogging(level: LoggingLevel) { diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift index afb178f92..c59e037ca 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift @@ -1,4 +1,5 @@ import Foundation +import Combine class NotifyWatchSubscriptionsRequester { @@ -9,6 +10,8 @@ class NotifyWatchSubscriptionsRequester { private let logger: ConsoleLogging private let webDidResolver: NotifyWebDidResolver private let notifyServerUrl = "dev.notify.walletconnect.com" + private var account: Account? + private var publishers = Set() init(keyserverURL: URL, networkingInteractor: NetworkInteracting, @@ -23,9 +26,26 @@ class NotifyWatchSubscriptionsRequester { self.logger = logger self.kms = kms self.webDidResolver = webDidResolver + setUpWatchSubscriptionsOnSocketConnection() } - func watchSubscriptions(account: Account) async throws { + func setUpWatchSubscriptionsOnSocketConnection() { + networkingInteractor.socketConnectionStatusPublisher + .sink { [unowned self] status in + guard status == .connected else { return } + Task { try await watchSubscriptions() } + } + .store(in: &publishers) + } + + func setAccount(_ account: Account) { + self.account = account + Task { try await watchSubscriptions() } + } + + private func watchSubscriptions() async throws { + + guard let account = account else { return } logger.debug("Watching subscriptions") diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 1885a30e7..71954b967 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -46,6 +46,7 @@ class NotifyWatchSubscriptionsResponseSubscriber { logger.debug("number of subscriptions: \(newSubscriptions.count)") guard newSubscriptions != oldSubscriptions else {return} + // todo: unsubscribe for oldSubscriptions topics that are not included in new subscriptions notifyStorage.replaceAllSubscriptions(newSubscriptions, account: account) for subscription in newSubscriptions { From 41433c740d7b4004d6315ddc1b21f86c708136e3 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 13 Sep 2023 14:32:32 +0200 Subject: [PATCH 71/91] fix notification decryption --- Example/PNDecryptionService/NotificationService.swift | 2 +- .../NotifySubscriptionsChangedRequestSubscriber.swift | 2 +- .../NotifyWatchSubscriptionsResponseSubscriber.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Example/PNDecryptionService/NotificationService.swift b/Example/PNDecryptionService/NotificationService.swift index 21da33666..50023dd13 100644 --- a/Example/PNDecryptionService/NotificationService.swift +++ b/Example/PNDecryptionService/NotificationService.swift @@ -25,7 +25,7 @@ class NotificationService: UNNotificationServiceExtension { catch { NSLog("Push decryption, error=%@", error.localizedDescription) bestAttemptContent.title = "" - bestAttemptContent.body = "content not set" + bestAttemptContent.body = error.localizedDescription } contentHandler(bestAttemptContent) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index c3f2418fc..aab48f0ba 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -54,8 +54,8 @@ class NotifySubscriptionsChangedRequestSubscriber { notifyStorage.replaceAllSubscriptions(newSubscriptions, account: account) for subscription in newSubscriptions { - try groupKeychainStorage.add(subscription.symKey, forKey: subscription.topic) let symKey = try SymmetricKey(hex: subscription.symKey) + try groupKeychainStorage.add(symKey, forKey: subscription.topic) try kms.setSymmetricKey(symKey, for: subscription.topic) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 71954b967..84695e1a5 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -50,8 +50,8 @@ class NotifyWatchSubscriptionsResponseSubscriber { notifyStorage.replaceAllSubscriptions(newSubscriptions, account: account) for subscription in newSubscriptions { - try groupKeychainStorage.add(subscription.symKey, forKey: subscription.topic) let symKey = try SymmetricKey(hex: subscription.symKey) + try groupKeychainStorage.add(symKey, forKey: subscription.topic) try kms.setSymmetricKey(symKey, for: subscription.topic) } From 84702f8c4d03e32aac68a53ebe168c8b8f7fc5c2 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 13 Sep 2023 21:12:24 +0800 Subject: [PATCH 72/91] Cancellable task --- .../IntegrationTests/Push/NotifyTests.swift | 3 --- .../NetworkingInteractor.swift | 9 +++---- ...ubscriptionsChangedRequestSubscriber.swift | 2 ++ ...WatchSubscriptionsResponseSubscriber.swift | 4 ++-- .../WalletConnectUtils/Extensions/Task.swift | 24 +++++++++++++++++++ 5 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 Sources/WalletConnectUtils/Extensions/Task.swift diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index da71d5b71..a66f08786 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -14,8 +14,6 @@ import WalletConnectSigner final class NotifyTests: XCTestCase { - var walletPairingClient: PairingClient! - var walletNotifyClientA: NotifyClient! let gmDappDomain = "dev.gm.walletconnect.com" @@ -70,7 +68,6 @@ final class NotifyTests: XCTestCase { func makeWalletClient(prefix: String = "🦋 Wallet: ") -> NotifyClient { let (pairingClient, networkingInteractor, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) let notifyLogger = ConsoleLogger(prefix: prefix + " [Notify]", loggingLevel: .debug) - walletPairingClient = pairingClient let pushClient = PushClientFactory.create(projectId: "", pushHost: "echo.walletconnect.com", keychainStorage: keychain, diff --git a/Sources/WalletConnectNetworking/NetworkingInteractor.swift b/Sources/WalletConnectNetworking/NetworkingInteractor.swift index cb48e6d47..f311cdc5b 100644 --- a/Sources/WalletConnectNetworking/NetworkingInteractor.swift +++ b/Sources/WalletConnectNetworking/NetworkingInteractor.swift @@ -2,6 +2,7 @@ import Foundation import Combine public class NetworkingInteractor: NetworkInteracting { + private var tasks = Task.DisposeBag() private var publishers = Set() private let relayClient: RelayClient private let serializer: Serializing @@ -91,14 +92,14 @@ public class NetworkingInteractor: NetworkInteracting { subscription: @escaping (RequestSubscriptionPayload) async throws -> Void ) { requestSubscription(on: protocolMethod) - .sink { (payload: RequestSubscriptionPayload) in + .sink { [unowned self] (payload: RequestSubscriptionPayload) in Task(priority: .high) { do { try await subscription(payload) } catch { errorHandler?.handle(error: error) } - } + }.store(in: &tasks) }.store(in: &publishers) } @@ -110,14 +111,14 @@ public class NetworkingInteractor: NetworkInteracting { subscription: @escaping (ResponseSubscriptionPayload) async throws -> Void ) { responseSubscription(on: protocolMethod) - .sink { (payload: ResponseSubscriptionPayload) in + .sink { [unowned self] (payload: ResponseSubscriptionPayload) in Task(priority: .high) { do { try await subscription(payload) } catch { errorHandler?.handle(error: error) } - } + }.store(in: &tasks) }.store(in: &publishers) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift index c3f2418fc..81174ed4c 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifySubscriptionsChanged/NotifySubscriptionsChangedRequestSubscriber.swift @@ -63,6 +63,8 @@ class NotifySubscriptionsChangedRequestSubscriber { try await networkingInteractor.batchSubscribe(topics: topics) + try Task.checkCancellation() + var logProperties = ["rpcId": payload.id.string] for (index, subscription) in newSubscriptions.enumerated() { let key = "subscription_\(index + 1)" diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift index 1885a30e7..850fcac03 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsResponseSubscriber.swift @@ -54,9 +54,9 @@ class NotifyWatchSubscriptionsResponseSubscriber { try kms.setSymmetricKey(symKey, for: subscription.topic) } - let topics = newSubscriptions.map { $0.topic } + try await networkingInteractor.batchSubscribe(topics: newSubscriptions.map { $0.topic }) - try await networkingInteractor.batchSubscribe(topics: topics) + try Task.checkCancellation() var logProperties = [String: String]() for (index, subscription) in newSubscriptions.enumerated() { diff --git a/Sources/WalletConnectUtils/Extensions/Task.swift b/Sources/WalletConnectUtils/Extensions/Task.swift new file mode 100644 index 000000000..180157949 --- /dev/null +++ b/Sources/WalletConnectUtils/Extensions/Task.swift @@ -0,0 +1,24 @@ +import Foundation + +public typealias CancellableTask = Task + +extension Task where Success == Void, Failure == Never { + + public final class DisposeBag { + private var set: Set = [] + + public init() { } + + func insert(task: Task) { + set.insert(task) + } + + deinit { + set.forEach { $0.cancel() } + } + } + + public func store(in set: inout DisposeBag) { + set.insert(task: self) + } +} From 3b0e26e525f61b905e08f5fbf31a01bffaf0e5bb Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Sep 2023 15:56:52 +0200 Subject: [PATCH 73/91] disable w3i --- .../PresentationLayer/Wallet/Main/MainPresenter.swift | 1 - .../PresentationLayer/Wallet/Main/Model/TabPage.swift | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift index 4be0dc58a..82a927cc2 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift @@ -17,7 +17,6 @@ final class MainPresenter { return [ router.walletViewController(importAccount: importAccount), router.notificationsViewController(), - router.web3InboxViewController(), router.settingsViewController() ] } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift index 3f2051baf..4dd01cfe5 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift @@ -3,7 +3,6 @@ import UIKit enum TabPage: CaseIterable { case wallet case notifications - case web3Inbox case settings var title: String { @@ -12,8 +11,6 @@ enum TabPage: CaseIterable { return "Apps" case .notifications: return "Notifications" - case .web3Inbox: - return "Web3Inbox" case .settings: return "Settings" } @@ -25,8 +22,6 @@ enum TabPage: CaseIterable { return UIImage(systemName: "house.fill")! case .notifications: return UIImage(systemName: "bell.fill")! - case .web3Inbox: - return UIImage(systemName: "bell.fill")! case .settings: return UIImage(systemName: "gearshape.fill")! } @@ -37,6 +32,6 @@ enum TabPage: CaseIterable { } static var enabledTabs: [TabPage] { - return [.wallet, .notifications, .web3Inbox, .settings] + return [.wallet, .notifications, .settings] } } From 550160f4d4a1afb88a799cc1675dde19c03d558f Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 13 Sep 2023 17:08:05 +0200 Subject: [PATCH 74/91] remove w3i from wallet app --- Example/ExampleApp.xcodeproj/project.pbxproj | 20 -------- .../ApplicationLayer/AppDelegate.swift | 4 +- .../ConfigurationService.swift | 13 ++--- .../ApplicationLayer/ProfilingService.swift | 2 - .../Wallet/Main/MainRouter.swift | 5 -- .../Wallet/Web3Inbox/Web3InboxModule.swift | 13 ----- .../Wallet/Web3Inbox/Web3InboxRouter.swift | 12 ----- .../Web3Inbox/Web3InboxViewController.swift | 48 ------------------- 8 files changed, 7 insertions(+), 110 deletions(-) delete mode 100644 Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxModule.swift delete mode 100644 Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxRouter.swift delete mode 100644 Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxViewController.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index f40872c6c..bd2e994ff 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -18,9 +18,6 @@ 84474A0129B9EB74005F520B /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = 84474A0029B9EB74005F520B /* Starscream */; }; 84474A0229B9ECA2005F520B /* DefaultSocketFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AEF2877F73000094373 /* DefaultSocketFactory.swift */; }; 8448F1D427E4726F0000B866 /* WalletConnect in Frameworks */ = {isa = PBXBuildFile; productRef = 8448F1D327E4726F0000B866 /* WalletConnect */; }; - 84536D6E29EEAE1F008EA8DB /* Web3InboxModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84536D6D29EEAE1F008EA8DB /* Web3InboxModule.swift */; }; - 84536D7029EEAE28008EA8DB /* Web3InboxRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84536D6F29EEAE28008EA8DB /* Web3InboxRouter.swift */; }; - 84536D7229EEAE32008EA8DB /* Web3InboxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84536D7129EEAE32008EA8DB /* Web3InboxViewController.swift */; }; 84536D7429EEBCF0008EA8DB /* Web3Inbox in Frameworks */ = {isa = PBXBuildFile; productRef = 84536D7329EEBCF0008EA8DB /* Web3Inbox */; }; 845B8D8C2934B36C0084A966 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845B8D8B2934B36C0084A966 /* Account.swift */; }; 847BD1D62989492500076C90 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D12989492500076C90 /* MainViewController.swift */; }; @@ -371,9 +368,6 @@ 8439CB88293F658E00F2F2E2 /* PushMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushMessage.swift; sourceTree = ""; }; 844749F329B9E5B9005F520B /* RelayIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RelayIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 844749F529B9E5B9005F520B /* RelayClientEndToEndTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayClientEndToEndTests.swift; sourceTree = ""; }; - 84536D6D29EEAE1F008EA8DB /* Web3InboxModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Web3InboxModule.swift; sourceTree = ""; }; - 84536D6F29EEAE28008EA8DB /* Web3InboxRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Web3InboxRouter.swift; sourceTree = ""; }; - 84536D7129EEAE32008EA8DB /* Web3InboxViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Web3InboxViewController.swift; sourceTree = ""; }; 845AA7D929BA1EBA00F33739 /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = IntegrationTests.xctestplan; path = ExampleApp.xcodeproj/IntegrationTests.xctestplan; sourceTree = ""; }; 845AA7DC29BB424800F33739 /* SmokeTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = SmokeTests.xctestplan; sourceTree = ""; }; 845B8D8B2934B36C0084A966 /* Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = ""; }; @@ -795,16 +789,6 @@ path = RelayIntegrationTests; sourceTree = ""; }; - 84536D6C29EEAE0D008EA8DB /* Web3Inbox */ = { - isa = PBXGroup; - children = ( - 84536D6D29EEAE1F008EA8DB /* Web3InboxModule.swift */, - 84536D6F29EEAE28008EA8DB /* Web3InboxRouter.swift */, - 84536D7129EEAE32008EA8DB /* Web3InboxViewController.swift */, - ); - path = Web3Inbox; - sourceTree = ""; - }; 847BD1DB2989493F00076C90 /* Main */ = { isa = PBXGroup; children = ( @@ -1555,7 +1539,6 @@ isa = PBXGroup; children = ( A51811992A52E82100A52B15 /* Settings */, - 84536D6C29EEAE0D008EA8DB /* Web3Inbox */, 847BD1DB2989493F00076C90 /* Main */, C55D3477295DD4AA0004314A /* Welcome */, C55D3474295DCB850004314A /* AuthRequest */, @@ -2309,8 +2292,6 @@ C55D34B12965FB750004314A /* SessionProposalInteractor.swift in Sources */, C56EE247293F566D004840D1 /* ScanModule.swift in Sources */, C56EE28D293F5757004840D1 /* AppearanceConfigurator.swift in Sources */, - 84536D6E29EEAE1F008EA8DB /* Web3InboxModule.swift in Sources */, - 84536D7029EEAE28008EA8DB /* Web3InboxRouter.swift in Sources */, 847BD1D82989492500076C90 /* MainModule.swift in Sources */, 847BD1E7298A806800076C90 /* NotificationsInteractor.swift in Sources */, C56EE241293F566D004840D1 /* WalletModule.swift in Sources */, @@ -2342,7 +2323,6 @@ C55D347F295DD7140004314A /* AuthRequestModule.swift in Sources */, C56EE242293F566D004840D1 /* ScanPresenter.swift in Sources */, C56EE28B293F5757004840D1 /* SceneDelegate.swift in Sources */, - 84536D7229EEAE32008EA8DB /* Web3InboxViewController.swift in Sources */, C56EE276293F56D7004840D1 /* UIViewController.swift in Sources */, C56EE275293F56D7004840D1 /* InputConfig.swift in Sources */, C55D3493295DFA750004314A /* WelcomeModule.swift in Sources */, diff --git a/Example/WalletApp/ApplicationLayer/AppDelegate.swift b/Example/WalletApp/ApplicationLayer/AppDelegate.swift index 0b8afd190..1bef78e52 100644 --- a/Example/WalletApp/ApplicationLayer/AppDelegate.swift +++ b/Example/WalletApp/ApplicationLayer/AppDelegate.swift @@ -1,6 +1,6 @@ import UIKit -import Web3Inbox import Combine +import WalletConnectNotify @main final class AppDelegate: UIResponder, UIApplicationDelegate { @@ -29,7 +29,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { UserDefaults.standard.set(deviceTokenString.joined(), forKey: "deviceToken") Task(priority: .high) { - try await Web3Inbox.instance.register(deviceToken: deviceToken) + try await Notify.instance.register(deviceToken: deviceToken) } } diff --git a/Example/WalletApp/ApplicationLayer/ConfigurationService.swift b/Example/WalletApp/ApplicationLayer/ConfigurationService.swift index 225848c93..fd77aaee7 100644 --- a/Example/WalletApp/ApplicationLayer/ConfigurationService.swift +++ b/Example/WalletApp/ApplicationLayer/ConfigurationService.swift @@ -1,7 +1,7 @@ import Foundation import WalletConnectNetworking +import WalletConnectNotify import Web3Wallet -import Web3Inbox final class ConfigurationService { @@ -18,16 +18,13 @@ final class ConfigurationService { Web3Wallet.configure(metadata: metadata, crypto: DefaultCryptoProvider(), environment: BuildConfiguration.shared.apnsEnvironment) - Web3Inbox.configure( - account: importAccount.account, - bip44: DefaultBIP44Provider(), - config: [.chatEnabled: false, .settingsEnabled: false], + Notify.configure( groupIdentifier: "group.com.walletconnect.sdk", environment: BuildConfiguration.shared.apnsEnvironment, - crypto: DefaultCryptoProvider(), - onSign: importAccount.onSign + crypto: DefaultCryptoProvider() ) - Web3Inbox.instance.setLogging(level: .debug) + + Notify.instance.setLogging(level: .debug) if let clientId = try? Networking.interactor.getClientId() { LoggingService.instance.setUpUser(account: importAccount.account.absoluteString, clientId: clientId) diff --git a/Example/WalletApp/ApplicationLayer/ProfilingService.swift b/Example/WalletApp/ApplicationLayer/ProfilingService.swift index 14a778061..1e87c8a0d 100644 --- a/Example/WalletApp/ApplicationLayer/ProfilingService.swift +++ b/Example/WalletApp/ApplicationLayer/ProfilingService.swift @@ -2,7 +2,6 @@ import Foundation import Mixpanel import WalletConnectNetworking import Combine -import Web3Inbox final class ProfilingService { public static var instance = ProfilingService() @@ -32,7 +31,6 @@ final class ProfilingService { mixpanel.people.set(properties: ["$name": account, "account": account]) handleLogs(from: Networking.instance.logsPublisher) - handleLogs(from: Web3Inbox.instance.logsPublisher) } private func handleLogs(from publisher: AnyPublisher) { diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift index 7d176926f..b92eabc25 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift @@ -22,11 +22,6 @@ final class MainRouter { .wrapToNavigationController() } - func web3InboxViewController() -> UIViewController { - return Web3InboxModule.create(app: app) - .wrapToNavigationController() - } - func settingsViewController() -> UIViewController { return SettingsModule.create(app: app) .wrapToNavigationController() diff --git a/Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxModule.swift b/Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxModule.swift deleted file mode 100644 index ad0633441..000000000 --- a/Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxModule.swift +++ /dev/null @@ -1,13 +0,0 @@ -import SwiftUI - -final class Web3InboxModule { - - @discardableResult - static func create(app: Application) -> UIViewController { - let router = Web3InboxRouter(app: app) - let viewController = Web3InboxViewController() - router.viewController = viewController - return viewController - } - -} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxRouter.swift b/Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxRouter.swift deleted file mode 100644 index 3631c35be..000000000 --- a/Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxRouter.swift +++ /dev/null @@ -1,12 +0,0 @@ -import UIKit - -final class Web3InboxRouter { - - weak var viewController: UIViewController! - - private let app: Application - - init(app: Application) { - self.app = app - } -} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxViewController.swift b/Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxViewController.swift deleted file mode 100644 index d79c8b4ea..000000000 --- a/Example/WalletApp/PresentationLayer/Wallet/Web3Inbox/Web3InboxViewController.swift +++ /dev/null @@ -1,48 +0,0 @@ -import UIKit -import WebKit -import Web3Inbox - -final class Web3InboxViewController: UIViewController { - - private var webView: WKWebView? { - return view as? WKWebView - } - - init() { - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func viewDidLoad() { - super.viewDidLoad() - - edgesForExtendedLayout = [] - navigationItem.title = "Web3Inbox SDK" - navigationItem.largeTitleDisplayMode = .never - view = Web3Inbox.instance.getWebView() - - let refresh = UIBarButtonItem(barButtonSystemItem: .refresh, target: self, action: #selector(refreshTapped)) - let getUrl = UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(getUrlPressed)) - - navigationItem.rightBarButtonItems = [refresh, getUrl] - } - - @objc func refreshTapped() { - Web3Inbox.instance.reload() - } - - @objc func getUrlPressed(_ sender: UIBarItem) { - UIPasteboard.general.string = webView?.url?.absoluteString - - let alert = UIAlertController(title: "URL copied to clipboard", message: nil, preferredStyle: .alert) - let action = UIAlertAction(title: "OK", style: .cancel) - alert.addAction(action) - present(alert, animated: true) - } -} - - - From 99850b1c42b7e6da237c2c11ee65b1a434aaca2b Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 13 Sep 2023 17:12:46 +0200 Subject: [PATCH 75/91] remove from frameworks --- Example/ExampleApp.xcodeproj/project.pbxproj | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index bd2e994ff..20df83c49 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -18,7 +18,6 @@ 84474A0129B9EB74005F520B /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = 84474A0029B9EB74005F520B /* Starscream */; }; 84474A0229B9ECA2005F520B /* DefaultSocketFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AEF2877F73000094373 /* DefaultSocketFactory.swift */; }; 8448F1D427E4726F0000B866 /* WalletConnect in Frameworks */ = {isa = PBXBuildFile; productRef = 8448F1D327E4726F0000B866 /* WalletConnect */; }; - 84536D7429EEBCF0008EA8DB /* Web3Inbox in Frameworks */ = {isa = PBXBuildFile; productRef = 84536D7329EEBCF0008EA8DB /* Web3Inbox */; }; 845B8D8C2934B36C0084A966 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845B8D8B2934B36C0084A966 /* Account.swift */; }; 847BD1D62989492500076C90 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D12989492500076C90 /* MainViewController.swift */; }; 847BD1D82989492500076C90 /* MainModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D32989492500076C90 /* MainModule.swift */; }; @@ -701,7 +700,6 @@ A573C53D29EC366500E3CBFD /* HDWalletKit in Frameworks */, C56EE27D293F56F8004840D1 /* WalletConnectChat in Frameworks */, C5133A78294125CC00A8314C /* Web3 in Frameworks */, - 84536D7429EEBCF0008EA8DB /* Web3Inbox in Frameworks */, C5B2F7052970573D000DBA0E /* SolanaSwift in Frameworks */, 8487A9462A836C3F0003D5AF /* Sentry in Frameworks */, C55D349929630D440004314A /* Web3Wallet in Frameworks */, @@ -1934,7 +1932,6 @@ C5133A77294125CC00A8314C /* Web3 */, C55D349829630D440004314A /* Web3Wallet */, C5B2F7042970573D000DBA0E /* SolanaSwift */, - 84536D7329EEBCF0008EA8DB /* Web3Inbox */, A573C53C29EC366500E3CBFD /* HDWalletKit */, 8487A9452A836C3F0003D5AF /* Sentry */, A5B6C0F42A6EAB2800927332 /* WalletConnectNotify */, @@ -3159,10 +3156,6 @@ isa = XCSwiftPackageProductDependency; productName = WalletConnect; }; - 84536D7329EEBCF0008EA8DB /* Web3Inbox */ = { - isa = XCSwiftPackageProductDependency; - productName = Web3Inbox; - }; 8487A9432A836C2A0003D5AF /* Sentry */ = { isa = XCSwiftPackageProductDependency; package = 8487A9422A836C2A0003D5AF /* XCRemoteSwiftPackageReference "sentry-cocoa" */; From 00b93c5bcbf096f2abce9df2c067f5c3e372c472 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 13 Sep 2023 17:18:20 +0200 Subject: [PATCH 76/91] remove w3i from package --- Package.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Package.swift b/Package.swift index 8815d2a74..edc0d65fe 100644 --- a/Package.swift +++ b/Package.swift @@ -46,9 +46,6 @@ let package = Package( .library( name: "WalletConnectHistory", targets: ["WalletConnectHistory"]), - .library( - name: "Web3Inbox", - targets: ["Web3Inbox"]), .library( name: "WalletConnectModal", targets: ["WalletConnectModal"]), @@ -98,9 +95,6 @@ let package = Package( .target( name: "WalletConnectHistory", dependencies: ["HTTPClient", "WalletConnectRelay"]), - .target( - name: "Web3Inbox", - dependencies: ["WalletConnectChat", "WalletConnectNotify"]), .target( name: "WalletConnectSigner", dependencies: ["WalletConnectNetworking"]), From e9e71b1e7a63e2d67d0e0fb7017f1da0168d7389 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 13 Sep 2023 17:44:10 +0200 Subject: [PATCH 77/91] register notify --- Example/WalletApp/ApplicationLayer/ConfigurationService.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Example/WalletApp/ApplicationLayer/ConfigurationService.swift b/Example/WalletApp/ApplicationLayer/ConfigurationService.swift index fd77aaee7..49734c329 100644 --- a/Example/WalletApp/ApplicationLayer/ConfigurationService.swift +++ b/Example/WalletApp/ApplicationLayer/ConfigurationService.swift @@ -26,6 +26,8 @@ final class ConfigurationService { Notify.instance.setLogging(level: .debug) + Task { try await Notify.instance.register(account: importAccount.account, domain: "com.walletconnect", onSign: importAccount.onSign) } + if let clientId = try? Networking.interactor.getClientId() { LoggingService.instance.setUpUser(account: importAccount.account.absoluteString, clientId: clientId) ProfilingService.instance.setUpProfiling(account: importAccount.account.absoluteString, clientId: clientId) From e5c76804a5fa2e3a517666a89e58c2993d49617b Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 14 Sep 2023 16:37:00 +0800 Subject: [PATCH 78/91] Update subscription cleanup --- .../NotifyUpdateResponseSubscriber.swift | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift index a6f60cab6..d9b2bafbd 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift @@ -36,31 +36,10 @@ private extension NotifyUpdateResponseSubscriber { responseOfType: NotifyUpdateResponsePayload.Wrapper.self, errorHandler: logger ) { [unowned self] payload in - logger.debug("Received Notify Update response") - - let subscriptionTopic = payload.topic - - let (requestPayload, requestClaims) = try NotifyUpdatePayload.decodeAndVerify(from: payload.request) - let (_, _) = try NotifyUpdateResponsePayload.decodeAndVerify(from: payload.response) - - let scope = try await buildScope(selected: requestPayload.scope, appDomain: requestPayload.app.host) - - guard let oldSubscription = notifyStorage.getSubscription(topic: subscriptionTopic) else { - logger.debug("NotifyUpdateResponseSubscriber Subscription does not exist") - return - } - notifyStorage.updateSubscription(oldSubscription, scope: scope, expiry: requestClaims.exp) + let _ = try NotifyUpdateResponsePayload.decodeAndVerify(from: payload.response) - logger.debug("Updated Subscription") - } - } - - func buildScope(selected: String, appDomain: String) async throws -> [String: ScopeValue] { - let selectedScope = selected.components(separatedBy: " ") - let availableScope = try await nofityConfigProvider.getSubscriptionScope(appDomain: appDomain) - return availableScope.reduce(into: [:]) { - $0[$1.name] = ScopeValue(description: $1.description, enabled: selectedScope.contains($1.name)) + logger.debug("Received Notify Update response") } } } From 4143e0eaf3a55c5331bb7aacaff62cae1c116918 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 14 Sep 2023 14:51:40 +0200 Subject: [PATCH 79/91] savepoint --- .../IntegrationTests/Push/NotifyTests.swift | 38 ++++++++++--------- .../Client/Wallet/NotifyClient.swift | 13 ------- 2 files changed, 21 insertions(+), 30 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index a66f08786..96f52055f 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -92,10 +92,11 @@ final class NotifyTests: XCTestCase { func testWalletCreatesSubscription() async { let expectation = expectation(description: "expects to create notify subscription") - walletNotifyClientA.newSubscriptionPublisher - .sink { [unowned self] subscription in + walletNotifyClientA.subscriptionsPublisher + .sink { [unowned self] subscriptions in + guard let subscription = subscriptions.first else {return} Task(priority: .high) { - try! await walletNotifyClientA.deleteSubscription(topic: subscription.topic) + try await walletNotifyClientA.deleteSubscription(topic: subscription.topic) expectation.fulfill() } }.store(in: &publishers) @@ -155,25 +156,28 @@ final class NotifyTests: XCTestCase { func testWalletCreatesAndUpdatesSubscription() async { let expectation = expectation(description: "expects to create and update notify subscription") let updateScope: Set = ["alerts"] + expectation.assertForOverFulfill = false try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) - walletNotifyClientA.newSubscriptionPublisher - .sink { [unowned self] subscription in - Task(priority: .high) { - try! await walletNotifyClientA.update(topic: subscription.topic, scope: updateScope) - } - } - .store(in: &publishers) - - walletNotifyClientA.updateSubscriptionPublisher - .sink { [unowned self] subscription in + var didUpdate = false + walletNotifyClientA.subscriptionsPublisher + .sink { [unowned self] subscriptions in + guard let subscription = subscriptions.first else {return} let updatedScope = Set(subscription.scope.filter{ $0.value.enabled == true }.keys) - XCTAssertEqual(updatedScope, updateScope) - Task(priority: .high) { - try! await walletNotifyClientA.deleteSubscription(topic: subscription.topic) - expectation.fulfill() + + if !didUpdate { + didUpdate = true + Task(priority: .high) { + try await walletNotifyClientA.update(topic: subscription.topic, scope: updateScope) + } + } + if updateScope == updatedScope { + Task(priority: .high) { + try await walletNotifyClientA.deleteSubscription(topic: subscription.topic) + expectation.fulfill() + } } }.store(in: &publishers) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 9bd35e7f8..e8f5834cb 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -5,15 +5,6 @@ public class NotifyClient { private var publishers = Set() - /// publishes new subscriptions - public var newSubscriptionPublisher: AnyPublisher { - return notifyStorage.newSubscriptionPublisher - } - - public var deleteSubscriptionPublisher: AnyPublisher { - return notifyStorage.deleteSubscriptionPublisher - } - public var subscriptionsPublisher: AnyPublisher<[NotifySubscription], Never> { return notifyStorage.subscriptionsPublisher } @@ -22,10 +13,6 @@ public class NotifyClient { return notifyMessageSubscriber.notifyMessagePublisher } - public var updateSubscriptionPublisher: AnyPublisher { - return notifyStorage.updateSubscriptionPublisher - } - public var logsPublisher: AnyPublisher { logger.logsPublisher .eraseToAnyPublisher() From b3232a6b036d77fbd5dc937430b0229e37ffc99f Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 14 Sep 2023 14:56:07 +0200 Subject: [PATCH 80/91] fix notify test --- Example/IntegrationTests/Push/NotifyTests.swift | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index 96f52055f..cd8f80557 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -194,12 +194,17 @@ final class NotifyTests: XCTestCase { try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) - walletNotifyClientA.newSubscriptionPublisher - .sink { subscription in + var didNotify = false + walletNotifyClientA.subscriptionsPublisher + .sink { subscriptions in + guard let subscription = subscriptions.first else {return} let notifier = Publisher() - Task(priority: .high) { - try await notifier.notify(topic: subscription.topic, account: subscription.account, message: notifyMessage) - subscribeExpectation.fulfill() + if !didNotify { + didNotify = true + Task(priority: .high) { + try await notifier.notify(topic: subscription.topic, account: subscription.account, message: notifyMessage) + subscribeExpectation.fulfill() + } } }.store(in: &publishers) From de8733e8cbe488ef702876f9a74c50a50707c6db Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 14 Sep 2023 19:32:39 +0800 Subject: [PATCH 81/91] Discover list --- Example/ExampleApp.xcodeproj/project.pbxproj | 8 ++ .../Common/Helpers/SegmentedPicker.swift | 94 +++++++++++++ .../Models/ListingViewModel.swift | 20 +++ .../NotificationsPresenter.swift | 7 +- .../Notifications/NotificationsView.swift | 130 ++++++++++++------ 5 files changed, 215 insertions(+), 44 deletions(-) create mode 100644 Example/WalletApp/Common/Helpers/SegmentedPicker.swift create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 20df83c49..5c1892633 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -197,6 +197,8 @@ A5C2022B287EB89A007E3188 /* WelcomeInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5C2022A287EB89A007E3188 /* WelcomeInteractor.swift */; }; A5C5153329BB7A6A004210BA /* InviteType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5C5153229BB7A6A004210BA /* InviteType.swift */; }; A5C8BE85292FE20B006CC85C /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = A5C8BE84292FE20B006CC85C /* Web3 */; }; + A5D610C82AB31EE800C20083 /* SegmentedPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D610C72AB31EE800C20083 /* SegmentedPicker.swift */; }; + A5D610CA2AB3249100C20083 /* ListingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D610C92AB3249100C20083 /* ListingViewModel.swift */; }; A5D85228286333E300DAF5C3 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A5D85227286333E300DAF5C3 /* Starscream */; }; A5E03DF52864651200888481 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A5E03DF42864651200888481 /* Starscream */; }; A5E03DFA286465C700888481 /* SignClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03DF9286465C700888481 /* SignClientTests.swift */; }; @@ -526,6 +528,8 @@ A5C20228287EB34C007E3188 /* AccountStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountStorage.swift; sourceTree = ""; }; A5C2022A287EB89A007E3188 /* WelcomeInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeInteractor.swift; sourceTree = ""; }; A5C5153229BB7A6A004210BA /* InviteType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteType.swift; sourceTree = ""; }; + A5D610C72AB31EE800C20083 /* SegmentedPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedPicker.swift; sourceTree = ""; }; + A5D610C92AB3249100C20083 /* ListingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListingViewModel.swift; sourceTree = ""; }; A5E03DED286464DB00888481 /* IntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A5E03DF9286465C700888481 /* SignClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignClientTests.swift; sourceTree = ""; }; A5E03DFC286465D100888481 /* Stubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stubs.swift; sourceTree = ""; }; @@ -825,6 +829,7 @@ isa = PBXGroup; children = ( 847BD1EA298A87AB00076C90 /* SubscriptionsViewModel.swift */, + A5D610C92AB3249100C20083 /* ListingViewModel.swift */, ); path = Models; sourceTree = ""; @@ -1696,6 +1701,7 @@ C56EE2A2293F6BAF004840D1 /* UIPasteboardWrapper.swift */, C55D349A2965BC2F0004314A /* TagsView.swift */, A74D32B92A1E25AD00CB8536 /* QueryParameters.swift */, + A5D610C72AB31EE800C20083 /* SegmentedPicker.swift */, ); path = Helpers; sourceTree = ""; @@ -2309,6 +2315,7 @@ C55D3497295DFA750004314A /* WelcomeView.swift in Sources */, A57879722A4F225E00F8D10B /* ImportAccount.swift in Sources */, C5B2F71029705827000DBA0E /* EthereumTransaction.swift in Sources */, + A5D610C82AB31EE800C20083 /* SegmentedPicker.swift in Sources */, C56EE271293F56D7004840D1 /* View.swift in Sources */, C5B2F6FD297055B0000DBA0E /* Signer.swift in Sources */, C56EE24D293F566D004840D1 /* WalletRouter.swift in Sources */, @@ -2359,6 +2366,7 @@ C55D3494295DFA750004314A /* WelcomePresenter.swift in Sources */, C5B2F6F929705293000DBA0E /* SessionRequestPresenter.swift in Sources */, A57879712A4EDC8100F8D10B /* TextFieldView.swift in Sources */, + A5D610CA2AB3249100C20083 /* ListingViewModel.swift in Sources */, 84DB38F32983CDAE00BFEE37 /* PushRegisterer.swift in Sources */, 84943C7F2A9BA48C007EBAC2 /* ProfilingService.swift in Sources */, C5B2F6FB297055B0000DBA0E /* ETHSigner.swift in Sources */, diff --git a/Example/WalletApp/Common/Helpers/SegmentedPicker.swift b/Example/WalletApp/Common/Helpers/SegmentedPicker.swift new file mode 100644 index 000000000..a9906f378 --- /dev/null +++ b/Example/WalletApp/Common/Helpers/SegmentedPicker.swift @@ -0,0 +1,94 @@ +import SwiftUI + +public struct SegmentedPicker: View where Content: View, Selection: View { + + public typealias Data = [Element] + + @State private var frames: [CGRect] + @Binding private var selectedIndex: Data.Index? + + private let data: Data + private let selection: () -> Selection + private let content: (Data.Element, Bool) -> Content + + public init(_ data: Data, + selectedIndex: Binding, + @ViewBuilder content: @escaping (Data.Element, Bool) -> Content, + @ViewBuilder selection: @escaping () -> Selection + ) { + self.data = data + self.content = content + self.selection = selection + self._selectedIndex = selectedIndex + self._frames = State(wrappedValue: Array(repeating: .zero, count: data.count)) + } + + public var body: some View { + ZStack(alignment: Alignment(horizontal: .horizontalCenterAlignment, vertical: .center)) { + + if let selectedIndex = selectedIndex { + selection() + .frame(width: frames[selectedIndex].width, + height: frames[selectedIndex].height) + .alignmentGuide(.horizontalCenterAlignment) { dimensions in + dimensions[HorizontalAlignment.center] + } + } + + HStack(spacing: 0) { + ForEach(data.indices, id: \.self) { index in + Button(action: { selectedIndex = index }, + label: { content(data[index], selectedIndex == index) } + ) + .buttonStyle(PlainButtonStyle()) + .background(GeometryReader { proxy in + Color.clear.onAppear { frames[index] = proxy.frame(in: .global) } + }) + .alignmentGuide(.horizontalCenterAlignment, + isActive: selectedIndex == index) { dimensions in + dimensions[HorizontalAlignment.center] + } + } + } + } + } +} + +extension HorizontalAlignment { + + private enum CenterAlignmentID: AlignmentID { + static func defaultValue(in dimension: ViewDimensions) -> CGFloat { + return dimension[HorizontalAlignment.center] + } + } + + static var horizontalCenterAlignment: HorizontalAlignment { + HorizontalAlignment(CenterAlignmentID.self) + } +} + +extension View { + @ViewBuilder + @inlinable func alignmentGuide(_ alignment: HorizontalAlignment, + isActive: Bool, + computeValue: @escaping (ViewDimensions) -> CGFloat + ) -> some View { + if isActive { + alignmentGuide(alignment, computeValue: computeValue) + } else { + self + } + } + + @ViewBuilder + @inlinable func alignmentGuide(_ alignment: VerticalAlignment, + isActive: Bool, + computeValue: @escaping (ViewDimensions) -> CGFloat) -> some View + { + if isActive { + alignmentGuide(alignment, computeValue: computeValue) + } else { + self + } + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift new file mode 100644 index 000000000..8ac6a36ec --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift @@ -0,0 +1,20 @@ +import Foundation + +struct ListingViewModel: Identifiable { + + var id: String { + return UUID().uuidString + } + + var imageUrl: String { + return "" + } + + var title: String { + return "Title" + } + + var subtitle: String { + return "Subtitle" + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift index 0aa9d878d..8a3c81aec 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift @@ -8,6 +8,7 @@ final class NotificationsPresenter: ObservableObject { private var disposeBag = Set() @Published var subscriptions: [SubscriptionsViewModel] = [] + @Published var listings: [ListingViewModel] = [ListingViewModel(), ListingViewModel()] init(interactor: NotificationsInteractor, router: NotificationsRouter) { defer { setupInitialState() } @@ -20,6 +21,10 @@ final class NotificationsPresenter: ObservableObject { router.presentNotifications(subscription: subscription.subscription) } + func didPress(_ listing: ListingViewModel) { + + } + func setupInitialState() { setupSubscriptions() } @@ -35,7 +40,7 @@ final class NotificationsPresenter: ObservableObject { extension NotificationsPresenter: SceneViewModel { var sceneTitle: String? { - return "Notifications" + return "Inbox" } var largeTitleDisplayMode: UINavigationItem.LargeTitleDisplayMode { diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift index aed832740..9e956c0fa 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift @@ -4,65 +4,109 @@ struct NotificationsView: View { @EnvironmentObject var presenter: NotificationsPresenter + @State var selectedIndex: Int = 0 + @ViewBuilder var body: some View { - ZStack { - Color.grey100 - .edgesIgnoringSafeArea(.all) - - VStack(alignment: .leading, spacing: 16) { - ZStack { - if presenter.subscriptions.isEmpty { - VStack(spacing: 10) { - Image(systemName: "bell.badge.fill") - .resizable() - .frame(width: 32, height: 32) - .aspectRatio(contentMode: .fit) - .foregroundColor(.grey50) - - Text("Notifications from connected apps will appear here. To enable notifications, visit the app in your browser and look for a \(Image(systemName: "bell.fill")) notifications toggle \(Image(systemName: "switch.2"))") - .foregroundColor(.grey50) - .font(.system(size: 15, weight: .regular, design: .rounded)) - .multilineTextAlignment(.center) - .lineSpacing(4) - } - .padding(20) + VStack { + HStack { + SegmentedPicker(["Notifications", "Discover"], + selectedIndex: Binding( + get: { selectedIndex }, + set: { selectedIndex = $0 ?? 0 }), + content: { item, isSelected in + Text(item) + .font(.headline) + .foregroundColor(isSelected ? Color.black : Color.gray ) + .padding(.horizontal, 16) + .padding(.vertical, 8) + }, + selection: { + VStack(spacing: 0) { + Spacer() + Rectangle() + .fill(Color.black) + .frame(height: 1) + } + }) + .animation(.easeInOut(duration: 0.3)) + + Spacer() + } + + if selectedIndex == 0 { + notifications() + } else { + discover() + } + } + } + + private func discover() -> some View { + List { + ForEach(presenter.listings, id: \.id) { listing in + listRow(title: listing.title, subtitle: listing.subtitle, imageUrl: listing.imageUrl) { + presenter.didPress(listing) + } + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0)) + } + } + .listStyle(PlainListStyle()) + .padding(.vertical, 20) + } + + private func notifications() -> some View { + VStack(alignment: .leading, spacing: 16) { + ZStack { + if presenter.subscriptions.isEmpty { + VStack(spacing: 10) { + Image(systemName: "bell.badge.fill") + .resizable() + .frame(width: 32, height: 32) + .aspectRatio(contentMode: .fit) + .foregroundColor(.grey50) + + Text("Notifications from connected apps will appear here. To enable notifications, visit the app in your browser and look for a \(Image(systemName: "bell.fill")) notifications toggle \(Image(systemName: "switch.2"))") + .foregroundColor(.grey50) + .font(.system(size: 15, weight: .regular, design: .rounded)) + .multilineTextAlignment(.center) + .lineSpacing(4) } + .padding(20) + } - VStack { - if !presenter.subscriptions.isEmpty { - List { - ForEach(presenter.subscriptions, id: \.id) { subscription in - subscriptionsView(subscription: subscription) - .listRowSeparator(.hidden) - .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0)) + VStack { + if !presenter.subscriptions.isEmpty { + List { + ForEach(presenter.subscriptions, id: \.id) { subscription in + listRow(title: subscription.title, subtitle: subscription.subtitle, imageUrl: subscription.imageUrl) { + presenter.didPress(subscription) } - .onDelete { indexSet in - Task(priority: .high) { - await presenter.removeSubscribtion(at: indexSet) - } + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0)) + } + .onDelete { indexSet in + Task(priority: .high) { + await presenter.removeSubscribtion(at: indexSet) } } - .listStyle(PlainListStyle()) } + .listStyle(PlainListStyle()) } } } - .padding(.vertical, 20) } + .padding(.vertical, 20) } - - - - - private func subscriptionsView(subscription: SubscriptionsViewModel) -> some View { + private func listRow(title: String, subtitle: String, imageUrl: String, action: @escaping () -> Void) -> some View { Button { - presenter.didPress(subscription) + action() } label: { VStack { HStack(spacing: 10) { - AsyncImage(url: URL(string: subscription.imageUrl)) { phase in + AsyncImage(url: URL(string: imageUrl)) { phase in if let image = phase.image { image .resizable() @@ -78,11 +122,11 @@ struct NotificationsView: View { .padding(.leading, 20) VStack(alignment: .leading, spacing: 2) { - Text(subscription.title) + Text(title) .foregroundColor(.grey8) .font(.system(size: 20, weight: .semibold, design: .rounded)) - Text(subscription.subtitle) + Text(subtitle) .foregroundColor(.grey50) .font(.system(size: 13, weight: .medium, design: .rounded)) } From 8087851a809de59f5cbdea8b5c9bc94232c9fd81 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 15 Sep 2023 00:18:31 +0800 Subject: [PATCH 82/91] Explorer --- Example/ExampleApp.xcodeproj/project.pbxproj | 44 +++++++++- .../ListingsSertice/Listings.swift | 45 +++++++++++ .../ListingsSertice/ListingsAPI.swift | 31 +++++++ .../ListingsNetworkService.swift | 15 ++++ .../Common/Helpers/FailableDecodable.swift | 18 +++++ .../Wallet/Main/MainPresenter.swift | 2 +- .../Wallet/Main/MainRouter.swift | 4 +- .../Models/ListingViewModel.swift | 16 ++-- .../Models/SubscriptionsViewModel.swift | 8 +- .../NotificationsInteractor.swift | 19 +++++ .../Notifications/NotificationsModule.swift | 4 +- .../NotificationsPresenter.swift | 29 +++++-- .../Notifications/NotificationsView.swift | 80 ++++++++++++++----- 13 files changed, 275 insertions(+), 40 deletions(-) create mode 100644 Example/WalletApp/BusinessLayer/ListingsSertice/Listings.swift create mode 100644 Example/WalletApp/BusinessLayer/ListingsSertice/ListingsAPI.swift create mode 100644 Example/WalletApp/BusinessLayer/ListingsSertice/ListingsNetworkService.swift create mode 100644 Example/WalletApp/Common/Helpers/FailableDecodable.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 5c1892633..2eabffb63 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -160,6 +160,7 @@ A58EC616299D5C6400F3452A /* PlainButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58EC615299D5C6400F3452A /* PlainButton.swift */; }; A58EC618299D665A00F3452A /* Web3Inbox in Frameworks */ = {isa = PBXBuildFile; productRef = A58EC617299D665A00F3452A /* Web3Inbox */; }; A59CF4F6292F83D50031A42F /* DefaultSignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59CF4F5292F83D50031A42F /* DefaultSignerFactory.swift */; }; + A59D25EE2AB3672700D7EA3A /* AsyncButton in Frameworks */ = {isa = PBXBuildFile; productRef = A59D25ED2AB3672700D7EA3A /* AsyncButton */; }; A59F877628B5462900A9CD80 /* WalletConnectAuth in Frameworks */ = {isa = PBXBuildFile; productRef = A59F877528B5462900A9CD80 /* WalletConnectAuth */; }; A59FAEC928B7B93A002BB66F /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = A59FAEC828B7B93A002BB66F /* Web3 */; }; A5A0843D29D2F624000B9B17 /* DefaultCryptoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A0843B29D2F60A000B9B17 /* DefaultCryptoProvider.swift */; }; @@ -199,6 +200,10 @@ A5C8BE85292FE20B006CC85C /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = A5C8BE84292FE20B006CC85C /* Web3 */; }; A5D610C82AB31EE800C20083 /* SegmentedPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D610C72AB31EE800C20083 /* SegmentedPicker.swift */; }; A5D610CA2AB3249100C20083 /* ListingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D610C92AB3249100C20083 /* ListingViewModel.swift */; }; + A5D610CE2AB3594100C20083 /* ListingsAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D610CD2AB3594100C20083 /* ListingsAPI.swift */; }; + A5D610D02AB35AD500C20083 /* ListingsNetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D610CF2AB35AD500C20083 /* ListingsNetworkService.swift */; }; + A5D610D22AB35B1100C20083 /* Listings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D610D12AB35B1100C20083 /* Listings.swift */; }; + A5D610D42AB35BED00C20083 /* FailableDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D610D32AB35BED00C20083 /* FailableDecodable.swift */; }; A5D85228286333E300DAF5C3 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A5D85227286333E300DAF5C3 /* Starscream */; }; A5E03DF52864651200888481 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A5E03DF42864651200888481 /* Starscream */; }; A5E03DFA286465C700888481 /* SignClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03DF9286465C700888481 /* SignClientTests.swift */; }; @@ -530,6 +535,10 @@ A5C5153229BB7A6A004210BA /* InviteType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteType.swift; sourceTree = ""; }; A5D610C72AB31EE800C20083 /* SegmentedPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedPicker.swift; sourceTree = ""; }; A5D610C92AB3249100C20083 /* ListingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListingViewModel.swift; sourceTree = ""; }; + A5D610CD2AB3594100C20083 /* ListingsAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListingsAPI.swift; sourceTree = ""; }; + A5D610CF2AB35AD500C20083 /* ListingsNetworkService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListingsNetworkService.swift; sourceTree = ""; }; + A5D610D12AB35B1100C20083 /* Listings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Listings.swift; sourceTree = ""; }; + A5D610D32AB35BED00C20083 /* FailableDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailableDecodable.swift; sourceTree = ""; }; A5E03DED286464DB00888481 /* IntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A5E03DF9286465C700888481 /* SignClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignClientTests.swift; sourceTree = ""; }; A5E03DFC286465D100888481 /* Stubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stubs.swift; sourceTree = ""; }; @@ -702,6 +711,7 @@ buildActionMask = 2147483647; files = ( A573C53D29EC366500E3CBFD /* HDWalletKit in Frameworks */, + A59D25EE2AB3672700D7EA3A /* AsyncButton in Frameworks */, C56EE27D293F56F8004840D1 /* WalletConnectChat in Frameworks */, C5133A78294125CC00A8314C /* Web3 in Frameworks */, C5B2F7052970573D000DBA0E /* SolanaSwift in Frameworks */, @@ -1415,6 +1425,24 @@ path = Components; sourceTree = ""; }; + A5D610CB2AB358ED00C20083 /* BusinessLayer */ = { + isa = PBXGroup; + children = ( + A5D610CC2AB3592F00C20083 /* ListingsSertice */, + ); + path = BusinessLayer; + sourceTree = ""; + }; + A5D610CC2AB3592F00C20083 /* ListingsSertice */ = { + isa = PBXGroup; + children = ( + A5D610CD2AB3594100C20083 /* ListingsAPI.swift */, + A5D610CF2AB35AD500C20083 /* ListingsNetworkService.swift */, + A5D610D12AB35B1100C20083 /* Listings.swift */, + ); + path = ListingsSertice; + sourceTree = ""; + }; A5E03DEE286464DB00888481 /* IntegrationTests */ = { isa = PBXGroup; children = ( @@ -1533,6 +1561,7 @@ C56EE25C293F56D6004840D1 /* Common */, C56EE27E293F5756004840D1 /* ApplicationLayer */, C56EE29E293F577B004840D1 /* PresentationLayer */, + A5D610CB2AB358ED00C20083 /* BusinessLayer */, C56EE2A0293F6B10004840D1 /* Other */, ); path = WalletApp; @@ -1702,6 +1731,7 @@ C55D349A2965BC2F0004314A /* TagsView.swift */, A74D32B92A1E25AD00CB8536 /* QueryParameters.swift */, A5D610C72AB31EE800C20083 /* SegmentedPicker.swift */, + A5D610D32AB35BED00C20083 /* FailableDecodable.swift */, ); path = Helpers; sourceTree = ""; @@ -1942,6 +1972,7 @@ 8487A9452A836C3F0003D5AF /* Sentry */, A5B6C0F42A6EAB2800927332 /* WalletConnectNotify */, 84943C7C2A9BA328007EBAC2 /* Mixpanel */, + A59D25ED2AB3672700D7EA3A /* AsyncButton */, ); productName = ChatWallet; productReference = C56EE21B293F55ED004840D1 /* WalletApp.app */; @@ -2319,6 +2350,7 @@ C56EE271293F56D7004840D1 /* View.swift in Sources */, C5B2F6FD297055B0000DBA0E /* Signer.swift in Sources */, C56EE24D293F566D004840D1 /* WalletRouter.swift in Sources */, + A5D610D02AB35AD500C20083 /* ListingsNetworkService.swift in Sources */, C5F32A342954817600A6476E /* ConnectionDetailsView.swift in Sources */, C55D348A295DD8CA0004314A /* PasteUriPresenter.swift in Sources */, A51811A22A52E83100A52B15 /* SettingsInteractor.swift in Sources */, @@ -2368,9 +2400,11 @@ A57879712A4EDC8100F8D10B /* TextFieldView.swift in Sources */, A5D610CA2AB3249100C20083 /* ListingViewModel.swift in Sources */, 84DB38F32983CDAE00BFEE37 /* PushRegisterer.swift in Sources */, + A5D610CE2AB3594100C20083 /* ListingsAPI.swift in Sources */, 84943C7F2A9BA48C007EBAC2 /* ProfilingService.swift in Sources */, C5B2F6FB297055B0000DBA0E /* ETHSigner.swift in Sources */, C56EE274293F56D7004840D1 /* SceneViewController.swift in Sources */, + A5D610D42AB35BED00C20083 /* FailableDecodable.swift in Sources */, 847BD1E5298A806800076C90 /* NotificationsPresenter.swift in Sources */, C55D3496295DFA750004314A /* WelcomeInteractor.swift in Sources */, C5B2F6FC297055B0000DBA0E /* SOLSigner.swift in Sources */, @@ -2386,6 +2420,7 @@ A51811A32A52E83100A52B15 /* SettingsView.swift in Sources */, A57879732A4F248200F8D10B /* AccountStorage.swift in Sources */, C55D34AF2965FB750004314A /* SessionProposalPresenter.swift in Sources */, + A5D610D22AB35B1100C20083 /* Listings.swift in Sources */, C5F32A302954816100A6476E /* ConnectionDetailsInteractor.swift in Sources */, 847BD1E8298A806800076C90 /* NotificationsView.swift in Sources */, ); @@ -2915,7 +2950,7 @@ INFOPLIST_KEY_UIRequiresFullScreen = NO; INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; - IPHONEOS_DEPLOYMENT_TARGET = 15.4; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2953,7 +2988,7 @@ INFOPLIST_KEY_UIRequiresFullScreen = NO; INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; - IPHONEOS_DEPLOYMENT_TARGET = 15.4; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -3239,6 +3274,11 @@ isa = XCSwiftPackageProductDependency; productName = Web3Inbox; }; + A59D25ED2AB3672700D7EA3A /* AsyncButton */ = { + isa = XCSwiftPackageProductDependency; + package = A58EC60F299D57B800F3452A /* XCRemoteSwiftPackageReference "swiftui-async-button" */; + productName = AsyncButton; + }; A59F877528B5462900A9CD80 /* WalletConnectAuth */ = { isa = XCSwiftPackageProductDependency; productName = WalletConnectAuth; diff --git a/Example/WalletApp/BusinessLayer/ListingsSertice/Listings.swift b/Example/WalletApp/BusinessLayer/ListingsSertice/Listings.swift new file mode 100644 index 000000000..56e4158a5 --- /dev/null +++ b/Example/WalletApp/BusinessLayer/ListingsSertice/Listings.swift @@ -0,0 +1,45 @@ +import Foundation + +struct Listing: Codable { + struct ImageURL: Codable { + @FailableDecodable + private(set) var sm: URL? + + @FailableDecodable + private(set) var md: URL? + + @FailableDecodable + private(set) var lg: URL? + } + struct App: Codable { + @FailableDecodable + private(set) var ios: URL? + + @FailableDecodable + private(set) var android: URL? + + @FailableDecodable + private(set) var browser: URL? + } + struct Mobile: Codable { + let native: String? + let universal: String? + } + struct Metadata: Codable { + struct Colors: Codable { + let primary: String? + let secondary: String? + } + let shortName: String + let colors: Colors + } + let id: String + let name: String + let description: String + let homepage: String + let image_url: ImageURL + let app: App + let mobile: Mobile + let metadata: Metadata + let chains: [String] +} diff --git a/Example/WalletApp/BusinessLayer/ListingsSertice/ListingsAPI.swift b/Example/WalletApp/BusinessLayer/ListingsSertice/ListingsAPI.swift new file mode 100644 index 000000000..f718a5b8a --- /dev/null +++ b/Example/WalletApp/BusinessLayer/ListingsSertice/ListingsAPI.swift @@ -0,0 +1,31 @@ +import Foundation +import HTTPClient + +enum ListingsAPI: HTTPService { + + var path: String { + return "/v3/dapps" + } + + var method: HTTPMethod { + return .get + } + + var body: Data? { + return nil + } + + var queryParameters: [String : String]? { + return ["projectId": InputConfig.projectId, "is_notify_enabled": "true"] + } + + var additionalHeaderFields: [String : String]? { + return nil + } + + var scheme: String { + return "https" + } + + case notifyDApps +} diff --git a/Example/WalletApp/BusinessLayer/ListingsSertice/ListingsNetworkService.swift b/Example/WalletApp/BusinessLayer/ListingsSertice/ListingsNetworkService.swift new file mode 100644 index 000000000..e11f30bdb --- /dev/null +++ b/Example/WalletApp/BusinessLayer/ListingsSertice/ListingsNetworkService.swift @@ -0,0 +1,15 @@ +import Foundation +import HTTPClient + +final class ListingsNetworkService { + + struct ListingsResponse: Codable { + let listings: [String: Listing] + } + + func getListings() async throws -> [Listing] { + let httpClient = HTTPNetworkClient(host: "explorer-api.walletconnect.com") + let response = try await httpClient.request(ListingsResponse.self, at: ListingsAPI.notifyDApps) + return response.listings.values.compactMap { $0 } + } +} diff --git a/Example/WalletApp/Common/Helpers/FailableDecodable.swift b/Example/WalletApp/Common/Helpers/FailableDecodable.swift new file mode 100644 index 000000000..f4274e35e --- /dev/null +++ b/Example/WalletApp/Common/Helpers/FailableDecodable.swift @@ -0,0 +1,18 @@ +@propertyWrapper +struct FailableDecodable: Codable, Hashable { + var wrappedValue: Wrapped? + + init(_ wrappedValue: Wrapped?) { + self.wrappedValue = wrappedValue + } + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + wrappedValue = try? container.decode(Wrapped.self) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(wrappedValue) + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift index 82a927cc2..762bdf97c 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift @@ -16,7 +16,7 @@ final class MainPresenter { var viewControllers: [UIViewController] { return [ router.walletViewController(importAccount: importAccount), - router.notificationsViewController(), + router.notificationsViewController(importAccount: importAccount), router.settingsViewController() ] } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift index b92eabc25..211a1fc62 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift @@ -17,8 +17,8 @@ final class MainRouter { .wrapToNavigationController() } - func notificationsViewController() -> UIViewController { - return NotificationsModule.create(app: app) + func notificationsViewController(importAccount: ImportAccount) -> UIViewController { + return NotificationsModule.create(app: app, importAccount: importAccount) .wrapToNavigationController() } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift index 8ac6a36ec..92ded2fdf 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift @@ -2,19 +2,25 @@ import Foundation struct ListingViewModel: Identifiable { + let listing: Listing + var id: String { - return UUID().uuidString + return listing.id } - var imageUrl: String { - return "" + var imageUrl: URL? { + return listing.image_url.md } var title: String { - return "Title" + return listing.name } var subtitle: String { - return "Subtitle" + return listing.description + } + + var url: String { + return listing.homepage } } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift index e727c94e3..7029134ad 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift @@ -8,8 +8,8 @@ struct SubscriptionsViewModel: Identifiable { return subscription.topic } - var imageUrl: String { - return subscription.metadata.url + var imageUrl: URL? { + return try? subscription.metadata.icons.first?.asURL() } var title: String { @@ -19,4 +19,8 @@ struct SubscriptionsViewModel: Identifiable { var subtitle: String { return subscription.metadata.description } + + var url: String { + return subscription.metadata.url + } } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift index 84797d283..7d821354d 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift @@ -7,11 +7,22 @@ final class NotificationsInteractor { return Notify.instance.subscriptionsPublisher } + private let importAccount: ImportAccount + + init(importAccount: ImportAccount) { + self.importAccount = importAccount + } + func getSubscriptions() -> [NotifySubscription] { let subs = Notify.instance.getActiveSubscriptions() return subs } + func getListings() async throws -> [Listing] { + let service = ListingsNetworkService() + return try await service.getListings() + } + func removeSubscription(_ subscription: NotifySubscription) async { do { try await Notify.instance.deleteSubscription(topic: subscription.topic) @@ -19,4 +30,12 @@ final class NotificationsInteractor { print(error) } } + + func subscribe(url: String) async throws { + try await Notify.instance.subscribe(appDomain: url, account: importAccount.account) + } + + func unsubscribe(topic: String) async throws { + try await Notify.instance.deleteSubscription(topic: topic) + } } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsModule.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsModule.swift index f7b2b620c..cbfdf2c41 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsModule.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsModule.swift @@ -3,9 +3,9 @@ import SwiftUI final class NotificationsModule { @discardableResult - static func create(app: Application) -> UIViewController { + static func create(app: Application, importAccount: ImportAccount) -> UIViewController { let router = NotificationsRouter(app: app) - let interactor = NotificationsInteractor() + let interactor = NotificationsInteractor(importAccount: importAccount) let presenter = NotificationsPresenter(interactor: interactor, router: router) let view = NotificationsView().environmentObject(presenter) let viewController = SceneViewController(viewModel: presenter, content: view) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift index 8a3c81aec..4f2c18fb6 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift @@ -8,7 +8,7 @@ final class NotificationsPresenter: ObservableObject { private var disposeBag = Set() @Published var subscriptions: [SubscriptionsViewModel] = [] - @Published var listings: [ListingViewModel] = [ListingViewModel(), ListingViewModel()] + @Published var listings: [ListingViewModel] = [] init(interactor: NotificationsInteractor, router: NotificationsRouter) { defer { setupInitialState() } @@ -17,11 +17,28 @@ final class NotificationsPresenter: ObservableObject { } - func didPress(_ subscription: SubscriptionsViewModel) { + @MainActor + func fetch() async throws { + self.listings = try await interactor.getListings().map { ListingViewModel(listing: $0) } + } + + func subscription(forListing listing: ListingViewModel) -> SubscriptionsViewModel? { + return subscriptions.first(where: { $0.url == listing.url }) + } + + func subscribe(listing: ListingViewModel) async throws { + try await interactor.subscribe(url: listing.url) + } + + func unsubscribe(subscription: SubscriptionsViewModel) async throws { + try await interactor.unsubscribe(topic: subscription.subscription.topic) + } + + func didPress(subscription: SubscriptionsViewModel) { router.presentNotifications(subscription: subscription.subscription) } - func didPress(_ listing: ListingViewModel) { + func didPress(listing: ListingViewModel) { } @@ -53,10 +70,8 @@ extension NotificationsPresenter: SceneViewModel { private extension NotificationsPresenter { func setupSubscriptions() { - self.subscriptions = interactor.getSubscriptions() - .map { - return SubscriptionsViewModel(subscription: $0) - } + self.subscriptions = interactor.getSubscriptions().map { SubscriptionsViewModel(subscription: $0) } + interactor.subscriptionsPublisher .receive(on: DispatchQueue.main) .sink { [weak self] notifySubscriptions in diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift index 9e956c0fa..eaba97801 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift @@ -1,4 +1,5 @@ import SwiftUI +import AsyncButton struct NotificationsView: View { @@ -39,17 +40,17 @@ struct NotificationsView: View { } else { discover() } + }.task { + try! await presenter.fetch() } } private func discover() -> some View { - List { - ForEach(presenter.listings, id: \.id) { listing in - listRow(title: listing.title, subtitle: listing.subtitle, imageUrl: listing.imageUrl) { - presenter.didPress(listing) - } - .listRowSeparator(.hidden) - .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0)) + return List { + ForEach(presenter.listings) { listing in + listingRow(listing: listing) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0)) } } .listStyle(PlainListStyle()) @@ -80,11 +81,9 @@ struct NotificationsView: View { if !presenter.subscriptions.isEmpty { List { ForEach(presenter.subscriptions, id: \.id) { subscription in - listRow(title: subscription.title, subtitle: subscription.subtitle, imageUrl: subscription.imageUrl) { - presenter.didPress(subscription) - } - .listRowSeparator(.hidden) - .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0)) + subscriptionRow(subscription: subscription) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0)) } .onDelete { indexSet in Task(priority: .high) { @@ -100,21 +99,21 @@ struct NotificationsView: View { .padding(.vertical, 20) } - private func listRow(title: String, subtitle: String, imageUrl: String, action: @escaping () -> Void) -> some View { + private func subscriptionRow(subscription: SubscriptionsViewModel) -> some View { Button { - action() + presenter.didPress(subscription: subscription) } label: { VStack { HStack(spacing: 10) { - AsyncImage(url: URL(string: imageUrl)) { phase in + AsyncImage(url: subscription.imageUrl) { phase in if let image = phase.image { image .resizable() .frame(width: 60, height: 60) - .background(Color.black) + .background(Color.black.opacity(0.1)) .cornerRadius(30, corners: .allCorners) } else { - Color.black + Color.black.opacity(0.1) .frame(width: 60, height: 60) .cornerRadius(30, corners: .allCorners) } @@ -122,11 +121,11 @@ struct NotificationsView: View { .padding(.leading, 20) VStack(alignment: .leading, spacing: 2) { - Text(title) + Text(subscription.title) .foregroundColor(.grey8) .font(.system(size: 20, weight: .semibold, design: .rounded)) - Text(subtitle) + Text(subscription.subtitle) .foregroundColor(.grey50) .font(.system(size: 13, weight: .medium, design: .rounded)) } @@ -140,6 +139,49 @@ struct NotificationsView: View { } } } + + private func listingRow(listing: ListingViewModel) -> some View { + VStack { + HStack(spacing: 10) { + AsyncImage(url: listing.imageUrl) { phase in + if let image = phase.image { + image + .resizable() + .frame(width: 60, height: 60) + .background(Color.black.opacity(0.1)) + .cornerRadius(30, corners: .allCorners) + } else { + Color.black.opacity(0.1) + .frame(width: 60, height: 60) + .cornerRadius(30, corners: .allCorners) + } + } + .padding(.leading, 20) + + VStack(alignment: .leading, spacing: 2) { + Text(listing.title) + .foregroundColor(.grey8) + .font(.system(size: 20, weight: .semibold, design: .rounded)) + + Text(listing.subtitle) + .foregroundColor(.grey50) + .font(.system(size: 13, weight: .medium, design: .rounded)) + } + + Spacer() + + if let subscription = presenter.subscription(forListing: listing) { + AsyncButton("Unsubscribe") { + try await presenter.unsubscribe(subscription: subscription) + }.padding(16.0) + } else { + AsyncButton("Subscribe") { + try await presenter.subscribe(listing: listing) + }.padding(16.0) + } + } + } + } } #if DEBUG From 302f6d81458221393299b04b59b880e154d5f1b3 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 15 Sep 2023 01:39:25 +0800 Subject: [PATCH 83/91] Subscribe / unsubscribe connected --- .../Wallet/Notifications/Models/ListingViewModel.swift | 6 ++++-- .../Wallet/Notifications/NotificationsInteractor.swift | 4 ++-- .../Wallet/Notifications/NotificationsPresenter.swift | 6 ++++-- .../Wallet/Notifications/NotificationsView.swift | 7 ++++++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift index 92ded2fdf..a3aa45a17 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift @@ -20,7 +20,9 @@ struct ListingViewModel: Identifiable { return listing.description } - var url: String { - return listing.homepage + var appDomain: String? { + // TODO: Remove after gm release + let url = listing.homepage == "https://notify.gm.walletconnect.com" ? "https://dev.gm.walletconnect.com" : listing.homepage + return URL(string: url)?.host } } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift index 7d821354d..d2fdd1ab8 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift @@ -31,8 +31,8 @@ final class NotificationsInteractor { } } - func subscribe(url: String) async throws { - try await Notify.instance.subscribe(appDomain: url, account: importAccount.account) + func subscribe(domain: String) async throws { + try await Notify.instance.subscribe(appDomain: domain, account: importAccount.account) } func unsubscribe(topic: String) async throws { diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift index 4f2c18fb6..ba525f5bf 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift @@ -23,11 +23,13 @@ final class NotificationsPresenter: ObservableObject { } func subscription(forListing listing: ListingViewModel) -> SubscriptionsViewModel? { - return subscriptions.first(where: { $0.url == listing.url }) + return subscriptions.first(where: { $0.url == listing.appDomain }) } func subscribe(listing: ListingViewModel) async throws { - try await interactor.subscribe(url: listing.url) + if let domain = listing.appDomain { + try await interactor.subscribe(domain: domain) + } } func unsubscribe(subscription: SubscriptionsViewModel) async throws { diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift index eaba97801..66de2b936 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift @@ -40,7 +40,8 @@ struct NotificationsView: View { } else { discover() } - }.task { + } + .task { try! await presenter.fetch() } } @@ -62,6 +63,8 @@ struct NotificationsView: View { ZStack { if presenter.subscriptions.isEmpty { VStack(spacing: 10) { + Spacer() + Image(systemName: "bell.badge.fill") .resizable() .frame(width: 32, height: 32) @@ -73,6 +76,8 @@ struct NotificationsView: View { .font(.system(size: 15, weight: .regular, design: .rounded)) .multilineTextAlignment(.center) .lineSpacing(4) + + Spacer() } .padding(20) } From 1b0c174f9c442a2cd2f14b55804f4d31af0f90fb Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 15 Sep 2023 10:11:52 +0200 Subject: [PATCH 84/91] switch to notify prod url --- .../NotifyWatchSubscriptionsRequester.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift index c59e037ca..ef37767ac 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyWatchSubscriptions/NotifyWatchSubscriptionsRequester.swift @@ -9,7 +9,7 @@ class NotifyWatchSubscriptionsRequester { private let kms: KeyManagementService private let logger: ConsoleLogging private let webDidResolver: NotifyWebDidResolver - private let notifyServerUrl = "dev.notify.walletconnect.com" + private let notifyServerUrl = "notify.walletconnect.com" private var account: Account? private var publishers = Set() From 4f7039ae5a93197370027433a5e7a6e3d5e50e97 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 15 Sep 2023 10:57:25 +0200 Subject: [PATCH 85/91] switch to prod gm in test --- Example/IntegrationTests/Push/NotifyTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index cd8f80557..83b91e47e 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -16,7 +16,7 @@ final class NotifyTests: XCTestCase { var walletNotifyClientA: NotifyClient! - let gmDappDomain = "dev.gm.walletconnect.com" + let gmDappDomain = "gm.walletconnect.com" let pk = try! EthereumPrivateKey() From e0887ef22fc321db1a80bc856f3aea105ee20e98 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 18 Sep 2023 12:42:30 +0300 Subject: [PATCH 86/91] enable more tests in notify tests plan --- NotifyTests.xctestplan | 5 +++++ Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/NotifyTests.xctestplan b/NotifyTests.xctestplan index fc50c4a84..d626fa6e0 100644 --- a/NotifyTests.xctestplan +++ b/NotifyTests.xctestplan @@ -41,6 +41,11 @@ "testTargets" : [ { "selectedTests" : [ + "NotifyTests\/testNotifyServerSubscribeAndNotifies()", + "NotifyTests\/testNotifySubscriptionChanged()", + "NotifyTests\/testNotifyWatchSubscriptions()", + "NotifyTests\/testWalletCreatesAndUpdatesSubscription()", + "NotifyTests\/testWalletCreatesSubscription()", "PushTests\/testNotifyServerSubscribeAndNotifies()", "PushTests\/testWalletCreatesAndUpdatesSubscription()" ], diff --git a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift index c67d99178..427ba04e0 100644 --- a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift +++ b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientProxy.swift @@ -25,8 +25,6 @@ final class NotifyClientProxy { try await respond(request: request) case .subscribe: let params = try parse(SubscribeRequest.self, params: request.params) - // TODO: Remove after - let appDomain = params.appDomain == "notify.gm.walletconnect.com" ? "dev.gm.walletconnect.com" : params.appDomain try await client.subscribe(appDomain: appDomain, account: params.account) try await respond(request: request) case .getActiveSubscriptions: @@ -46,8 +44,6 @@ final class NotifyClientProxy { try await respond(request: request) case .register: let params = try parse(RegisterRequest.self, params: request.params) - // TODO: Remove after - let appDomain = params.domain == "notify.gm.walletconnect.com" ? "dev.gm.walletconnect.com" : params.domain try await client.register(account: params.account, domain: params.domain, isLimited: params.isLimited, onSign: onSign) try await respond(request: request) } From 25869f582e47414272d3beced5bea7414ee5f10f Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 18 Sep 2023 13:04:50 +0300 Subject: [PATCH 87/91] remove hack from listing view model --- .../Wallet/Notifications/Models/ListingViewModel.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift index a3aa45a17..7ae7ead37 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/ListingViewModel.swift @@ -21,8 +21,7 @@ struct ListingViewModel: Identifiable { } var appDomain: String? { - // TODO: Remove after gm release - let url = listing.homepage == "https://notify.gm.walletconnect.com" ? "https://dev.gm.walletconnect.com" : listing.homepage + let url = listing.homepage return URL(string: url)?.host } } From 698d7e04dddb12b4fe88e6dd08dbd83836342c1c Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 18 Sep 2023 15:02:53 +0300 Subject: [PATCH 88/91] disable chat tests --- .../xcshareddata/xcschemes/WalletConnect.xcscheme | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnect.xcscheme b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnect.xcscheme index 4f51ebe1b..351e9f253 100644 --- a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnect.xcscheme +++ b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnect.xcscheme @@ -147,11 +147,11 @@ + buildForTesting = "NO" + buildForRunning = "NO" + buildForProfiling = "NO" + buildForArchiving = "NO" + buildForAnalyzing = "NO"> Date: Mon, 18 Sep 2023 15:04:37 +0300 Subject: [PATCH 89/91] comment them out --- Tests/ChatTests/RegistryServiceTests.swift | 66 +++++++++++----------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/Tests/ChatTests/RegistryServiceTests.swift b/Tests/ChatTests/RegistryServiceTests.swift index 24d2c657e..8f6cb51b7 100644 --- a/Tests/ChatTests/RegistryServiceTests.swift +++ b/Tests/ChatTests/RegistryServiceTests.swift @@ -43,39 +43,39 @@ final class RegistryServiceTests: XCTestCase { resubscriptionService = ResubscriptionService(networkingInteractor: networkingInteractor, kms: kms, logger: ConsoleLoggerMock()) } - func testRegister() async throws { - let pubKey = try await identityClient.register(account: account, onSign: onSign) - - XCTAssertTrue(networkService.callRegisterIdentity) - - let identityKey = try identityStorage.getIdentityKey(for: account) - XCTAssertEqual(identityKey.publicKey.hexRepresentation, pubKey) - } - - func testGoPublic() async throws { - XCTAssertTrue(networkingInteractor.subscriptions.isEmpty) - - _ = try await identityClient.register(account: account, onSign: onSign) - let inviteKey = try await identityClient.goPublic(account: account) - try await resubscriptionService.subscribeForInvites(inviteKey: inviteKey) - - XCTAssertNoThrow(try identityStorage.getInviteKey(for: account)) - XCTAssertTrue(networkService.callRegisterInvite) - - XCTAssertEqual(networkingInteractor.subscriptions.count, 1) - XCTAssertNotNil(kms.getPublicKey(for: networkingInteractor.subscriptions[0])) - } - - func testUnregister() async throws { - XCTAssertThrowsError(try identityStorage.getIdentityKey(for: account)) - - _ = try await identityClient.register(account: account, onSign: onSign) - XCTAssertNoThrow(try identityStorage.getIdentityKey(for: account)) - - try await identityClient.unregister(account: account, onSign: onSign) - XCTAssertThrowsError(try identityStorage.getIdentityKey(for: account)) - XCTAssertTrue(networkService.callRemoveIdentity) - } +// func testRegister() async throws { +// let pubKey = try await identityClient.register(account: account, onSign: onSign) +// +// XCTAssertTrue(networkService.callRegisterIdentity) +// +// let identityKey = try identityStorage.getIdentityKey(for: account) +// XCTAssertEqual(identityKey.publicKey.hexRepresentation, pubKey) +// } + +// func testGoPublic() async throws { +// XCTAssertTrue(networkingInteractor.subscriptions.isEmpty) +// +// _ = try await identityClient.register(account: account, onSign: onSign) +// let inviteKey = try await identityClient.goPublic(account: account) +// try await resubscriptionService.subscribeForInvites(inviteKey: inviteKey) +// +// XCTAssertNoThrow(try identityStorage.getInviteKey(for: account)) +// XCTAssertTrue(networkService.callRegisterInvite) +// +// XCTAssertEqual(networkingInteractor.subscriptions.count, 1) +// XCTAssertNotNil(kms.getPublicKey(for: networkingInteractor.subscriptions[0])) +// } + +// func testUnregister() async throws { +// XCTAssertThrowsError(try identityStorage.getIdentityKey(for: account)) +// +// _ = try await identityClient.register(account: account, onSign: onSign) +// XCTAssertNoThrow(try identityStorage.getIdentityKey(for: account)) +// +// try await identityClient.unregister(account: account, onSign: onSign) +// XCTAssertThrowsError(try identityStorage.getIdentityKey(for: account)) +// XCTAssertTrue(networkService.callRemoveIdentity) +// } func testGoPrivate() async throws { let invitePubKey = try AgreementPublicKey(hex: inviteKeyStub) From 01b0dfe58524040cb71792739cd843898755761d Mon Sep 17 00:00:00 2001 From: llbartekll Date: Mon, 18 Sep 2023 12:24:26 +0000 Subject: [PATCH 90/91] 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 e32e2e114..594e69a66 100644 --- a/Sources/WalletConnectRelay/PackageConfig.json +++ b/Sources/WalletConnectRelay/PackageConfig.json @@ -1 +1 @@ -{"version": "1.7.2"} +{"version": "1.8.0"} From f5e2ac84d84c93e61b497a371fb43bcbaa47be43 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 18 Sep 2023 18:02:36 +0800 Subject: [PATCH 91/91] Echo renamed --- WalletConnectSwiftV2.podspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WalletConnectSwiftV2.podspec b/WalletConnectSwiftV2.podspec index c2f80eb8f..cc6ab4f3d 100644 --- a/WalletConnectSwiftV2.podspec +++ b/WalletConnectSwiftV2.podspec @@ -78,7 +78,7 @@ Pod::Spec.new do |spec| ss.source_files = 'Sources/Web3Wallet/**/*.{h,m,swift}' ss.dependency 'WalletConnectSwiftV2/WalletConnectSign' ss.dependency 'WalletConnectSwiftV2/WalletConnectAuth' - ss.dependency 'WalletConnectSwiftV2/WalletConnectEcho' + ss.dependency 'WalletConnectSwiftV2/WalletConnectPush' ss.dependency 'WalletConnectSwiftV2/WalletConnectVerify' end @@ -130,8 +130,8 @@ Pod::Spec.new do |spec| ss.dependency 'WalletConnectSwiftV2/WalletConnectJWT' end - spec.subspec 'WalletConnectEcho' do |ss| - ss.source_files = 'Sources/WalletConnectEcho/**/*.{h,m,swift}' + spec.subspec 'WalletConnectPush' do |ss| + ss.source_files = 'Sources/WalletConnectPush/**/*.{h,m,swift}' ss.dependency 'WalletConnectSwiftV2/WalletConnectNetworking' ss.dependency 'WalletConnectSwiftV2/WalletConnectJWT' end