diff --git a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectPush.xcscheme b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectPush.xcscheme
index 48c7aad62..c779cb9d1 100644
--- a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectPush.xcscheme
+++ b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectPush.xcscheme
@@ -20,6 +20,20 @@
ReferencedContainer = "container:..">
+
+
+
+
+
+
+
+
) async throws
+}
+
+class NotifyUpdateRequester: NotifyUpdateRequesting {
enum Errors: Error {
case noSubscriptionForGivenTopic
}
diff --git a/Sources/WalletConnectPush/Client/Wallet/PushStorage.swift b/Sources/WalletConnectPush/Client/Wallet/PushStorage.swift
index 8393c734f..091b390ec 100644
--- a/Sources/WalletConnectPush/Client/Wallet/PushStorage.swift
+++ b/Sources/WalletConnectPush/Client/Wallet/PushStorage.swift
@@ -1,7 +1,14 @@
import Foundation
import Combine
-final class PushStorage {
+protocol PushStoring {
+ func getSubscriptions() -> [PushSubscription]
+ func getSubscription(topic: String) -> PushSubscription?
+ func setSubscription(_ subscription: PushSubscription) async throws
+ func deleteSubscription(topic: String) async throws
+}
+
+final class PushStorage: PushStoring {
private var publishers = Set()
diff --git a/Sources/WalletConnectPush/Client/Wallet/SubscriptionsAutoUpdater.swift b/Sources/WalletConnectPush/Client/Wallet/SubscriptionsAutoUpdater.swift
new file mode 100644
index 000000000..d6e939a5b
--- /dev/null
+++ b/Sources/WalletConnectPush/Client/Wallet/SubscriptionsAutoUpdater.swift
@@ -0,0 +1,46 @@
+
+import Foundation
+
+class SubscriptionsAutoUpdater {
+ private let notifyUpdateRequester: NotifyUpdateRequesting
+ private let logger: ConsoleLogging
+ private let pushStorage: PushStoring
+
+ init(notifyUpdateRequester: NotifyUpdateRequesting,
+ logger: ConsoleLogging,
+ pushStorage: PushStoring) {
+ self.notifyUpdateRequester = notifyUpdateRequester
+ self.logger = logger
+ self.pushStorage = pushStorage
+ updateSubscriptionsIfNeeded()
+ }
+
+ private func updateSubscriptionsIfNeeded() {
+ for subscription in pushStorage.getSubscriptions() {
+ if shouldUpdate(subscription: subscription) {
+ let scope = Set(subscription.scope.filter{ $0.value.enabled == true }.keys)
+ let topic = subscription.topic
+ Task {
+ do {
+ try await notifyUpdateRequester.update(topic: topic, scope: scope)
+ } catch {
+ logger.error("Failed to update subscription for topic: \(topic)")
+ }
+ }
+ }
+ }
+ }
+
+ private func shouldUpdate(subscription: PushSubscription) -> Bool {
+ let currentDate = Date()
+ let calendar = Calendar.current
+ let expiryDate = subscription.expiry
+ let dateComponents = calendar.dateComponents([.day], from: currentDate, to: expiryDate)
+ if let numberOfDays = dateComponents.day,
+ numberOfDays < 14 {
+ return true
+ } else {
+ return false
+ }
+ }
+}
diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift
index ee6b5c6ca..0e41dbdd2 100644
--- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift
+++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift
@@ -52,6 +52,7 @@ public class WalletPushClient {
private let notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber
private let notifyProposeResponder: NotifyProposeResponder
private let notifyProposeSubscriber: NotifyProposeSubscriber
+ private let subscriptionsAutoUpdater: SubscriptionsAutoUpdater
init(logger: ConsoleLogging,
kms: KeyManagementServiceProtocol,
@@ -68,7 +69,8 @@ public class WalletPushClient {
notifyUpdateRequester: NotifyUpdateRequester,
notifyUpdateResponseSubscriber: NotifyUpdateResponseSubscriber,
notifyProposeResponder: NotifyProposeResponder,
- notifyProposeSubscriber: NotifyProposeSubscriber
+ notifyProposeSubscriber: NotifyProposeSubscriber,
+ subscriptionsAutoUpdater: SubscriptionsAutoUpdater
) {
self.logger = logger
self.echoClient = echoClient
@@ -85,6 +87,7 @@ public class WalletPushClient {
self.notifyUpdateResponseSubscriber = notifyUpdateResponseSubscriber
self.notifyProposeResponder = notifyProposeResponder
self.notifyProposeSubscriber = notifyProposeSubscriber
+ self.subscriptionsAutoUpdater = subscriptionsAutoUpdater
}
public func enableSync(account: Account, onSign: @escaping SigningCallback) async throws {
diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift
index f57d7b7ef..f65c4928b 100644
--- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift
+++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift
@@ -62,6 +62,8 @@ public struct WalletPushClientFactory {
let deletePushSubscriptionSubscriber = DeletePushSubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushStorage: pushStorage)
+ let subscriptionsAutoUpdater = SubscriptionsAutoUpdater(notifyUpdateRequester: notifyUpdateRequester, logger: logger, pushStorage: pushStorage)
+
return WalletPushClient(
logger: logger,
kms: kms,
@@ -78,7 +80,8 @@ public struct WalletPushClientFactory {
notifyUpdateRequester: notifyUpdateRequester,
notifyUpdateResponseSubscriber: notifyUpdateResponseSubscriber,
notifyProposeResponder: notifyProposeResponder,
- notifyProposeSubscriber: notifyProposeSubscriber
+ notifyProposeSubscriber: notifyProposeSubscriber,
+ subscriptionsAutoUpdater: subscriptionsAutoUpdater
)
}
}
diff --git a/Tests/NotifyTests/Mocks/MockNotifyUpdateRequester.swift b/Tests/NotifyTests/Mocks/MockNotifyUpdateRequester.swift
new file mode 100644
index 000000000..8f4d698e1
--- /dev/null
+++ b/Tests/NotifyTests/Mocks/MockNotifyUpdateRequester.swift
@@ -0,0 +1,15 @@
+
+import Foundation
+@testable import WalletConnectPush
+
+
+class MockNotifyUpdateRequester: NotifyUpdateRequesting {
+ var updatedTopics: [String] = []
+ var completionHandler: (() -> Void)?
+
+ func update(topic: String, scope: Set) async throws {
+ updatedTopics.append(topic)
+ completionHandler?()
+ }
+}
+
diff --git a/Tests/NotifyTests/Mocks/MockPushStoring.swift b/Tests/NotifyTests/Mocks/MockPushStoring.swift
new file mode 100644
index 000000000..06dc07960
--- /dev/null
+++ b/Tests/NotifyTests/Mocks/MockPushStoring.swift
@@ -0,0 +1,31 @@
+
+import Foundation
+@testable import WalletConnectPush
+
+class MockPushStoring: PushStoring {
+ var subscriptions: [PushSubscription]
+
+ init(subscriptions: [PushSubscription]) {
+ self.subscriptions = subscriptions
+ }
+
+ func getSubscriptions() -> [PushSubscription] {
+ return subscriptions
+ }
+
+ func getSubscription(topic: String) -> PushSubscription? {
+ return subscriptions.first { $0.topic == topic }
+ }
+
+ func setSubscription(_ subscription: PushSubscription) async throws {
+ if let index = subscriptions.firstIndex(where: { $0.topic == subscription.topic }) {
+ subscriptions[index] = subscription
+ } else {
+ subscriptions.append(subscription)
+ }
+ }
+
+ func deleteSubscription(topic: String) async throws {
+ subscriptions.removeAll(where: { $0.topic == topic })
+ }
+}
diff --git a/Tests/NotifyTests/Stubs/PushSubscription.swift b/Tests/NotifyTests/Stubs/PushSubscription.swift
new file mode 100644
index 000000000..de40c5772
--- /dev/null
+++ b/Tests/NotifyTests/Stubs/PushSubscription.swift
@@ -0,0 +1,23 @@
+
+import Foundation
+@testable import WalletConnectPush
+
+extension PushSubscription {
+ static func stub(topic: String, expiry: Date) -> PushSubscription {
+ let account = Account(chainIdentifier: "eip155:1", address: "0x15bca56b6e2728aec2532df9d436bd1600e86688")!
+ let relay = RelayProtocolOptions.stub()
+ let metadata = AppMetadata.stub()
+ let symKey = "key1"
+
+ return PushSubscription(
+ topic: topic,
+ account: account,
+ relay: relay,
+ metadata: metadata,
+ scope: ["test": ScopeValue(description: "desc", enabled: true)],
+ expiry: expiry,
+ symKey: symKey
+ )
+ }
+}
+
diff --git a/Tests/NotifyTests/SubscriptionsAutoUpdaterTests.swift b/Tests/NotifyTests/SubscriptionsAutoUpdaterTests.swift
new file mode 100644
index 000000000..60f0c09c3
--- /dev/null
+++ b/Tests/NotifyTests/SubscriptionsAutoUpdaterTests.swift
@@ -0,0 +1,36 @@
+import Foundation
+import XCTest
+import TestingUtils
+@testable import WalletConnectPush
+
+class SubscriptionsAutoUpdaterTests: XCTestCase {
+ var sut: SubscriptionsAutoUpdater!
+
+ func testUpdateSubscriptionsIfNeeded() async {
+ let subscriptions: [PushSubscription] = [
+ PushSubscription.stub(topic: "topic1", expiry: Date().addingTimeInterval(60 * 60 * 24 * 20)),
+ PushSubscription.stub(topic: "topic2", expiry: Date().addingTimeInterval(60 * 60 * 24 * 10)),
+ PushSubscription.stub(topic: "topic3", expiry: Date().addingTimeInterval(60 * 60 * 24 * 30))
+ ]
+
+ let expectation = expectation(description: "update")
+
+ let notifyUpdateRequester = MockNotifyUpdateRequester()
+ let logger = ConsoleLoggerMock()
+ let pushStorage = MockPushStoring(subscriptions: subscriptions)
+
+ notifyUpdateRequester.completionHandler = {
+ if notifyUpdateRequester.updatedTopics.contains("topic2") {
+ expectation.fulfill()
+ }
+ }
+
+ sut = SubscriptionsAutoUpdater(notifyUpdateRequester: notifyUpdateRequester,
+ logger: logger,
+ pushStorage: pushStorage)
+
+ await waitForExpectations(timeout: 1, handler: nil)
+
+ XCTAssertEqual(notifyUpdateRequester.updatedTopics, ["topic2"])
+ }
+}