Skip to content

Commit

Permalink
Merge pull request #1256 from WalletConnect/feature/update-subscripti…
Browse files Browse the repository at this point in the history
…ons-on-responses

[Notify] Subscriptions Updater
  • Loading branch information
flypaper0 committed Jan 29, 2024
2 parents 678fa51 + abaa83d commit 452314f
Show file tree
Hide file tree
Showing 13 changed files with 200 additions and 178 deletions.
16 changes: 11 additions & 5 deletions Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class NotifyClient {
return logger.logsPublisher
}

private let deleteNotifySubscriptionRequester: DeleteNotifySubscriptionRequester
private let notifyDeleteSubscriptionRequester: NotifyDeleteSubscriptionRequester
private let notifySubscribeRequester: NotifySubscribeRequester

public let logger: ConsoleLogging
Expand All @@ -31,12 +31,14 @@ public class NotifyClient {
private let notifyMessageSubscriber: NotifyMessageSubscriber
private let resubscribeService: NotifyResubscribeService
private let notifySubscribeResponseSubscriber: NotifySubscribeResponseSubscriber
private let notifyDeleteSubscriptionSubscriber: NotifyDeleteSubscriptionSubscriber
private let notifyUpdateRequester: NotifyUpdateRequester
private let notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber
private let subscriptionsAutoUpdater: SubscriptionsAutoUpdater
private let notifyWatchSubscriptionsResponseSubscriber: NotifyWatchSubscriptionsResponseSubscriber
private let notifyWatcherAgreementKeysProvider: NotifyWatcherAgreementKeysProvider
private let notifySubscriptionsChangedRequestSubscriber: NotifySubscriptionsChangedRequestSubscriber
private let notifySubscriptionsUpdater: NotifySubsctiptionsUpdater
private let subscriptionWatcher: SubscriptionWatcher

init(logger: ConsoleLogging,
Expand All @@ -47,17 +49,19 @@ public class NotifyClient {
pushClient: PushClient,
notifyMessageSubscriber: NotifyMessageSubscriber,
notifyStorage: NotifyStorage,
deleteNotifySubscriptionRequester: DeleteNotifySubscriptionRequester,
notifyDeleteSubscriptionRequester: NotifyDeleteSubscriptionRequester,
resubscribeService: NotifyResubscribeService,
notifySubscribeRequester: NotifySubscribeRequester,
notifySubscribeResponseSubscriber: NotifySubscribeResponseSubscriber,
notifyDeleteSubscriptionSubscriber: NotifyDeleteSubscriptionSubscriber,
notifyUpdateRequester: NotifyUpdateRequester,
notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber,
notifyAccountProvider: NotifyAccountProvider,
subscriptionsAutoUpdater: SubscriptionsAutoUpdater,
notifyWatchSubscriptionsResponseSubscriber: NotifyWatchSubscriptionsResponseSubscriber,
notifyWatcherAgreementKeysProvider: NotifyWatcherAgreementKeysProvider,
notifySubscriptionsChangedRequestSubscriber: NotifySubscriptionsChangedRequestSubscriber,
notifySubscriptionsUpdater: NotifySubsctiptionsUpdater,
subscriptionWatcher: SubscriptionWatcher
) {
self.logger = logger
Expand All @@ -67,17 +71,19 @@ public class NotifyClient {
self.historyService = historyService
self.notifyMessageSubscriber = notifyMessageSubscriber
self.notifyStorage = notifyStorage
self.deleteNotifySubscriptionRequester = deleteNotifySubscriptionRequester
self.notifyDeleteSubscriptionRequester = notifyDeleteSubscriptionRequester
self.resubscribeService = resubscribeService
self.notifySubscribeRequester = notifySubscribeRequester
self.notifySubscribeResponseSubscriber = notifySubscribeResponseSubscriber
self.notifyDeleteSubscriptionSubscriber = notifyDeleteSubscriptionSubscriber
self.notifyUpdateRequester = notifyUpdateRequester
self.notifyUpdateResponseSubscriber = notifyUpdateResponseSubscriber
self.notifyAccountProvider = notifyAccountProvider
self.subscriptionsAutoUpdater = subscriptionsAutoUpdater
self.notifyWatchSubscriptionsResponseSubscriber = notifyWatchSubscriptionsResponseSubscriber
self.notifyWatcherAgreementKeysProvider = notifyWatcherAgreementKeysProvider
self.notifySubscriptionsChangedRequestSubscriber = notifySubscriptionsChangedRequestSubscriber
self.notifySubscriptionsUpdater = notifySubscriptionsUpdater
self.subscriptionWatcher = subscriptionWatcher
}

Expand Down Expand Up @@ -125,7 +131,7 @@ public class NotifyClient {
}

public func deleteSubscription(topic: String) async throws {
try await deleteNotifySubscriptionRequester.delete(topic: topic)
try await notifyDeleteSubscriptionRequester.delete(topic: topic)
}

public func deleteNotifyMessage(id: String) {
Expand Down Expand Up @@ -184,7 +190,7 @@ private extension NotifyClient {
extension NotifyClient {

public var subscriptionChangedPublisher: AnyPublisher<[NotifySubscription], Never> {
return notifySubscriptionsChangedRequestSubscriber.subscriptionChangedPublisher
return notifySubscriptionsUpdater.subscriptionChangedPublisher
}

public func register(deviceToken: String) async throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,28 +45,32 @@ 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 = NotifyWebDidResolver()
let deleteNotifySubscriptionRequester = DeleteNotifySubscriptionRequester(keyserver: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, kms: kms, logger: logger, notifyStorage: notifyStorage)
let notifyDeleteSubscriptionRequester = NotifyDeleteSubscriptionRequester(keyserver: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, notifyStorage: notifyStorage)
let resubscribeService = NotifyResubscribeService(networkInteractor: networkInteractor, notifyStorage: notifyStorage, logger: logger)

let notifyConfigProvider = NotifyConfigProvider(projectId: projectId, explorerHost: explorerHost)

let notifySubscribeRequester = NotifySubscribeRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, kms: kms, webDidResolver: webDidResolver, notifyConfigProvider: notifyConfigProvider)

let notifySubscribeResponseSubscriber = NotifySubscribeResponseSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, groupKeychainStorage: groupKeychainStorage, notifyStorage: notifyStorage, notifyConfigProvider: notifyConfigProvider)
let notifySubscriptionsUpdater = NotifySubsctiptionsUpdater(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifyStorage: notifyStorage, groupKeychainStorage: groupKeychainStorage)

let notifySubscriptionsBuilder = NotifySubscriptionsBuilder(notifyConfigProvider: notifyConfigProvider)

let notifySubscribeResponseSubscriber = NotifySubscribeResponseSubscriber(networkingInteractor: networkInteractor, logger: logger, notifySubscriptionsBuilder: notifySubscriptionsBuilder, notifySubscriptionsUpdater: notifySubscriptionsUpdater)

let notifyUpdateRequester = NotifyUpdateRequester(keyserverURL: keyserverURL, identityClient: identityClient, networkingInteractor: networkInteractor, notifyConfigProvider: notifyConfigProvider, logger: logger, notifyStorage: notifyStorage)

let notifyUpdateResponseSubscriber = NotifyUpdateResponseSubscriber(networkingInteractor: networkInteractor, logger: logger, notifyConfigProvider: notifyConfigProvider, notifyStorage: notifyStorage)
let notifyUpdateResponseSubscriber = NotifyUpdateResponseSubscriber(networkingInteractor: networkInteractor, logger: logger, notifySubscriptionsBuilder: notifySubscriptionsBuilder, notifySubscriptionsUpdater: notifySubscriptionsUpdater)

let subscriptionsAutoUpdater = SubscriptionsAutoUpdater(notifyUpdateRequester: notifyUpdateRequester, logger: logger, notifyStorage: notifyStorage)

let notifyWatcherAgreementKeysProvider = NotifyWatcherAgreementKeysProvider(kms: kms)
let notifyWatchSubscriptionsRequester = NotifyWatchSubscriptionsRequester(keyserverURL: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, webDidResolver: webDidResolver, notifyAccountProvider: notifyAccountProvider, notifyWatcherAgreementKeysProvider: notifyWatcherAgreementKeysProvider, notifyHost: notifyHost)
let notifySubscriptionsBuilder = NotifySubscriptionsBuilder(notifyConfigProvider: notifyConfigProvider)
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 notifyWatchSubscriptionsResponseSubscriber = NotifyWatchSubscriptionsResponseSubscriber(networkingInteractor: networkInteractor, logger: logger, notifySubscriptionsBuilder: notifySubscriptionsBuilder, notifySubscriptionsUpdater: notifySubscriptionsUpdater)
let notifySubscriptionsChangedRequestSubscriber = NotifySubscriptionsChangedRequestSubscriber(keyserver: keyserverURL, networkingInteractor: networkInteractor, identityClient: identityClient, logger: logger, notifySubscriptionsUpdater: notifySubscriptionsUpdater, notifySubscriptionsBuilder: notifySubscriptionsBuilder)
let subscriptionWatcher = SubscriptionWatcher(notifyWatchSubscriptionsRequester: notifyWatchSubscriptionsRequester, logger: logger)
let historyService = HistoryService(keyserver: keyserverURL, networkingClient: networkInteractor, identityClient: identityClient)
let notifyDeleteSubscriptionSubscriber = NotifyDeleteSubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, notifySubscriptionsBuilder: notifySubscriptionsBuilder, notifySubscriptionsUpdater: notifySubscriptionsUpdater)

return NotifyClient(
logger: logger,
Expand All @@ -77,17 +81,19 @@ public struct NotifyClientFactory {
pushClient: pushClient,
notifyMessageSubscriber: notifyMessageSubscriber,
notifyStorage: notifyStorage,
deleteNotifySubscriptionRequester: deleteNotifySubscriptionRequester,
notifyDeleteSubscriptionRequester: notifyDeleteSubscriptionRequester,
resubscribeService: resubscribeService,
notifySubscribeRequester: notifySubscribeRequester,
notifySubscribeResponseSubscriber: notifySubscribeResponseSubscriber,
notifySubscribeResponseSubscriber: notifySubscribeResponseSubscriber,
notifyDeleteSubscriptionSubscriber: notifyDeleteSubscriptionSubscriber,
notifyUpdateRequester: notifyUpdateRequester,
notifyUpdateResponseSubscriber: notifyUpdateResponseSubscriber,
notifyAccountProvider: notifyAccountProvider,
subscriptionsAutoUpdater: subscriptionsAutoUpdater,
notifyWatchSubscriptionsResponseSubscriber: notifyWatchSubscriptionsResponseSubscriber,
notifyWatcherAgreementKeysProvider: notifyWatcherAgreementKeysProvider,
notifySubscriptionsChangedRequestSubscriber: notifySubscriptionsChangedRequestSubscriber,
notifySubscriptionsChangedRequestSubscriber: notifySubscriptionsChangedRequestSubscriber,
notifySubscriptionsUpdater: notifySubscriptionsUpdater,
subscriptionWatcher: subscriptionWatcher
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Foundation
import Combine

final class NotifySubsctiptionsUpdater {
private let networkingInteractor: NetworkInteracting
private let kms: KeyManagementServiceProtocol
private let logger: ConsoleLogging
private let notifyStorage: NotifyStorage
private let groupKeychainStorage: KeychainStorageProtocol

private let subscriptionChangedSubject = PassthroughSubject<[NotifySubscription], Never>()

var subscriptionChangedPublisher: AnyPublisher<[NotifySubscription], Never> {
return subscriptionChangedSubject.eraseToAnyPublisher()
}

init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, logger: ConsoleLogging, notifyStorage: NotifyStorage, groupKeychainStorage: KeychainStorageProtocol) {
self.networkingInteractor = networkingInteractor
self.kms = kms
self.logger = logger
self.notifyStorage = notifyStorage
self.groupKeychainStorage = groupKeychainStorage
}

func update(subscriptions newSubscriptions: [NotifySubscription], for account: Account) async throws {
let oldSubscriptions = notifyStorage.getSubscriptions(account: account)

subscriptionChangedSubject.send(newSubscriptions)

try Task.checkCancellation()

let subscriptions = oldSubscriptions.difference(from: newSubscriptions)

logger.debug("Received: \(newSubscriptions.count), changed: \(subscriptions.count)")

if subscriptions.count > 0 {
try notifyStorage.replaceAllSubscriptions(newSubscriptions)

for subscription in newSubscriptions {
let symKey = try SymmetricKey(hex: subscription.symKey)
try groupKeychainStorage.add(symKey, forKey: subscription.topic)
try kms.setSymmetricKey(symKey, for: subscription.topic)
}

let topicsToSubscribe = newSubscriptions.map { $0.topic }

let oldTopics = Set(oldSubscriptions.map { $0.topic })
let topicsToUnsubscribe = Array(oldTopics.subtracting(topicsToSubscribe))

try await networkingInteractor.batchUnsubscribe(topics: topicsToUnsubscribe)
try await networkingInteractor.batchSubscribe(topics: topicsToSubscribe)

try Task.checkCancellation()

logger.debug("Updated Subscriptions by Subscriptions Changed Request", properties: [
"topics": newSubscriptions.map { $0.topic }.joined(separator: ",")
])
}
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
import Foundation

class DeleteNotifySubscriptionRequester {
class NotifyDeleteSubscriptionRequester {
enum Errors: Error {
case notifySubscriptionNotFound
}
private let keyserver: URL
private let networkingInteractor: NetworkInteracting
private let identityClient: IdentityClient
private let kms: KeyManagementServiceProtocol
private let logger: ConsoleLogging
private let notifyStorage: NotifyStorage

init(
keyserver: URL,
networkingInteractor: NetworkInteracting,
identityClient: IdentityClient,
kms: KeyManagementServiceProtocol,
logger: ConsoleLogging,
notifyStorage: NotifyStorage
) {
self.keyserver = keyserver
self.networkingInteractor = networkingInteractor
self.identityClient = identityClient
self.kms = kms
self.logger = logger
self.notifyStorage = notifyStorage
}
Expand All @@ -49,15 +46,11 @@ class DeleteNotifySubscriptionRequester {
try notifyStorage.deleteSubscription(topic: topic)
try notifyStorage.deleteMessages(topic: topic)

networkingInteractor.unsubscribe(topic: topic)

logger.debug("Subscription removed, topic: \(topic)")

kms.deleteSymmetricKey(for: topic)
logger.debug("Subscription delete request sent, topic: \(topic)")
}
}

private extension DeleteNotifySubscriptionRequester {
private extension NotifyDeleteSubscriptionRequester {

func createJWTWrapper(dappPubKey: DIDKey, reason: String, app: DIDWeb, account: Account) throws -> NotifyDeletePayload.Wrapper {
let jwtPayload = NotifyDeletePayload(account: account, keyserver: keyserver, dappPubKey: dappPubKey, app: app)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Foundation
import Combine

class NotifyDeleteSubscriptionSubscriber {

private let networkingInteractor: NetworkInteracting
private let kms: KeyManagementServiceProtocol
private let logger: ConsoleLogging
private let notifySubscriptionsBuilder: NotifySubscriptionsBuilder
private let notifySubscriptionsUpdater: NotifySubsctiptionsUpdater

init(
networkingInteractor: NetworkInteracting,
kms: KeyManagementServiceProtocol,
logger: ConsoleLogging,
notifySubscriptionsBuilder: NotifySubscriptionsBuilder,
notifySubscriptionsUpdater: NotifySubsctiptionsUpdater
) {
self.networkingInteractor = networkingInteractor
self.kms = kms
self.logger = logger
self.notifySubscriptionsBuilder = notifySubscriptionsBuilder
self.notifySubscriptionsUpdater = notifySubscriptionsUpdater

subscribeForDeleteResponse()
}
}

private extension NotifyDeleteSubscriptionSubscriber {

func subscribeForDeleteResponse() {
networkingInteractor.subscribeOnResponse(
protocolMethod: NotifyDeleteProtocolMethod(),
requestOfType: NotifyDeletePayload.Wrapper.self,
responseOfType: NotifyDeleteResponsePayload.Wrapper.self,
errorHandler: logger
) { [unowned self] payload in

let (responsePayload, _) = try NotifyDeleteResponsePayload.decodeAndVerify(from: payload.response)

let subscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(responsePayload.subscriptions)

try await notifySubscriptionsUpdater.update(subscriptions: subscriptions, for: responsePayload.account)

logger.debug("Received Notify Delete response")

networkingInteractor.unsubscribe(topic: payload.topic)
kms.deleteSymmetricKey(for: payload.topic)
}
}
}
Loading

0 comments on commit 452314f

Please sign in to comment.