From c446b7e13c24644f9a3b38e4b2fa66b6daf1e8fc Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 27 Aug 2023 16:37:58 +0100 Subject: [PATCH 01/32] add profiling service --- Example/ExampleApp.xcodeproj/project.pbxproj | 32 +++++++++++++++++-- .../xcshareddata/swiftpm/Package.resolved | 9 ++++++ .../ConfigurationService.swift | 1 + .../Configurator/ThirdPartyConfigurator.swift | 8 ++++- .../ApplicationLayer/ProfilingService.swift | 11 +++++++ 5 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 Example/WalletApp/ApplicationLayer/ProfilingService.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index a0a35346e..f40872c6c 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ @@ -34,11 +34,13 @@ 847BD1E7298A806800076C90 /* NotificationsInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1E2298A806800076C90 /* NotificationsInteractor.swift */; }; 847BD1E8298A806800076C90 /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1E3298A806800076C90 /* NotificationsView.swift */; }; 847BD1EB298A87AB00076C90 /* SubscriptionsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1EA298A87AB00076C90 /* SubscriptionsViewModel.swift */; }; - 847CF3AF28E3141700F1D760 /* WalletConnectPush in Frameworks */ = {isa = PBXBuildFile; productRef = 847CF3AE28E3141700F1D760 /* WalletConnectPush */; settings = {ATTRIBUTES = (Required, ); }; }; 847F08012A25DBFF00B2A5A4 /* XPlatformW3WTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847F08002A25DBFF00B2A5A4 /* XPlatformW3WTests.swift */; }; 8487A9442A836C2A0003D5AF /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 8487A9432A836C2A0003D5AF /* Sentry */; }; 8487A9462A836C3F0003D5AF /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 8487A9452A836C3F0003D5AF /* Sentry */; }; 8487A9482A83AD680003D5AF /* LoggingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8487A9472A83AD680003D5AF /* LoggingService.swift */; }; + 84943C7B2A9BA206007EBAC2 /* Mixpanel in Frameworks */ = {isa = PBXBuildFile; productRef = 84943C7A2A9BA206007EBAC2 /* Mixpanel */; }; + 84943C7D2A9BA328007EBAC2 /* Mixpanel in Frameworks */ = {isa = PBXBuildFile; productRef = 84943C7C2A9BA328007EBAC2 /* Mixpanel */; }; + 84943C7F2A9BA48C007EBAC2 /* ProfilingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84943C7E2A9BA48C007EBAC2 /* ProfilingService.swift */; }; 849D7A93292E2169006A2BD4 /* NotifyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849D7A92292E2169006A2BD4 /* NotifyTests.swift */; }; 84A6E3C32A386BBC008A0571 /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A6E3C22A386BBC008A0571 /* Publisher.swift */; }; 84AA01DB28CF0CD7005D48D8 /* XCTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AA01DA28CF0CD7005D48D8 /* XCTest.swift */; }; @@ -389,6 +391,7 @@ 847F08002A25DBFF00B2A5A4 /* XPlatformW3WTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XPlatformW3WTests.swift; sourceTree = ""; }; 8487A92E2A7BD2F30003D5AF /* XPlatformProtocolTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = XPlatformProtocolTests.xctestplan; path = ../XPlatformProtocolTests.xctestplan; sourceTree = ""; }; 8487A9472A83AD680003D5AF /* LoggingService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingService.swift; sourceTree = ""; }; + 84943C7E2A9BA48C007EBAC2 /* ProfilingService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfilingService.swift; sourceTree = ""; }; 849A4F18298281E300E61ACE /* WalletAppRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WalletAppRelease.entitlements; sourceTree = ""; }; 849A4F19298281F100E61ACE /* PNDecryptionServiceRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PNDecryptionServiceRelease.entitlements; sourceTree = ""; }; 849D7A92292E2169006A2BD4 /* NotifyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyTests.swift; sourceTree = ""; }; @@ -644,6 +647,7 @@ A54195A52934E83F0035AD19 /* Web3 in Frameworks */, 8487A9442A836C2A0003D5AF /* Sentry in Frameworks */, A5D85228286333E300DAF5C3 /* Starscream in Frameworks */, + 84943C7B2A9BA206007EBAC2 /* Mixpanel in Frameworks */, A573C53929EC365000E3CBFD /* HDWalletKit in Frameworks */, A5BB7FA328B6A50400707FC6 /* WalletConnectAuth in Frameworks */, ); @@ -710,6 +714,7 @@ C56EE255293F569A004840D1 /* Starscream in Frameworks */, A5B6C0F52A6EAB2800927332 /* WalletConnectNotify in Frameworks */, C56EE27B293F56F8004840D1 /* WalletConnectAuth in Frameworks */, + 84943C7D2A9BA328007EBAC2 /* Mixpanel in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1669,6 +1674,7 @@ 84DB38F22983CDAE00BFEE37 /* PushRegisterer.swift */, A51811972A52E21A00A52B15 /* ConfigurationService.swift */, 8487A9472A83AD680003D5AF /* LoggingService.swift */, + 84943C7E2A9BA48C007EBAC2 /* ProfilingService.swift */, ); path = ApplicationLayer; sourceTree = ""; @@ -1823,6 +1829,7 @@ CF25F28A2A432488009C7E49 /* WalletConnectModal */, 8487A9432A836C2A0003D5AF /* Sentry */, A5B6C0F02A6EAB0800927332 /* WalletConnectNotify */, + 84943C7A2A9BA206007EBAC2 /* Mixpanel */, ); productName = DApp; productReference = 84CE641C27981DED00142511 /* DApp.app */; @@ -1948,6 +1955,7 @@ A573C53C29EC366500E3CBFD /* HDWalletKit */, 8487A9452A836C3F0003D5AF /* Sentry */, A5B6C0F42A6EAB2800927332 /* WalletConnectNotify */, + 84943C7C2A9BA328007EBAC2 /* Mixpanel */, ); productName = ChatWallet; productReference = C56EE21B293F55ED004840D1 /* WalletApp.app */; @@ -2024,6 +2032,7 @@ A58EC60F299D57B800F3452A /* XCRemoteSwiftPackageReference "swiftui-async-button" */, A561C7FE29DF32CE00DF540D /* XCRemoteSwiftPackageReference "HDWallet" */, 8487A9422A836C2A0003D5AF /* XCRemoteSwiftPackageReference "sentry-cocoa" */, + 84943C792A9BA206007EBAC2 /* XCRemoteSwiftPackageReference "mixpanel-swift" */, ); productRefGroup = 764E1D3D26F8D3FC00A1FB15 /* Products */; projectDirPath = ""; @@ -2374,6 +2383,7 @@ C5B2F6F929705293000DBA0E /* SessionRequestPresenter.swift in Sources */, A57879712A4EDC8100F8D10B /* TextFieldView.swift in Sources */, 84DB38F32983CDAE00BFEE37 /* PushRegisterer.swift in Sources */, + 84943C7F2A9BA48C007EBAC2 /* ProfilingService.swift in Sources */, C5B2F6FB297055B0000DBA0E /* ETHSigner.swift in Sources */, C56EE274293F56D7004840D1 /* SceneViewController.swift in Sources */, 847BD1E5298A806800076C90 /* NotificationsPresenter.swift in Sources */, @@ -3105,6 +3115,14 @@ minimumVersion = 8.0.0; }; }; + 84943C792A9BA206007EBAC2 /* XCRemoteSwiftPackageReference "mixpanel-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/mixpanel/mixpanel-swift"; + requirement = { + branch = master; + kind = branch; + }; + }; A5434021291E6A270068F706 /* XCRemoteSwiftPackageReference "solana-swift" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/flypaper0/solana-swift"; @@ -3175,6 +3193,16 @@ package = 8487A9422A836C2A0003D5AF /* XCRemoteSwiftPackageReference "sentry-cocoa" */; productName = Sentry; }; + 84943C7A2A9BA206007EBAC2 /* Mixpanel */ = { + isa = XCSwiftPackageProductDependency; + package = 84943C792A9BA206007EBAC2 /* XCRemoteSwiftPackageReference "mixpanel-swift" */; + productName = Mixpanel; + }; + 84943C7C2A9BA328007EBAC2 /* Mixpanel */ = { + isa = XCSwiftPackageProductDependency; + package = 84943C792A9BA206007EBAC2 /* XCRemoteSwiftPackageReference "mixpanel-swift" */; + productName = Mixpanel; + }; 84DDB4EC28ABB663003D66ED /* WalletConnectAuth */ = { isa = XCSwiftPackageProductDependency; productName = WalletConnectAuth; diff --git a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d71b949a8..9d6fdc5ce 100644 --- a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -28,6 +28,15 @@ "version": null } }, + { + "package": "Mixpanel", + "repositoryURL": "https://github.com/mixpanel/mixpanel-swift", + "state": { + "branch": "master", + "revision": "1ce27d937009d5ecce74dad97d69898ffea49c75", + "version": null + } + }, { "package": "PromiseKit", "repositoryURL": "https://github.com/mxcl/PromiseKit.git", diff --git a/Example/WalletApp/ApplicationLayer/ConfigurationService.swift b/Example/WalletApp/ApplicationLayer/ConfigurationService.swift index 58054aa20..1f7028f0b 100644 --- a/Example/WalletApp/ApplicationLayer/ConfigurationService.swift +++ b/Example/WalletApp/ApplicationLayer/ConfigurationService.swift @@ -29,6 +29,7 @@ final class ConfigurationService { 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) } LoggingService.instance.startLogging() } diff --git a/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift b/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift index cea617574..b5cbb0b66 100644 --- a/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift +++ b/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift @@ -1,5 +1,6 @@ import Foundation import Sentry +import Mixpanel struct ThirdPartyConfigurator: Configurator { @@ -7,7 +8,7 @@ struct ThirdPartyConfigurator: Configurator { configureLogging() } - func configureLogging() { + private func configureLogging() { guard let sentryDsn = InputConfig.sentryDsn, !sentryDsn.isEmpty else { return } SentrySDK.start { options in options.dsn = "https://\(sentryDsn)" @@ -16,4 +17,9 @@ struct ThirdPartyConfigurator: Configurator { options.tracesSampleRate = 1.0 } } + + private func configureProfiling() { + Mixpanel.initialize(token: "", trackAutomaticEvents: true) + + } } diff --git a/Example/WalletApp/ApplicationLayer/ProfilingService.swift b/Example/WalletApp/ApplicationLayer/ProfilingService.swift new file mode 100644 index 000000000..30616f702 --- /dev/null +++ b/Example/WalletApp/ApplicationLayer/ProfilingService.swift @@ -0,0 +1,11 @@ +import Foundation +import Mixpanel + +final class ProfilingService { + public static var instance = ProfilingService() + + func setUpProfiling(account: String, clientId: String) { + Mixpanel.mainInstance().identify(distinctId: clientId) + Mixpanel.mainInstance().people.set(properties: [ "account": account]) + } +} From 8eef07849de1c49190aff9856dfaf85380cfad89 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 27 Aug 2023 16:52:09 +0100 Subject: [PATCH 02/32] savepoint --- .../Configurator/ThirdPartyConfigurator.swift | 7 ------- Example/WalletApp/ApplicationLayer/ProfilingService.swift | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift b/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift index b5cbb0b66..b14d8b4df 100644 --- a/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift +++ b/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift @@ -1,11 +1,9 @@ import Foundation import Sentry -import Mixpanel struct ThirdPartyConfigurator: Configurator { func configure() { - configureLogging() } private func configureLogging() { @@ -17,9 +15,4 @@ struct ThirdPartyConfigurator: Configurator { options.tracesSampleRate = 1.0 } } - - private func configureProfiling() { - Mixpanel.initialize(token: "", trackAutomaticEvents: true) - - } } diff --git a/Example/WalletApp/ApplicationLayer/ProfilingService.swift b/Example/WalletApp/ApplicationLayer/ProfilingService.swift index 30616f702..83c09e336 100644 --- a/Example/WalletApp/ApplicationLayer/ProfilingService.swift +++ b/Example/WalletApp/ApplicationLayer/ProfilingService.swift @@ -5,6 +5,7 @@ final class ProfilingService { public static var instance = ProfilingService() func setUpProfiling(account: String, clientId: String) { + Mixpanel.initialize(token: "", trackAutomaticEvents: true) Mixpanel.mainInstance().identify(distinctId: clientId) Mixpanel.mainInstance().people.set(properties: [ "account": account]) } From 746e9abf0e3246045541c98f3a2f3d321ea68004 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 27 Aug 2023 17:02:12 +0100 Subject: [PATCH 03/32] update config file --- Configuration.xcconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Configuration.xcconfig b/Configuration.xcconfig index 27c07ad29..361714e46 100644 --- a/Configuration.xcconfig +++ b/Configuration.xcconfig @@ -14,4 +14,6 @@ RELAY_HOST = relay.walletconnect.com // WALLETAPP_SENTRY_DSN = WALLETAPP_SENTRY_DSN +// MIXPANEL_TOKEN = MIXPANEL_TOKEN + CAST_HOST = notify.walletconnect.com From 304342f0a026780ddb5f0fcfd6938ec8d0038d74 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 27 Aug 2023 17:02:21 +0100 Subject: [PATCH 04/32] savepoint --- Example/WalletApp/ApplicationLayer/ProfilingService.swift | 3 ++- Example/WalletApp/Common/InputConfig.swift | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Example/WalletApp/ApplicationLayer/ProfilingService.swift b/Example/WalletApp/ApplicationLayer/ProfilingService.swift index 83c09e336..fb9f95a40 100644 --- a/Example/WalletApp/ApplicationLayer/ProfilingService.swift +++ b/Example/WalletApp/ApplicationLayer/ProfilingService.swift @@ -5,7 +5,8 @@ final class ProfilingService { public static var instance = ProfilingService() func setUpProfiling(account: String, clientId: String) { - Mixpanel.initialize(token: "", trackAutomaticEvents: true) + guard let token = InputConfig.mixpanelToken, !token.isEmpty else { return } + Mixpanel.initialize(token: token, trackAutomaticEvents: true) Mixpanel.mainInstance().identify(distinctId: clientId) Mixpanel.mainInstance().people.set(properties: [ "account": account]) } diff --git a/Example/WalletApp/Common/InputConfig.swift b/Example/WalletApp/Common/InputConfig.swift index cd523e551..b8ce51193 100644 --- a/Example/WalletApp/Common/InputConfig.swift +++ b/Example/WalletApp/Common/InputConfig.swift @@ -12,6 +12,10 @@ struct InputConfig { static var sentryDsn: String? { return config(for: "WALLETAPP_SENTRY_DSN") } + + static var mixpanelToken: String? { + return config(for: "MIXPANEL_TOKEN") + } private static func config(for key: String) -> String? { return Bundle.main.object(forInfoDictionaryKey: key) as? String From ef3d5c349f100697b59a05ad17ce0ec2e474a435 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 28 Aug 2023 16:17:58 +0100 Subject: [PATCH 05/32] update profiling service --- .../ApplicationLayer/ProfilingService.swift | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Example/WalletApp/ApplicationLayer/ProfilingService.swift b/Example/WalletApp/ApplicationLayer/ProfilingService.swift index fb9f95a40..c1f5c7701 100644 --- a/Example/WalletApp/ApplicationLayer/ProfilingService.swift +++ b/Example/WalletApp/ApplicationLayer/ProfilingService.swift @@ -1,13 +1,47 @@ import Foundation import Mixpanel +import WalletConnectNetworking +import Combine final class ProfilingService { public static var instance = ProfilingService() + private let queue = DispatchQueue(label: "com.walletApp.loggingService") + private var publishers = [AnyCancellable]() + private var isProfiling = false + func setUpProfiling(account: String, clientId: String) { + queue.sync { + guard isProfiling == false else { return } + isProfiling = true + } guard let token = InputConfig.mixpanelToken, !token.isEmpty else { return } Mixpanel.initialize(token: token, trackAutomaticEvents: true) Mixpanel.mainInstance().identify(distinctId: clientId) Mixpanel.mainInstance().people.set(properties: [ "account": account]) + + + Networking.instance.logsPublisher + .sink { [unowned self] log in + self.queue.sync { + switch log { + case .error(let log): + send(event: log) + case .warn(let log): + send(event: log) + case .debug(let log): + send(event: log) + default: + return + } + } + } + .store(in: &publishers) } + + func send(event: String) { + Mixpanel.mainInstance().track(event: event) + } + + } From e5211dacec5984df7e732da344c44e04bcaa41b9 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 28 Aug 2023 18:28:21 +0100 Subject: [PATCH 06/32] update logger --- Example/WalletApp/ApplicationLayer/ProfilingService.swift | 3 ++- Example/WalletApp/Other/Info.plist | 2 ++ Sources/WalletConnectNetworking/NetworkingInteractor.swift | 1 + Sources/WalletConnectRelay/RelayClient.swift | 5 +++++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Example/WalletApp/ApplicationLayer/ProfilingService.swift b/Example/WalletApp/ApplicationLayer/ProfilingService.swift index c1f5c7701..bf86cd79a 100644 --- a/Example/WalletApp/ApplicationLayer/ProfilingService.swift +++ b/Example/WalletApp/ApplicationLayer/ProfilingService.swift @@ -6,7 +6,7 @@ import Combine final class ProfilingService { public static var instance = ProfilingService() - private let queue = DispatchQueue(label: "com.walletApp.loggingService") + private let queue = DispatchQueue(label: "com.walletApp.profilingService") private var publishers = [AnyCancellable]() private var isProfiling = false @@ -16,6 +16,7 @@ final class ProfilingService { isProfiling = true } guard let token = InputConfig.mixpanelToken, !token.isEmpty else { return } + Mixpanel.initialize(token: token, trackAutomaticEvents: true) Mixpanel.mainInstance().identify(distinctId: clientId) Mixpanel.mainInstance().people.set(properties: [ "account": account]) diff --git a/Example/WalletApp/Other/Info.plist b/Example/WalletApp/Other/Info.plist index 3a0166b38..2f0f15d26 100644 --- a/Example/WalletApp/Other/Info.plist +++ b/Example/WalletApp/Other/Info.plist @@ -30,6 +30,8 @@ $(WALLETAPP_SENTRY_DSN) SIMULATOR_IDENTIFIER $(SIMULATOR_IDENTIFIER) + MIXPANEL_TOKEN + $(MIXPANEL_TOKEN) UIApplicationSceneManifest UIApplicationSupportsMultipleScenes diff --git a/Sources/WalletConnectNetworking/NetworkingInteractor.swift b/Sources/WalletConnectNetworking/NetworkingInteractor.swift index a07f0b81b..d216f9974 100644 --- a/Sources/WalletConnectNetworking/NetworkingInteractor.swift +++ b/Sources/WalletConnectNetworking/NetworkingInteractor.swift @@ -22,6 +22,7 @@ public class NetworkingInteractor: NetworkInteracting { public var logsPublisher: AnyPublisher { logger.logsPublisher .merge(with: serializer.logsPublisher) + .merge(with: relayClient.logsPublisher) .eraseToAnyPublisher() } diff --git a/Sources/WalletConnectRelay/RelayClient.swift b/Sources/WalletConnectRelay/RelayClient.swift index 60eb6aa06..441f40314 100644 --- a/Sources/WalletConnectRelay/RelayClient.swift +++ b/Sources/WalletConnectRelay/RelayClient.swift @@ -42,6 +42,11 @@ public final class RelayClient { private let concurrentQueue = DispatchQueue(label: "com.walletconnect.sdk.relay_client", attributes: .concurrent) + public var logsPublisher: AnyPublisher { + logger.logsPublisher + .eraseToAnyPublisher() + } + // MARK: - Initialization init( From 08429883b5ad7d039848131547bd92a2201205dd Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 28 Aug 2023 18:34:43 +0100 Subject: [PATCH 07/32] update fastfile and makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6d054315d..32cdfdd66 100755 --- a/Makefile +++ b/Makefile @@ -67,11 +67,11 @@ x_platform_protocol_tests: ./run_tests.sh --scheme IntegrationTests --testplan XPlatformProtocolTests --project Example/ExampleApp.xcodeproj release_wallet: - fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) sentry_dsn:$(WALLETAPP_SENTRY_DSN) --env WalletApp + fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) sentry_dsn:$(WALLETAPP_SENTRY_DSN) mixpanel_token:$(MIXPANEL_TOKEN) --env WalletApp release_showcase: fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) --env Showcase release_all: - fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) sentry_dsn:$(WALLETAPP_SENTRY_DSN) --env WalletApp + fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) sentry_dsn:$(WALLETAPP_SENTRY_DSN) mixpanel_token:$(MIXPANEL_TOKEN) --env WalletApp fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) --env Showcase From 65e3fdaa2be20062c93160ba6af5b936ce32d6f2 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 28 Aug 2023 18:36:10 +0100 Subject: [PATCH 08/32] update fastfile --- fastlane/Fastfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 7918fec5d..ef829c945 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -103,7 +103,7 @@ platform :ios do project: "Example/ExampleApp.xcodeproj", scheme: ENV["SCHEME"], export_method: "app-store", - xcargs: "RELAY_HOST='#{options[:relay_host]}' PROJECT_ID='#{options[:project_id]}' WALLETAPP_SENTRY_DSN='#{options[:sentry_dsn]}'" + xcargs: "RELAY_HOST='#{options[:relay_host]}' PROJECT_ID='#{options[:project_id]}' WALLETAPP_SENTRY_DSN='#{options[:sentry_dsn]}' MIXPANEL_TOKEN='#{options[:mixpanel_token]}'" ) upload_to_testflight( apple_id: ENV["APPLE_ID"], @@ -113,6 +113,7 @@ platform :ios do notify_external_testers: true, skip_waiting_for_build_processing: false, groups: [ + "WalletConnect", "WalletConnect Users" ] ) From 7a48249fdc1c7721b8cf4b55ce0235ae2e4b8963 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 28 Aug 2023 18:38:38 +0100 Subject: [PATCH 09/32] update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fbafbbd5c..3174bdc93 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,4 +35,4 @@ jobs: APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} WALLETAPP_SENTRY_DSN: ${{ secrets.WALLETAPP_SENTRY_DSN }} run: | - make release_all APPLE_ID=${{ secrets.APPLE_ID }} TOKEN=$(echo -n $GH_USER:$GH_TOKEN | base64) PROJECT_ID=${{ secrets.RELEASE_PROJECT_ID }} WALLETAPP_SENTRY_DSN=${{ secrets.WALLETAPP_SENTRY_DSN }} + make release_all APPLE_ID=${{ secrets.APPLE_ID }} TOKEN=$(echo -n $GH_USER:$GH_TOKEN | base64) PROJECT_ID=${{ secrets.RELEASE_PROJECT_ID }} WALLETAPP_SENTRY_DSN=${{ secrets.WALLETAPP_SENTRY_DSN }} MIXPANEL_TOKEN=${{secrets.MIXPANEL_TOKEN}} From 874f31330df301544a16d2cb3795dca023111937 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 28 Aug 2023 18:55:36 +0100 Subject: [PATCH 10/32] Add web3inbox logs --- .../ApplicationLayer/ProfilingService.swift | 18 ++++++++++++++++++ Sources/Web3Inbox/Web3InboxClient.swift | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/Example/WalletApp/ApplicationLayer/ProfilingService.swift b/Example/WalletApp/ApplicationLayer/ProfilingService.swift index bf86cd79a..3da453fd7 100644 --- a/Example/WalletApp/ApplicationLayer/ProfilingService.swift +++ b/Example/WalletApp/ApplicationLayer/ProfilingService.swift @@ -2,6 +2,7 @@ import Foundation import Mixpanel import WalletConnectNetworking import Combine +import Web3Inbox final class ProfilingService { public static var instance = ProfilingService() @@ -38,6 +39,23 @@ final class ProfilingService { } } .store(in: &publishers) + + Web3Inbox.instance.logsPublisher + .sink { [unowned self] log in + self.queue.sync { + switch log { + case .error(let log): + send(event: log) + case .warn(let log): + send(event: log) + case .debug(let log): + send(event: log) + default: + return + } + } + } + .store(in: &publishers) } func send(event: String) { diff --git a/Sources/Web3Inbox/Web3InboxClient.swift b/Sources/Web3Inbox/Web3InboxClient.swift index 0325b6991..fa2d25d7f 100644 --- a/Sources/Web3Inbox/Web3InboxClient.swift +++ b/Sources/Web3Inbox/Web3InboxClient.swift @@ -1,5 +1,6 @@ import Foundation import WebKit +import Combine public final class Web3InboxClient { @@ -19,6 +20,11 @@ public final class Web3InboxClient { private let webviewSubscriber: WebViewRequestSubscriber + public var logsPublisher: AnyPublisher { + logger.logsPublisher + .eraseToAnyPublisher() + } + init( webView: WKWebView, account: Account, From c9d90ad10ed96228dd637e06a9cb5008955f937f Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Tue, 29 Aug 2023 19:32:37 +0800 Subject: [PATCH 11/32] Register steps --- Sources/WalletConnectIdentity/IdentityClient.swift | 5 +++++ .../WalletConnectNotify/Client/Wallet/NotifyClient.swift | 8 ++++++++ .../Client/Wallet/NotifySyncService.swift | 8 ++++++++ 3 files changed, 21 insertions(+) diff --git a/Sources/WalletConnectIdentity/IdentityClient.swift b/Sources/WalletConnectIdentity/IdentityClient.swift index 8ec6d2943..57335fb79 100644 --- a/Sources/WalletConnectIdentity/IdentityClient.swift +++ b/Sources/WalletConnectIdentity/IdentityClient.swift @@ -72,4 +72,9 @@ public final class IdentityClient { public func getInviteKey(for account: Account) throws -> AgreementPublicKey { return try identityStorage.getInviteKey(for: account) } + + public func isIdentityRegistered(account: Account) -> Bool { + let key = try? identityStorage.getIdentityKey(for: account) + return key != nil + } } diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 00f499a57..083ce9bca 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -111,6 +111,14 @@ public class NotifyClient { public func register(deviceToken: Data) async throws { try await pushClient.register(deviceToken: deviceToken) } + + public func isIdentityRegistered(account: Account) -> Bool { + return notifySyncService.isIdentityRegistered(account: account) + } + + public func isSyncRegistered(account: Account) -> Bool { + return notifySyncService.isSyncRegistered(account: account) + } } #if targetEnvironment(simulator) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifySyncService.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifySyncService.swift index 517b81e50..ecd67c72b 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifySyncService.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifySyncService.swift @@ -118,6 +118,14 @@ final class NotifySyncService { coldStartStore.set(Date(), forKey: account.absoluteString) } + + func isIdentityRegistered(account: Account) -> Bool { + return identityClient.isIdentityRegistered(account: account) + } + + func isSyncRegistered(account: Account) -> Bool { + return syncClient.isRegistered(account: account) + } } private extension NotifySyncService { From d80c3f84dbc7eb8f000fce0df809382b29ace611 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 29 Aug 2023 14:24:35 +0100 Subject: [PATCH 12/32] reenable native notify integration --- .../PresentationLayer/Wallet/Main/MainPresenter.swift | 1 + .../PresentationLayer/Wallet/Main/Model/TabPage.swift | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift index 7167284c2..4be0dc58a 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift @@ -16,6 +16,7 @@ final class MainPresenter { var viewControllers: [UIViewController] { 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 1c93883ad..3f2051baf 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift @@ -2,6 +2,7 @@ import UIKit enum TabPage: CaseIterable { case wallet + case notifications case web3Inbox case settings @@ -9,6 +10,8 @@ enum TabPage: CaseIterable { switch self { case .wallet: return "Apps" + case .notifications: + return "Notifications" case .web3Inbox: return "Web3Inbox" case .settings: @@ -20,6 +23,8 @@ enum TabPage: CaseIterable { switch self { case .wallet: return UIImage(systemName: "house.fill")! + case .notifications: + return UIImage(systemName: "bell.fill")! case .web3Inbox: return UIImage(systemName: "bell.fill")! case .settings: @@ -32,6 +37,6 @@ enum TabPage: CaseIterable { } static var enabledTabs: [TabPage] { - return [.wallet, .web3Inbox, .settings] + return [.wallet, .notifications, .web3Inbox, .settings] } } From 13c6b3bcddbd4dedb33e96f99a6e36f4345ec0e8 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 30 Aug 2023 16:33:49 +0800 Subject: [PATCH 13/32] Messages publisher --- .../Client/Wallet/NotifyClient.swift | 6 +++++- .../Client/Wallet/NotifyStorage.swift | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 083ce9bca..99ba78a9c 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -23,7 +23,7 @@ public class NotifyClient { } public var notifyMessagePublisher: AnyPublisher { - notifyMessageSubscriber.notifyMessagePublisher + return notifyMessageSubscriber.notifyMessagePublisher } public var updateSubscriptionPublisher: AnyPublisher, Never> { @@ -119,6 +119,10 @@ public class NotifyClient { public func isSyncRegistered(account: Account) -> Bool { return notifySyncService.isSyncRegistered(account: account) } + + public func messagesPublisher(topic: String) -> AnyPublisher<[NotifyMessageRecord], Never> { + return notifyStorage.messagesPublisher(topic: topic) + } } #if targetEnvironment(simulator) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift index 23867f8f3..9ef73a705 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift @@ -18,6 +18,7 @@ final class NotifyStorage: NotifyStoring { private let newSubscriptionSubject = PassthroughSubject() private let updateSubscriptionSubject = PassthroughSubject() private let deleteSubscriptionSubject = PassthroughSubject() + private let messagesSubject = PassthroughSubject<[NotifyMessageRecord], Never>() private let subscriptionStoreDelegate: NotifySubscriptionStoreDelegate @@ -26,7 +27,7 @@ final class NotifyStorage: NotifyStoring { } var updateSubscriptionPublisher: AnyPublisher { - return newSubscriptionSubject.eraseToAnyPublisher() + return updateSubscriptionSubject.eraseToAnyPublisher() } var deleteSubscriptionPublisher: AnyPublisher { @@ -37,6 +38,10 @@ final class NotifyStorage: NotifyStoring { return subscriptionStore.dataUpdatePublisher } + var messagesPublisher: AnyPublisher<[NotifyMessageRecord], Never> { + return messagesSubject.eraseToAnyPublisher() + } + init( subscriptionStore: SyncStore, messagesStore: KeyedDatabase, @@ -88,6 +93,12 @@ final class NotifyStorage: NotifyStoring { // MARK: Messages + func messagesPublisher(topic: String) -> AnyPublisher<[NotifyMessageRecord], Never> { + return messagesPublisher + .map { $0.filter { $0.topic == topic } } + .eraseToAnyPublisher() + } + func getMessages(topic: String) -> [NotifyMessageRecord] { return messagesStore.getAll(for: topic) .sorted{$0.publishedAt > $1.publishedAt} @@ -110,6 +121,10 @@ final class NotifyStorage: NotifyStoring { private extension NotifyStorage { func setupSubscriptions() { + messagesStore.onUpdate = { [unowned self] in + messagesSubject.send(messagesStore.getAll()) + } + subscriptionStore.syncUpdatePublisher.sink { [unowned self] (_, _, update) in switch update { case .set(let subscription): From 1ae013bd126bbb6be5866429efc964c2c317140c Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 30 Aug 2023 16:42:22 +0800 Subject: [PATCH 14/32] testOnUpdate --- Tests/WalletConnectUtilsTests/KeyedDatabaseTests.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Tests/WalletConnectUtilsTests/KeyedDatabaseTests.swift b/Tests/WalletConnectUtilsTests/KeyedDatabaseTests.swift index fc1674fbf..1cd08b53f 100644 --- a/Tests/WalletConnectUtilsTests/KeyedDatabaseTests.swift +++ b/Tests/WalletConnectUtilsTests/KeyedDatabaseTests.swift @@ -37,4 +37,14 @@ final class KeyedDatabaseTests: XCTestCase { XCTAssertEqual(value, updated) } + + func testOnUpdate() { + let new = Object(key: "key1", value: "value1") + + var onUpdateCalled = false + sut.onUpdate = { onUpdateCalled = true } + sut.set(element: new, for: storageKey) + + XCTAssertTrue(onUpdateCalled) + } } From f73ab86032b09d8b64148d7e39dbd999eddecbad Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 30 Aug 2023 16:55:57 +0800 Subject: [PATCH 15/32] PushMessagesView use messages publisher --- .../PushMessages/PushMessagesInteractor.swift | 4 +- .../PushMessages/PushMessagesPresenter.swift | 37 +++++++------------ .../PushMessages/PushMessagesView.swift | 6 +-- 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesInteractor.swift index e198f8383..b1953934e 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesInteractor.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesInteractor.swift @@ -9,8 +9,8 @@ final class PushMessagesInteractor { self.subscription = subscription } - var notifyMessagePublisher: AnyPublisher { - return Notify.instance.notifyMessagePublisher + var messagesPublisher: AnyPublisher<[NotifyMessageRecord], Never> { + return Notify.instance.messagesPublisher(topic: subscription.topic) } func getPushMessages() -> [NotifyMessageRecord] { diff --git a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift index 1c725aec6..c4c3252a9 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift @@ -8,10 +8,16 @@ final class PushMessagesPresenter: ObservableObject { private let router: PushMessagesRouter private var disposeBag = Set() - @Published var pushMessages: [PushMessageViewModel] = [] + @Published private var pushMessages: [NotifyMessageRecord] = [] + + var messages: [PushMessageViewModel] { + return pushMessages + .sorted { $0.publishedAt > $1.publishedAt } + .map { PushMessageViewModel(pushMessageRecord: $0) } + } init(interactor: PushMessagesInteractor, router: PushMessagesRouter) { - defer { reloadPushMessages() } + defer { setupInitialState() } self.interactor = interactor self.router = router } @@ -20,7 +26,6 @@ final class PushMessagesPresenter: ObservableObject { if let index = indexSet.first { interactor.deletePushMessage(id: pushMessages[index].id) } - reloadPushMessages() } } @@ -40,27 +45,13 @@ extension PushMessagesPresenter: SceneViewModel { private extension PushMessagesPresenter { - func reloadPushMessages() { - self.pushMessages = interactor.getPushMessages() - .sorted { - // Most recent first - $0.publishedAt > $1.publishedAt - } - .map { pushMessageRecord in - PushMessageViewModel(pushMessageRecord: pushMessageRecord) - } - - interactor.notifyMessagePublisher + func setupInitialState() { + pushMessages = interactor.getPushMessages() + + interactor.messagesPublisher .receive(on: DispatchQueue.main) - .sink { [weak self] newPushMessage in - let newMessageViewModel = PushMessageViewModel(pushMessageRecord: newPushMessage) - guard let index = self?.pushMessages.firstIndex( - where: { $0.pushMessageRecord.publishedAt > newPushMessage.publishedAt } - ) else { - self?.pushMessages.append(newMessageViewModel) - return - } - self?.pushMessages.insert(newMessageViewModel, at: index) + .sink { [unowned self] messages in + pushMessages = interactor.getPushMessages() } .store(in: &disposeBag) } diff --git a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesView.swift b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesView.swift index c29766ed3..7f22c53f6 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesView.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesView.swift @@ -11,7 +11,7 @@ struct PushMessagesView: View { VStack(alignment: .leading, spacing: 16) { ZStack { - if presenter.pushMessages.isEmpty { + if presenter.messages.isEmpty { VStack(spacing: 10) { Image(systemName: "bell.badge.fill") .resizable() @@ -29,9 +29,9 @@ struct PushMessagesView: View { } VStack { - if !presenter.pushMessages.isEmpty { + if !presenter.messages.isEmpty { List { - ForEach(presenter.pushMessages, id: \.id) { pm in + ForEach(presenter.messages, id: \.id) { pm in notificationView(pushMessage: pm) .listRowSeparator(.hidden) .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0)) From 8121b82cd07c97c759efee84bb6a8ddc8e58449d Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 30 Aug 2023 14:11:11 +0100 Subject: [PATCH 16/32] add refresh notification --- .../Wallet/PushMessages/PushMessagesPresenter.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift index 1c725aec6..5730870a7 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift @@ -14,6 +14,16 @@ final class PushMessagesPresenter: ObservableObject { defer { reloadPushMessages() } self.interactor = interactor self.router = router + setUpMessagesRefresh() + } + + private func setUpMessagesRefresh() { + Timer.publish(every: 60.0, on: .main, in: .default) + .autoconnect() + .sink { [weak self] _ in + self?.reloadPushMessages() + } + .store(in: &disposeBag) } func deletePushMessage(at indexSet: IndexSet) { From ca4d5a61dbe206e32be8e9bd91bfeb97bac59b53 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 30 Aug 2023 14:12:21 +0100 Subject: [PATCH 17/32] add refresh --- .../Wallet/PushMessages/PushMessagesPresenter.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift index c4c3252a9..456b5ff27 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift @@ -20,6 +20,16 @@ final class PushMessagesPresenter: ObservableObject { defer { setupInitialState() } self.interactor = interactor self.router = router + setUpMessagesRefresh() + } + + private func setUpMessagesRefresh() { + Timer.publish(every: 60.0, on: .main, in: .default) + .autoconnect() + .sink { [weak self] _ in + self?.reloadPushMessages() + } + .store(in: &disposeBag) } func deletePushMessage(at indexSet: IndexSet) { From 0170fb421e42c1f9968b59fff71588a3c0c3f544 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 30 Aug 2023 14:35:22 +0100 Subject: [PATCH 18/32] add refresh timer --- .../PushMessages/PushMessagesPresenter.swift | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift index 456b5ff27..ec8b91c8f 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift @@ -24,13 +24,14 @@ final class PushMessagesPresenter: ObservableObject { } private func setUpMessagesRefresh() { - Timer.publish(every: 60.0, on: .main, in: .default) + Timer.publish(every: 10.0, on: .main, in: .default) .autoconnect() - .sink { [weak self] _ in - self?.reloadPushMessages() - } - .store(in: &disposeBag) + .sink(receiveValue: { [weak self] _ in + guard let self = self else { return } + self.pushMessages = self.interactor.getPushMessages() + }).store(in: &disposeBag) } + func deletePushMessage(at indexSet: IndexSet) { if let index = indexSet.first { @@ -60,8 +61,9 @@ private extension PushMessagesPresenter { interactor.messagesPublisher .receive(on: DispatchQueue.main) - .sink { [unowned self] messages in - pushMessages = interactor.getPushMessages() + .sink { [weak self] messages in + guard let self = self else { return } + self.pushMessages = self.interactor.getPushMessages() } .store(in: &disposeBag) } From e10d22dbcc14a34372d2476d1ea8ba32033c54fd Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 31 Aug 2023 15:13:08 +0100 Subject: [PATCH 19/32] Update logging add notify logging to mixpanel --- .../ConfigurationService.swift | 1 + .../ApplicationLayer/LoggingService.swift | 4 +- .../ApplicationLayer/ProfilingService.swift | 31 +++++++-------- .../Client/Wallet/NotifyClient.swift | 9 +++++ .../Logger/ConsoleLogger.swift | 39 ++++++++++--------- Sources/WalletConnectUtils/Logger/Log.swift | 26 +++++++++++-- Sources/Web3Inbox/Web3InboxClient.swift | 6 +++ .../Web3Inbox/Web3InboxClientFactory.swift | 2 +- Sources/Web3Inbox/WebView/WebViewProxy.swift | 7 +++- 9 files changed, 82 insertions(+), 43 deletions(-) diff --git a/Example/WalletApp/ApplicationLayer/ConfigurationService.swift b/Example/WalletApp/ApplicationLayer/ConfigurationService.swift index 1f7028f0b..5aa30d797 100644 --- a/Example/WalletApp/ApplicationLayer/ConfigurationService.swift +++ b/Example/WalletApp/ApplicationLayer/ConfigurationService.swift @@ -26,6 +26,7 @@ final class ConfigurationService { crypto: DefaultCryptoProvider(), onSign: importAccount.onSign ) + Web3Inbox.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/LoggingService.swift b/Example/WalletApp/ApplicationLayer/LoggingService.swift index 30c0b484b..ebb236741 100644 --- a/Example/WalletApp/ApplicationLayer/LoggingService.swift +++ b/Example/WalletApp/ApplicationLayer/LoggingService.swift @@ -31,9 +31,9 @@ final class LoggingService { self.queue.sync { switch log { case .error(let log): - SentrySDK.capture(error: LoggingError.networking(log)) + SentrySDK.capture(error: LoggingError.networking(log.aggregated)) case .warn(let log): - SentrySDK.capture(message: log) + SentrySDK.capture(message: log.aggregated) default: return } diff --git a/Example/WalletApp/ApplicationLayer/ProfilingService.swift b/Example/WalletApp/ApplicationLayer/ProfilingService.swift index 3da453fd7..20dec5fbe 100644 --- a/Example/WalletApp/ApplicationLayer/ProfilingService.swift +++ b/Example/WalletApp/ApplicationLayer/ProfilingService.swift @@ -19,6 +19,7 @@ final class ProfilingService { guard let token = InputConfig.mixpanelToken, !token.isEmpty else { return } Mixpanel.initialize(token: token, trackAutomaticEvents: true) + Mixpanel.mainInstance().alias = "Bartek" Mixpanel.mainInstance().identify(distinctId: clientId) Mixpanel.mainInstance().people.set(properties: [ "account": account]) @@ -27,12 +28,12 @@ final class ProfilingService { .sink { [unowned self] log in self.queue.sync { switch log { - case .error(let log): - send(event: log) - case .warn(let log): - send(event: log) - case .debug(let log): - send(event: log) + case .error(let logMessage): + send(logMessage: logMessage) + case .warn(let logMessage): + send(logMessage: logMessage) + case .debug(let logMessage): + send(logMessage: logMessage) default: return } @@ -44,12 +45,12 @@ final class ProfilingService { .sink { [unowned self] log in self.queue.sync { switch log { - case .error(let log): - send(event: log) - case .warn(let log): - send(event: log) - case .debug(let log): - send(event: log) + case .error(let logMessage): + send(logMessage: logMessage) + case .warn(let logMessage): + send(logMessage: logMessage) + case .debug(let logMessage): + send(logMessage: logMessage) default: return } @@ -58,9 +59,7 @@ final class ProfilingService { .store(in: &publishers) } - func send(event: String) { - Mixpanel.mainInstance().track(event: event) + func send(logMessage: LogMessage) { + Mixpanel.mainInstance().track(event: logMessage.message, properties: logMessage.properties) } - - } diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 00f499a57..4b6b39b3d 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -30,6 +30,11 @@ public class NotifyClient { return notifyUpdateResponseSubscriber.updateSubscriptionPublisher } + public var logsPublisher: AnyPublisher { + logger.logsPublisher + .eraseToAnyPublisher() + } + private let deleteNotifySubscriptionService: DeleteNotifySubscriptionService private let notifySubscribeRequester: NotifySubscribeRequester @@ -84,6 +89,10 @@ public class NotifyClient { try await notifySyncService.fetchHistoryIfNeeded(account: account) } + public func setLogging(level: LoggingLevel) { + 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) } diff --git a/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift b/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift index 8c8b1a736..4219f4d1d 100644 --- a/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift +++ b/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift @@ -3,7 +3,7 @@ import Combine public protocol ConsoleLogging { var logsPublisher: AnyPublisher { get } - func debug(_ items: Any..., file: String, function: String, line: Int) + func debug(_ items: Any..., file: String, function: String, line: Int, properties: [String: String]?) func info(_ items: Any..., file: String, function: String, line: Int) func warn(_ items: Any..., file: String, function: String, line: Int) func error(_ items: Any..., file: String, function: String, line: Int) @@ -11,8 +11,8 @@ public protocol ConsoleLogging { } public extension ConsoleLogging { - func debug(_ items: Any..., file: String = #file, function: String = #function, line: Int = #line) { - debug(items, file: file, function: function, line: line) + func debug(_ items: Any..., file: String = #file, function: String = #function, line: Int = #line, properties: [String: String]? = nil) { + debug(items, file: file, function: function, line: line, properties: properties) } func info(_ items: Any..., file: String = #file, function: String = #function, line: Int = #line) { info(items, file: file, function: function, line: line) @@ -42,29 +42,32 @@ public class ConsoleLogger { self.loggingLevel = loggingLevel } - private func logMessage(_ items: Any..., logType: LoggingLevel, file: String = #file, function: String = #function, line: Int = #line) { + private func logMessage(_ items: Any..., logType: LoggingLevel, file: String = #file, function: String = #function, line: Int = #line, properties: [String: String]? = nil) { let fileName = (file as NSString).lastPathComponent items.forEach { - var log = "[\(fileName)]: \($0) - \(function) - line: \(line) - \(logFormattedDate(Date()))" - + var logMessage = "\($0)" + var properties = properties ?? [String: String]() + properties["fileName"] = fileName + properties["line"] = "\(line)" + properties["function"] = function switch logType { case .debug: - log = "\(prefix) \(log)" - logsPublisherSubject.send(.debug(log)) + logMessage = "\(prefix) \(logMessage)" + logsPublisherSubject.send(.debug(LogMessage(message: logMessage, properties: properties))) case .info: - log = "\(prefix) ℹ️ \(log)" - logsPublisherSubject.send(.info(log)) + logMessage = "\(prefix) ℹ️ \(logMessage)" + logsPublisherSubject.send(.info(LogMessage(message: logMessage, properties: properties))) case .warn: - log = "\(prefix) ⚠️ \(log)" - logsPublisherSubject.send(.warn(log)) + logMessage = "\(prefix) ⚠️ \(logMessage)" + logsPublisherSubject.send(.warn(LogMessage(message: logMessage, properties: properties))) case .error: - log = "\(prefix) ‼️ \(log)" - logsPublisherSubject.send(.error(log)) + logMessage = "\(prefix) ‼️ \(logMessage)" + logsPublisherSubject.send(.error(LogMessage(message: logMessage, properties: properties))) case .off: return } - - Swift.print(log) + logMessage = "\(prefix) [\(fileName)]: \($0) - \(function) - line: \(line) - \(logFormattedDate(Date()))" + Swift.print(logMessage) } } @@ -77,9 +80,9 @@ public class ConsoleLogger { extension ConsoleLogger: ConsoleLogging { - public func debug(_ items: Any..., file: String, function: String, line: Int) { + public func debug(_ items: Any..., file: String, function: String, line: Int, properties: [String : String]?) { if loggingLevel >= .debug { - logMessage(items, logType: .debug, file: file, function: function, line: line) + logMessage(items, logType: .debug, file: file, function: function, line: line, properties: properties) } } diff --git a/Sources/WalletConnectUtils/Logger/Log.swift b/Sources/WalletConnectUtils/Logger/Log.swift index 022dcb1d8..5e3c7f785 100644 --- a/Sources/WalletConnectUtils/Logger/Log.swift +++ b/Sources/WalletConnectUtils/Logger/Log.swift @@ -1,8 +1,26 @@ import Foundation +public struct LogMessage { + public let message: String + public let properties: [String: String]? + public var aggregated: String { + var aggregatedProperties = "" + + properties?.forEach { key, value in + aggregatedProperties += "\(key): \(value), " + } + + if !aggregatedProperties.isEmpty { + aggregatedProperties = String(aggregatedProperties.dropLast(2)) + } + + return "\(message), properties: [\(aggregatedProperties)]" + } +} + public enum Log { - case error(String) - case warn(String) - case info(String) - case debug(String) + case error(LogMessage) + case warn(LogMessage) + case info(LogMessage) + case debug(LogMessage) } diff --git a/Sources/Web3Inbox/Web3InboxClient.swift b/Sources/Web3Inbox/Web3InboxClient.swift index fa2d25d7f..2c3100200 100644 --- a/Sources/Web3Inbox/Web3InboxClient.swift +++ b/Sources/Web3Inbox/Web3InboxClient.swift @@ -52,6 +52,12 @@ public final class Web3InboxClient { setupSubscriptions() } + + public func setLogging(level: LoggingLevel) { + logger.setLogging(level: level) + notifyClient.setLogging(level: .debug) + } + public func getWebView() -> WKWebView { return webView } diff --git a/Sources/Web3Inbox/Web3InboxClientFactory.swift b/Sources/Web3Inbox/Web3InboxClientFactory.swift index 3257b4b7b..83ce998fe 100644 --- a/Sources/Web3Inbox/Web3InboxClientFactory.swift +++ b/Sources/Web3Inbox/Web3InboxClientFactory.swift @@ -12,7 +12,7 @@ final class Web3InboxClientFactory { ) -> Web3InboxClient { let url = buildUrl(account: account, config: config) - let logger = ConsoleLogger(prefix: "📬", loggingLevel: .debug) + let logger = ConsoleLogger(prefix: "📬", loggingLevel: .off) let webviewSubscriber = WebViewRequestSubscriber(url: url, logger: logger) let webView = WebViewFactory(url: url, webviewSubscriber: webviewSubscriber).create() let chatWebViewProxy = WebViewProxy(webView: webView, scriptFormatter: ChatWebViewScriptFormatter(), logger: logger) diff --git a/Sources/Web3Inbox/WebView/WebViewProxy.swift b/Sources/Web3Inbox/WebView/WebViewProxy.swift index 7aa396d93..ad513ed2d 100644 --- a/Sources/Web3Inbox/WebView/WebViewProxy.swift +++ b/Sources/Web3Inbox/WebView/WebViewProxy.swift @@ -19,7 +19,9 @@ actor WebViewProxy { @MainActor func respond(_ response: RPCResponse, _ request: RPCRequest) async throws { let body = try response.json(dateEncodingStrategy: .millisecondsSince1970) - logger.debug("resonding to w3i request \(request.method) with \(body)") + let logProperties: [String: String] = ["method": request.method, "requestId": "\(request.id!)", "response": body] + print(logProperties) + logger.debug("resonding to w3i request \(request.method) with \(body)", properties: logProperties) let script = scriptFormatter.formatScript(body: body) webView.evaluateJavaScript(script, completionHandler: nil) } @@ -27,7 +29,8 @@ actor WebViewProxy { @MainActor func request(_ request: RPCRequest) async throws { let body = try request.json(dateEncodingStrategy: .millisecondsSince1970) - logger.debug("requesting w3i with \(body)") + let logProperties = ["method": request.method, "requestId": "\(request.id!)"] + logger.debug("requesting w3i with \(body)", properties: logProperties) let script = scriptFormatter.formatScript(body: body) webView.evaluateJavaScript(script, completionHandler: nil) } From 34805cfa8d19f863828609843d7968026ad808a1 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 31 Aug 2023 15:29:11 +0100 Subject: [PATCH 20/32] update logging --- .../NotifySubscribeResponseSubscriber.swift | 12 ++++++------ Sources/Web3Inbox/Web3InboxClient.swift | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift index 48d32401b..d5349d8c0 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift @@ -44,14 +44,14 @@ class NotifySubscribeResponseSubscriber { networkingInteractor.responseSubscription(on: protocolMethod) .sink { [unowned self] (payload: ResponseSubscriptionPayload) in Task(priority: .high) { - logger.debug("NotifySubscribeResponseSubscriber: Received Notify Subscribe response") + logger.debug("Received Notify Subscribe response") 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("NotifySubscribeResponseSubscriber: no symmetric key for topic \(payload.topic)") + logger.debug("No symmetric key for topic \(payload.topic)") return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) } @@ -77,15 +77,15 @@ class NotifySubscribeResponseSubscriber { 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!)") + logger.debug("subscribing notify subscription topic: \(notifySubscriptionTopic!)") try await networkingInteractor.subscribe(topic: notifySubscriptionTopic) } catch { - logger.debug("NotifySubscribeResponseSubscriber: error: \(error)") + logger.debug("error: \(error)") return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) } guard let metadata = metadata else { - logger.debug("NotifySubscribeResponseSubscriber: no metadata for topic: \(notifySubscriptionTopic!)") + logger.debug("No metadata for topic: \(notifySubscriptionTopic!)") return subscriptionErrorSubject.send(Errors.couldNotCreateSubscription) } dappsMetadataStore.delete(forKey: payload.topic) @@ -95,7 +95,7 @@ class NotifySubscribeResponseSubscriber { try await notifyStorage.setSubscription(notifySubscription) - logger.debug("NotifySubscribeResponseSubscriber: unsubscribing response topic: \(payload.topic)") + logger.debug("Unsubscribing response topic: \(payload.topic)") networkingInteractor.unsubscribe(topic: payload.topic) } }.store(in: &publishers) diff --git a/Sources/Web3Inbox/Web3InboxClient.swift b/Sources/Web3Inbox/Web3InboxClient.swift index 2c3100200..d6277cb4e 100644 --- a/Sources/Web3Inbox/Web3InboxClient.swift +++ b/Sources/Web3Inbox/Web3InboxClient.swift @@ -22,6 +22,7 @@ public final class Web3InboxClient { public var logsPublisher: AnyPublisher { logger.logsPublisher + .merge(with: notifyClient.logsPublisher) .eraseToAnyPublisher() } From 58830606261c051356ae2a5f25696b8135caba38 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Sep 2023 09:27:55 +0100 Subject: [PATCH 21/32] update log messages --- .../wc_notifyMessage/NotifyMessageSubscriber.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift index 727751621..957c4df60 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyMessage/NotifyMessageSubscriber.swift @@ -30,10 +30,11 @@ class NotifyMessageSubscriber { networkingInteractor.requestSubscription(on: protocolMethod) .sink { [unowned self] (payload: RequestSubscriptionPayload) in - logger.debug("Received Notify Message") + logger.debug("Received Notify Message on topic: \(payload.topic)", properties: ["topic": payload.topic]) 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) @@ -60,7 +61,7 @@ class NotifyMessageSubscriber { protocolMethod: NotifyMessageProtocolMethod() ) - logger.debug("Sent Notify Receipt Response") + 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) From b217fb8cd125476f478dbe8849456b95ccbf76ed Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Sep 2023 09:54:59 +0100 Subject: [PATCH 22/32] update account display --- Example/WalletApp/ApplicationLayer/ProfilingService.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Example/WalletApp/ApplicationLayer/ProfilingService.swift b/Example/WalletApp/ApplicationLayer/ProfilingService.swift index 20dec5fbe..bc0c9bace 100644 --- a/Example/WalletApp/ApplicationLayer/ProfilingService.swift +++ b/Example/WalletApp/ApplicationLayer/ProfilingService.swift @@ -19,10 +19,10 @@ final class ProfilingService { guard let token = InputConfig.mixpanelToken, !token.isEmpty else { return } Mixpanel.initialize(token: token, trackAutomaticEvents: true) - Mixpanel.mainInstance().alias = "Bartek" - Mixpanel.mainInstance().identify(distinctId: clientId) - Mixpanel.mainInstance().people.set(properties: [ "account": account]) - + let mixpanel = Mixpanel.mainInstance() + mixpanel.alias = account + mixpanel.identify(distinctId: clientId) + mixpanel.people.set(properties: ["$name": account, "account": account]) Networking.instance.logsPublisher .sink { [unowned self] log in From 24a9142ed7dd6334f1ce1618dba906b27427d4c8 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Sep 2023 10:03:23 +0100 Subject: [PATCH 23/32] fix tests crash --- 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 4219f4d1d..f87f2dfef 100644 --- a/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift +++ b/Sources/WalletConnectUtils/Logger/ConsoleLogger.swift @@ -115,7 +115,7 @@ public struct ConsoleLoggerMock: ConsoleLogging { public init() {} - public func debug(_ items: Any..., file: String, function: String, line: Int) { } + public func debug(_ items: Any..., file: String, function: String, line: Int, properties: [String: String]?) { } public func info(_ items: Any..., file: String, function: String, line: Int) { } public func warn(_ items: Any..., file: String, function: String, line: Int) { } public func error(_ items: Any..., file: String, function: String, line: Int) { } From e2d8d16832a7ce3fc0d4266ccc45af5338ac1aed Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Sep 2023 10:10:37 +0100 Subject: [PATCH 24/32] refactor profiling service --- .../ApplicationLayer/ProfilingService.swift | 51 ++++++++----------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/Example/WalletApp/ApplicationLayer/ProfilingService.swift b/Example/WalletApp/ApplicationLayer/ProfilingService.swift index bc0c9bace..14a778061 100644 --- a/Example/WalletApp/ApplicationLayer/ProfilingService.swift +++ b/Example/WalletApp/ApplicationLayer/ProfilingService.swift @@ -9,13 +9,20 @@ final class ProfilingService { private let queue = DispatchQueue(label: "com.walletApp.profilingService") private var publishers = [AnyCancellable]() - private var isProfiling = false + private var isProfiling: Bool { + get { + return queue.sync { _isProfiling } + } + set { + queue.sync { _isProfiling = newValue } + } + } + private var _isProfiling = false func setUpProfiling(account: String, clientId: String) { - queue.sync { - guard isProfiling == false else { return } - isProfiling = true - } + guard !isProfiling else { return } + isProfiling = true + guard let token = InputConfig.mixpanelToken, !token.isEmpty else { return } Mixpanel.initialize(token: token, trackAutomaticEvents: true) @@ -24,39 +31,25 @@ final class ProfilingService { mixpanel.identify(distinctId: clientId) mixpanel.people.set(properties: ["$name": account, "account": account]) - Networking.instance.logsPublisher + handleLogs(from: Networking.instance.logsPublisher) + handleLogs(from: Web3Inbox.instance.logsPublisher) + } + + private func handleLogs(from publisher: AnyPublisher) { + publisher .sink { [unowned self] log in self.queue.sync { switch log { - case .error(let logMessage): - send(logMessage: logMessage) - case .warn(let logMessage): - send(logMessage: logMessage) - case .debug(let logMessage): - send(logMessage: logMessage) + case .error(let logMessage), + .warn(let logMessage), + .debug(let logMessage): + self.send(logMessage: logMessage) default: return } } } .store(in: &publishers) - - Web3Inbox.instance.logsPublisher - .sink { [unowned self] log in - self.queue.sync { - switch log { - case .error(let logMessage): - send(logMessage: logMessage) - case .warn(let logMessage): - send(logMessage: logMessage) - case .debug(let logMessage): - send(logMessage: logMessage) - default: - return - } - } - } - .store(in: &publishers) } func send(logMessage: LogMessage) { From fceafe55e9b308ba5e756e46aa0fea182e59d422 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Sep 2023 10:14:18 +0100 Subject: [PATCH 25/32] update logging service --- .../Configurator/ThirdPartyConfigurator.swift | 8 +------- .../WalletApp/ApplicationLayer/LoggingService.swift | 10 ++++++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift b/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift index b14d8b4df..f7eceeb61 100644 --- a/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift +++ b/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift @@ -7,12 +7,6 @@ struct ThirdPartyConfigurator: Configurator { } private func configureLogging() { - guard let sentryDsn = InputConfig.sentryDsn, !sentryDsn.isEmpty else { return } - SentrySDK.start { options in - options.dsn = "https://\(sentryDsn)" - // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring. - // We recommend adjusting this value in production. - options.tracesSampleRate = 1.0 - } + LoggingService.instance.configure() } } diff --git a/Example/WalletApp/ApplicationLayer/LoggingService.swift b/Example/WalletApp/ApplicationLayer/LoggingService.swift index ebb236741..6ab0b1504 100644 --- a/Example/WalletApp/ApplicationLayer/LoggingService.swift +++ b/Example/WalletApp/ApplicationLayer/LoggingService.swift @@ -20,6 +20,16 @@ final class LoggingService { SentrySDK.setUser(user) } + func configure() { + guard let sentryDsn = InputConfig.sentryDsn, !sentryDsn.isEmpty else { return } + SentrySDK.start { options in + options.dsn = "https://\(sentryDsn)" + // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring. + // We recommend adjusting this value in production. + options.tracesSampleRate = 1.0 + } + } + func startLogging() { queue.sync { guard isLogging == false else { return } From 3fa466aa20eae1729a780f669087caf3c6a3512d Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Sep 2023 10:17:48 +0100 Subject: [PATCH 26/32] update logging service --- .../Configurator/ThirdPartyConfigurator.swift | 1 - .../ApplicationLayer/LoggingService.swift | 28 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift b/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift index f7eceeb61..1d4418f8c 100644 --- a/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift +++ b/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift @@ -1,5 +1,4 @@ import Foundation -import Sentry struct ThirdPartyConfigurator: Configurator { diff --git a/Example/WalletApp/ApplicationLayer/LoggingService.swift b/Example/WalletApp/ApplicationLayer/LoggingService.swift index 6ab0b1504..e7a74cb9b 100644 --- a/Example/WalletApp/ApplicationLayer/LoggingService.swift +++ b/Example/WalletApp/ApplicationLayer/LoggingService.swift @@ -10,7 +10,16 @@ final class LoggingService { public static var instance = LoggingService() private var publishers = [AnyCancellable]() - private var isLogging = false + private var isLogging: Bool { + get { + return queue.sync { _isLogging } + } + set { + queue.sync { _isLogging = newValue } + } + } + private var _isLogging = false + private let queue = DispatchQueue(label: "com.walletApp.loggingService") func setUpUser(account: String, clientId: String) { @@ -24,26 +33,25 @@ final class LoggingService { guard let sentryDsn = InputConfig.sentryDsn, !sentryDsn.isEmpty else { return } SentrySDK.start { options in options.dsn = "https://\(sentryDsn)" - // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring. - // We recommend adjusting this value in production. options.tracesSampleRate = 1.0 } } func startLogging() { - queue.sync { - guard isLogging == false else { return } - isLogging = true - } + guard !isLogging else { return } + isLogging = true Networking.instance.logsPublisher - .sink { log in - self.queue.sync { + .sink { [weak self] log in + self?.queue.sync { switch log { case .error(let log): SentrySDK.capture(error: LoggingError.networking(log.aggregated)) case .warn(let log): - SentrySDK.capture(message: log.aggregated) + // Example of setting level to warning + var event = Event(level: .warning) + event.message = SentryMessage(formatted: log.aggregated) + SentrySDK.capture(event: event) default: return } From d28e88c796b3284e078e7bb191d39005afb29629 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Sep 2023 10:23:44 +0100 Subject: [PATCH 27/32] cleanup --- .../Wallet/PushMessages/PushMessagesPresenter.swift | 10 ---------- Sources/Web3Inbox/WebView/WebViewProxy.swift | 1 - 2 files changed, 11 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift index 5730870a7..1c725aec6 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/PushMessages/PushMessagesPresenter.swift @@ -14,16 +14,6 @@ final class PushMessagesPresenter: ObservableObject { defer { reloadPushMessages() } self.interactor = interactor self.router = router - setUpMessagesRefresh() - } - - private func setUpMessagesRefresh() { - Timer.publish(every: 60.0, on: .main, in: .default) - .autoconnect() - .sink { [weak self] _ in - self?.reloadPushMessages() - } - .store(in: &disposeBag) } func deletePushMessage(at indexSet: IndexSet) { diff --git a/Sources/Web3Inbox/WebView/WebViewProxy.swift b/Sources/Web3Inbox/WebView/WebViewProxy.swift index ad513ed2d..5f4612701 100644 --- a/Sources/Web3Inbox/WebView/WebViewProxy.swift +++ b/Sources/Web3Inbox/WebView/WebViewProxy.swift @@ -20,7 +20,6 @@ actor WebViewProxy { func respond(_ response: RPCResponse, _ request: RPCRequest) async throws { let body = try response.json(dateEncodingStrategy: .millisecondsSince1970) let logProperties: [String: String] = ["method": request.method, "requestId": "\(request.id!)", "response": body] - print(logProperties) logger.debug("resonding to w3i request \(request.method) with \(body)", properties: logProperties) let script = scriptFormatter.formatScript(body: body) webView.evaluateJavaScript(script, completionHandler: nil) From 7f2fa52e80198ddd60cc8ee3198748236b845e1b Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 1 Sep 2023 19:18:26 +0800 Subject: [PATCH 28/32] Sync removed from Notify --- .../IntegrationTests/Push/NotifyTests.swift | 114 +++++++------- Package.swift | 2 +- .../DeleteNotifySubscriptionService.swift | 6 +- .../Client/Wallet/NotifyClient.swift | 23 +-- .../Client/Wallet/NotifyClientFactory.swift | 15 +- .../Client/Wallet/NotifyStorage.swift | 62 +++----- .../NotifySubscriptionStoreDelegate.swift | 32 ---- .../Client/Wallet/NotifySyncService.swift | 148 ------------------ .../NotifyUpdateResponseSubscriber.swift | 12 +- .../NotifySubscribeResponseSubscriber.swift | 2 +- Sources/WalletConnectNotify/Notify.swift | 2 - .../WalletConnectNotify/NotifyImports.swift | 3 +- 12 files changed, 93 insertions(+), 328 deletions(-) delete mode 100644 Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionStoreDelegate.swift delete mode 100644 Sources/WalletConnectNotify/Client/Wallet/NotifySyncService.swift diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index 10dc8e061..965c56f5a 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -9,8 +9,6 @@ import WalletConnectNetworking import WalletConnectPush @testable import WalletConnectNotify @testable import WalletConnectPairing -@testable import WalletConnectSync -@testable import WalletConnectHistory import WalletConnectIdentity import WalletConnectSigner @@ -22,8 +20,6 @@ final class NotifyTests: XCTestCase { let gmDappUrl = "https://notify.gm.walletconnect.com/" - var pairingStorage: PairingStorage! - let pk = try! EthereumPrivateKey() var privateKey: Data { @@ -34,9 +30,9 @@ final class NotifyTests: XCTestCase { return Account("eip155:1:" + pk.address.hex(eip55: true))! } - private var publishers = [AnyCancellable]() + private var publishers = Set() - func makeClientDependencies(prefix: String) -> (PairingClient, NetworkInteracting, SyncClient, KeychainStorageProtocol, KeyValueStorage) { + func makeClientDependencies(prefix: String) -> (PairingClient, NetworkInteracting, KeychainStorageProtocol, KeyValueStorage) { let keychain = KeychainStorageMock() let keyValueStorage = RuntimeKeyValueStorage() @@ -64,16 +60,14 @@ final class NotifyTests: XCTestCase { keychainStorage: keychain, networkingClient: networkingClient) - let syncClient = SyncClientFactory.create(networkInteractor: networkingClient, bip44: DefaultBIP44Provider(), keychain: keychain) - let clientId = try! networkingClient.getClientId() networkingLogger.debug("My client id is: \(clientId)") - return (pairingClient, networkingClient, syncClient, keychain, keyValueStorage) + return (pairingClient, networkingClient, keychain, keyValueStorage) } func makeWalletClients() { let prefix = "🦋 Wallet: " - let (pairingClient, networkingInteractor, syncClient, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) + let (pairingClient, networkingInteractor, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) let notifyLogger = ConsoleLogger(prefix: prefix + " [Notify]", loggingLevel: .debug) walletPairingClient = pairingClient let pushClient = PushClientFactory.create(projectId: "", @@ -81,11 +75,6 @@ final class NotifyTests: XCTestCase { keychainStorage: keychain, environment: .sandbox) let keyserverURL = URL(string: "https://keys.walletconnect.com")! - let historyClient = HistoryClientFactory.create( - historyUrl: "https://history.walletconnect.com", - relayUrl: "wss://relay.walletconnect.com", - keychain: keychain - ) walletNotifyClient = NotifyClientFactory.create(keyserverURL: keyserverURL, logger: notifyLogger, keyValueStorage: keyValueStorage, @@ -94,8 +83,6 @@ final class NotifyTests: XCTestCase { networkInteractor: networkingInteractor, pairingRegisterer: pairingClient, pushClient: pushClient, - syncClient: syncClient, - historyClient: historyClient, crypto: DefaultCryptoProvider()) } @@ -106,15 +93,18 @@ 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: []) + + walletNotifyClient.newSubscriptionPublisher + .sink { [unowned self] subscription in + Task(priority: .high) { + try! await walletNotifyClient.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, onSign: sign) - walletNotifyClient.subscriptionsPublisher - .first() - .sink { [unowned self] subscriptions in - XCTAssertNotNil(subscriptions.first) - Task { try! await walletNotifyClient.deleteSubscription(topic: subscriptions.first!.topic) } - expectation.fulfill() - }.store(in: &publishers) + wait(for: [expectation], timeout: InputConfig.defaultTimeout) } @@ -124,55 +114,57 @@ final class NotifyTests: XCTestCase { let updateScope: Set = ["alerts"] try! await walletNotifyClient.register(account: account, onSign: sign) try! await walletNotifyClient.subscribe(metadata: metadata, account: account, onSign: sign) - walletNotifyClient.subscriptionsPublisher - .first() - .sink { [unowned self] subscriptions in - sleep(1) - Task { try! await walletNotifyClient.update(topic: subscriptions.first!.topic, scope: updateScope) } + walletNotifyClient.newSubscriptionPublisher + .sink { [unowned self] subscription in + Task(priority: .high) { + try! await walletNotifyClient.update(topic: subscription.topic, scope: updateScope) + } } .store(in: &publishers) walletNotifyClient.updateSubscriptionPublisher - .sink { [unowned self] result in - guard case .success(let subscription) = result else { XCTFail(); return } + .sink { [unowned self] subscription in let updatedScope = Set(subscription.scope.filter{ $0.value.enabled == true }.keys) XCTAssertEqual(updatedScope, updateScope) - Task { try! await walletNotifyClient.deleteSubscription(topic: subscription.topic) } - expectation.fulfill() + Task(priority: .high) { + try! await walletNotifyClient.deleteSubscription(topic: subscription.topic) + expectation.fulfill() + } }.store(in: &publishers) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } -// func testNotifyServerSubscribeAndNotifies() async throws { -// let subscribeExpectation = expectation(description: "creates notify subscription") -// let messageExpectation = expectation(description: "receives a notify message") -// 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, onSign: sign) -// var subscription: NotifySubscription! -// walletNotifyClient.subscriptionsPublisher -// .first() -// .sink { subscriptions in -// XCTAssertNotNil(subscriptions.first) -// subscribeExpectation.fulfill() -// subscription = subscriptions.first! -// let notifier = Publisher() -// sleep(5) -// Task(priority: .high) { try await notifier.notify(topic: subscriptions.first!.topic, account: subscriptions.first!.account, message: notifyMessage) } -// }.store(in: &publishers) -// walletNotifyClient.notifyMessagePublisher -// .sink { notifyMessageRecord in -// XCTAssertEqual(notifyMessage, notifyMessageRecord.message) -// messageExpectation.fulfill() -// }.store(in: &publishers) -// -// wait(for: [subscribeExpectation, messageExpectation], timeout: InputConfig.defaultTimeout) -// try await walletNotifyClient.deleteSubscription(topic: subscription.topic) -// } + func testNotifyServerSubscribeAndNotifies() async throws { + let subscribeExpectation = expectation(description: "creates notify subscription") + let messageExpectation = expectation(description: "receives a notify message") + 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, onSign: sign) + + walletNotifyClient.newSubscriptionPublisher + .sink { subscription in + let notifier = Publisher() + Task(priority: .high) { + try await notifier.notify(topic: subscription.topic, account: subscription.account, message: notifyMessage) + subscribeExpectation.fulfill() + } + }.store(in: &publishers) + + walletNotifyClient.notifyMessagePublisher + .sink { [unowned self] notifyMessageRecord in + XCTAssertEqual(notifyMessage, notifyMessageRecord.message) + Task(priority: .high) { + try await walletNotifyClient.deleteSubscription(topic: notifyMessageRecord.topic) + messageExpectation.fulfill() + } + }.store(in: &publishers) + + wait(for: [subscribeExpectation, messageExpectation], timeout: InputConfig.defaultTimeout) + } } diff --git a/Package.swift b/Package.swift index dc111f0dd..8815d2a74 100644 --- a/Package.swift +++ b/Package.swift @@ -77,7 +77,7 @@ let package = Package( path: "Sources/Web3Wallet"), .target( name: "WalletConnectNotify", - dependencies: ["WalletConnectPairing", "WalletConnectPush", "WalletConnectIdentity", "WalletConnectSync", "WalletConnectHistory"], + dependencies: ["WalletConnectPairing", "WalletConnectPush", "WalletConnectIdentity", "WalletConnectSigner"], path: "Sources/WalletConnectNotify"), .target( name: "WalletConnectPush", diff --git a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift b/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift index cef34a689..fc4a361fd 100644 --- a/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift +++ b/Sources/WalletConnectNotify/Client/Common/DeleteNotifySubscriptionService.swift @@ -36,9 +36,6 @@ class DeleteNotifySubscriptionService { guard let subscription = notifyStorage.getSubscription(topic: topic) else { throw Errors.notifySubscriptionNotFound} - try await notifyStorage.deleteSubscription(topic: topic) - notifyStorage.deleteMessages(topic: topic) - let protocolMethod = NotifyDeleteProtocolMethod() let dappPubKey = try await webDidResolver.resolvePublicKey(dappUrl: subscription.metadata.url) @@ -52,7 +49,8 @@ class DeleteNotifySubscriptionService { let request = RPCRequest(method: protocolMethod.method, params: wrapper) try await networkingInteractor.request(request, topic: topic, protocolMethod: protocolMethod) - try await notifyStorage.deleteSubscription(topic: topic) + try notifyStorage.deleteSubscription(topic: topic) + notifyStorage.deleteMessages(topic: topic) networkingInteractor.unsubscribe(topic: topic) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 99ba78a9c..6ef82ad5b 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -26,8 +26,8 @@ public class NotifyClient { return notifyMessageSubscriber.notifyMessagePublisher } - public var updateSubscriptionPublisher: AnyPublisher, Never> { - return notifyUpdateResponseSubscriber.updateSubscriptionPublisher + public var updateSubscriptionPublisher: AnyPublisher { + return notifyStorage.updateSubscriptionPublisher } private let deleteNotifySubscriptionService: DeleteNotifySubscriptionService @@ -36,8 +36,8 @@ public class NotifyClient { public let logger: ConsoleLogging private let pushClient: PushClient + private let identityClient: IdentityClient private let notifyStorage: NotifyStorage - private let notifySyncService: NotifySyncService private let notifyMessageSubscriber: NotifyMessageSubscriber private let resubscribeService: NotifyResubscribeService private let notifySubscribeResponseSubscriber: NotifySubscribeResponseSubscriber @@ -48,10 +48,10 @@ public class NotifyClient { init(logger: ConsoleLogging, kms: KeyManagementServiceProtocol, + identityClient: IdentityClient, pushClient: PushClient, notifyMessageSubscriber: NotifyMessageSubscriber, notifyStorage: NotifyStorage, - notifySyncService: NotifySyncService, deleteNotifySubscriptionService: DeleteNotifySubscriptionService, resubscribeService: NotifyResubscribeService, notifySubscribeRequester: NotifySubscribeRequester, @@ -63,9 +63,9 @@ public class NotifyClient { ) { self.logger = logger self.pushClient = pushClient + self.identityClient = identityClient self.notifyMessageSubscriber = notifyMessageSubscriber self.notifyStorage = notifyStorage - self.notifySyncService = notifySyncService self.deleteNotifySubscriptionService = deleteNotifySubscriptionService self.resubscribeService = resubscribeService self.notifySubscribeRequester = notifySubscribeRequester @@ -77,11 +77,8 @@ public class NotifyClient { } public func register(account: Account, onSign: @escaping SigningCallback) async throws { - try await notifySyncService.registerSyncIfNeeded(account: account, onSign: onSign) - try await notifySyncService.registerIdentity(account: account, onSign: onSign) - try await notifyStorage.initialize(account: account) - try await notifyStorage.subscribe(account: account) - try await notifySyncService.fetchHistoryIfNeeded(account: account) + _ = try await identityClient.register(account: account, onSign: onSign) + } public func subscribe(metadata: AppMetadata, account: Account, onSign: @escaping SigningCallback) async throws { @@ -113,11 +110,7 @@ public class NotifyClient { } public func isIdentityRegistered(account: Account) -> Bool { - return notifySyncService.isIdentityRegistered(account: account) - } - - public func isSyncRegistered(account: Account) -> Bool { - return notifySyncService.isSyncRegistered(account: account) + return identityClient.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 2e15e4266..4a2724fd6 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -2,7 +2,7 @@ import Foundation public struct NotifyClientFactory { - public static func create(networkInteractor: NetworkInteracting, pairingRegisterer: PairingRegisterer, pushClient: PushClient, syncClient: SyncClient, historyClient: HistoryClient, crypto: CryptoProvider) -> NotifyClient { + public static func create(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")! @@ -18,8 +18,6 @@ public struct NotifyClientFactory { networkInteractor: networkInteractor, pairingRegisterer: pairingRegisterer, pushClient: pushClient, - syncClient: syncClient, - historyClient: historyClient, crypto: crypto ) } @@ -33,18 +31,13 @@ public struct NotifyClientFactory { networkInteractor: NetworkInteracting, pairingRegisterer: PairingRegisterer, pushClient: PushClient, - syncClient: SyncClient, - historyClient: HistoryClient, crypto: CryptoProvider ) -> NotifyClient { let kms = KeyManagementService(keychain: keychainStorage) - let subscriptionStore: SyncStore = SyncStoreFactory.create(name: NotifyStorageIdntifiers.notifySubscription, syncClient: syncClient, storage: keyValueStorage) - let subscriptionStoreDelegate = NotifySubscriptionStoreDelegate(networkingInteractor: networkInteractor, kms: kms, groupKeychainStorage: groupKeychainStorage) + let subscriptionStore = KeyedDatabase(storage: keyValueStorage, identifier: NotifyStorageIdntifiers.notifySubscription) let messagesStore = KeyedDatabase(storage: keyValueStorage, identifier: NotifyStorageIdntifiers.notifyMessagesRecords) - let notifyStorage = NotifyStorage(subscriptionStore: subscriptionStore, messagesStore: messagesStore, subscriptionStoreDelegate: subscriptionStoreDelegate) - let coldStartStore = CodableStore(defaults: keyValueStorage, identifier: NotifyStorageIdntifiers.coldStartStore) + let notifyStorage = NotifyStorage(subscriptionStore: subscriptionStore, messagesStore: messagesStore) let identityClient = IdentityClientFactory.create(keyserver: keyserverURL, keychain: keychainStorage, logger: logger) - let notifySyncService = NotifySyncService(syncClient: syncClient, logger: logger, historyClient: historyClient, identityClient: identityClient, subscriptionsStore: subscriptionStore, messagesStore: messagesStore, networkingInteractor: networkInteractor, kms: kms, coldStartStore: coldStartStore, groupKeychainStorage: groupKeychainStorage) 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) @@ -68,10 +61,10 @@ public struct NotifyClientFactory { return NotifyClient( logger: logger, kms: kms, + identityClient: identityClient, pushClient: pushClient, notifyMessageSubscriber: notifyMessageSubscriber, notifyStorage: notifyStorage, - notifySyncService: notifySyncService, deleteNotifySubscriptionService: deleteNotifySubscriptionService, resubscribeService: resubscribeService, notifySubscribeRequester: notifySubscribeRequester, diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift index 9ef73a705..ebc55c784 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyStorage.swift @@ -12,16 +12,15 @@ final class NotifyStorage: NotifyStoring { private var publishers = Set() - private let subscriptionStore: SyncStore + private let subscriptionStore: KeyedDatabase private let messagesStore: KeyedDatabase private let newSubscriptionSubject = PassthroughSubject() private let updateSubscriptionSubject = PassthroughSubject() private let deleteSubscriptionSubject = PassthroughSubject() + private let subscriptionsSubject = PassthroughSubject<[NotifySubscription], Never>() private let messagesSubject = PassthroughSubject<[NotifyMessageRecord], Never>() - private let subscriptionStoreDelegate: NotifySubscriptionStoreDelegate - var newSubscriptionPublisher: AnyPublisher { return newSubscriptionSubject.eraseToAnyPublisher() } @@ -35,33 +34,18 @@ final class NotifyStorage: NotifyStoring { } var subscriptionsPublisher: AnyPublisher<[NotifySubscription], Never> { - return subscriptionStore.dataUpdatePublisher + return subscriptionsSubject.eraseToAnyPublisher() } var messagesPublisher: AnyPublisher<[NotifyMessageRecord], Never> { return messagesSubject.eraseToAnyPublisher() } - init( - subscriptionStore: SyncStore, - messagesStore: KeyedDatabase, - subscriptionStoreDelegate: NotifySubscriptionStoreDelegate - ) { + init(subscriptionStore: KeyedDatabase, messagesStore: KeyedDatabase) { self.subscriptionStore = subscriptionStore self.messagesStore = messagesStore - self.subscriptionStoreDelegate = subscriptionStoreDelegate - setupSubscriptions() - } - - // MARK: Configuration - - func initialize(account: Account) async throws { - try await subscriptionStore.create(for: account) - try subscriptionStore.setupDatabaseSubscriptions(account: account) - } - func subscribe(account: Account) async throws { - try await subscriptionStore.subscribe(for: account) + setupSubscriptions() } // MARK: Subscriptions @@ -71,23 +55,26 @@ final class NotifyStorage: NotifyStoring { } func getSubscription(topic: String) -> NotifySubscription? { - return subscriptionStore.get(for: topic) + return subscriptionStore.getAll().first(where: { $0.topic == topic }) } - func setSubscription(_ subscription: NotifySubscription) async throws { - try await subscriptionStore.set(object: subscription, for: subscription.account) + func setSubscription(_ subscription: NotifySubscription) { + subscriptionStore.set(element: subscription, for: subscription.account.absoluteString) newSubscriptionSubject.send(subscription) } - func deleteSubscription(topic: String) async throws { - try await subscriptionStore.delete(id: topic) + func deleteSubscription(topic: String) throws { + guard let subscription = getSubscription(topic: topic) else { + throw Errors.subscriptionNotFound + } + subscriptionStore.delete(id: topic, for: subscription.account.absoluteString) deleteSubscriptionSubject.send(topic) } - func updateSubscription(_ subscription: NotifySubscription, scope: [String: ScopeValue], expiry: UInt64) async throws { + func updateSubscription(_ subscription: NotifySubscription, scope: [String: ScopeValue], expiry: UInt64) { let expiry = Date(timeIntervalSince1970: TimeInterval(expiry)) let updated = NotifySubscription(topic: subscription.topic, account: subscription.account, relay: subscription.relay, metadata: subscription.metadata, scope: scope, expiry: expiry, symKey: subscription.symKey) - try await setSubscription(updated) + subscriptionStore.set(element: updated, for: updated.account.absoluteString) updateSubscriptionSubject.send(updated) } @@ -120,22 +107,17 @@ final class NotifyStorage: NotifyStoring { private extension NotifyStorage { + enum Errors: Error { + case subscriptionNotFound + } + func setupSubscriptions() { messagesStore.onUpdate = { [unowned self] in messagesSubject.send(messagesStore.getAll()) } - subscriptionStore.syncUpdatePublisher.sink { [unowned self] (_, _, update) in - switch update { - case .set(let subscription): - subscriptionStoreDelegate.onUpdate(subscription) - newSubscriptionSubject.send(subscription) - case .delete(let object): - subscriptionStoreDelegate.onDelete(object, notifyStorage: self) - deleteSubscriptionSubject.send(object.topic) - case .update(let subscription): - newSubscriptionSubject.send(subscription) - } - }.store(in: &publishers) + subscriptionStore.onUpdate = { [unowned self] in + subscriptionsSubject.send(subscriptionStore.getAll()) + } } } diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionStoreDelegate.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionStoreDelegate.swift deleted file mode 100644 index 77a2c1a4d..000000000 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifySubscriptionStoreDelegate.swift +++ /dev/null @@ -1,32 +0,0 @@ -import Foundation - -final class NotifySubscriptionStoreDelegate { - - private let networkingInteractor: NetworkInteracting - private let kms: KeyManagementServiceProtocol - private let groupKeychainStorage: KeychainStorageProtocol - - init(networkingInteractor: NetworkInteracting, kms: KeyManagementServiceProtocol, groupKeychainStorage: KeychainStorageProtocol) { - self.networkingInteractor = networkingInteractor - self.kms = kms - self.groupKeychainStorage = groupKeychainStorage - } - - func onUpdate(_ subscription: NotifySubscription) { - Task(priority: .high) { - let symmetricKey = try SymmetricKey(hex: subscription.symKey) - try kms.setSymmetricKey(symmetricKey, for: subscription.topic) - try groupKeychainStorage.add(symmetricKey, forKey: subscription.topic) - try await networkingInteractor.subscribe(topic: subscription.topic) - } - } - - func onDelete(_ subscription: NotifySubscription, notifyStorage: NotifyStorage) { - Task(priority: .high) { - kms.deleteSymmetricKey(for: subscription.topic) - try? groupKeychainStorage.delete(key: subscription.topic) - networkingInteractor.unsubscribe(topic: subscription.topic) - notifyStorage.deleteMessages(topic: subscription.topic) - } - } -} diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifySyncService.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifySyncService.swift deleted file mode 100644 index ecd67c72b..000000000 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifySyncService.swift +++ /dev/null @@ -1,148 +0,0 @@ -import Foundation - -final class NotifySyncService { - - private let syncClient: SyncClient - private let historyClient: HistoryClient - private let identityClient: IdentityClient - private let logger: ConsoleLogging - private let subscriptionsStore: SyncStore - private let messagesStore: KeyedDatabase - private let networkingInteractor: NetworkInteracting - private let kms: KeyManagementServiceProtocol - private let coldStartStore: CodableStore - private let groupKeychainStorage: KeychainStorageProtocol - - init( - syncClient: SyncClient, - logger: ConsoleLogging, - historyClient: HistoryClient, - identityClient: IdentityClient, - subscriptionsStore: SyncStore, - messagesStore: KeyedDatabase, - networkingInteractor: NetworkInteracting, - kms: KeyManagementServiceProtocol, - coldStartStore: CodableStore, - groupKeychainStorage: KeychainStorageProtocol - ) { - self.syncClient = syncClient - self.logger = logger - self.historyClient = historyClient - self.identityClient = identityClient - self.subscriptionsStore = subscriptionsStore - self.messagesStore = messagesStore - self.networkingInteractor = networkingInteractor - self.kms = kms - self.coldStartStore = coldStartStore - self.groupKeychainStorage = groupKeychainStorage - } - - func registerIdentity(account: Account, onSign: @escaping SigningCallback) async throws { - _ = try await identityClient.register(account: account, onSign: onSign) - } - - func registerSyncIfNeeded(account: Account, onSign: @escaping SigningCallback) async throws { - guard !syncClient.isRegistered(account: account) else { return } - - let result = await onSign(syncClient.getMessage(account: account)) - - switch result { - case .signed(let signature): - try await syncClient.register(account: account, signature: signature) - logger.debug("Sync notifySubscriptions store registered and initialized") - case .rejected: - throw NotifyError.registerSignatureRejected - } - } - - func fetchHistoryIfNeeded(account: Account) async throws { - guard try isColdStart(account: account) else { return } - - try await historyClient.register(tags: [ - "5000", // sync_set - "5002", // sync_delete - "4002" // notify_message - ]) - - let syncTopic = try subscriptionsStore.getStoreTopic(account: account) - - let updates: [StoreSetDelete] = try await historyClient.getMessages( - topic: syncTopic, - count: 200, - direction: .backward - ) - - let inserts: [NotifySubscription] = updates.compactMap { update in - guard let value = update.value else { return nil } - return try? JSONDecoder().decode(NotifySubscription.self, from: Data(value.utf8)) - } - - let deletions: [String] = updates.compactMap { update in - guard update.value == nil else { return nil } - return update.key - } - - let subscriptions = inserts.filter { !deletions.contains( $0.databaseId ) } - - logger.debug("Received object from history: \(subscriptions)") - - try subscriptionsStore.replaceInStore(objects: subscriptions, for: account) - - for subscription in subscriptions { - let symmetricKey = try SymmetricKey(hex: subscription.symKey) - try kms.setSymmetricKey(symmetricKey, for: subscription.topic) - try groupKeychainStorage.add(symmetricKey, forKey: subscription.topic) - try await networkingInteractor.subscribe(topic: subscription.topic) - - let historyRecords: [HistoryRecord] = try await historyClient.getRecords( - topic: subscription.topic, - count: 200, - direction: .backward - ) - - let messageRecords = historyRecords.compactMap { record in - guard - let (messagePayload, _) = try? NotifyMessagePayload.decodeAndVerify(from: record.object) - else { fatalError() /* TODO: Handle error */ } - - return NotifyMessageRecord( - id: record.id.string, - topic: subscription.topic, - message: messagePayload.message, - publishedAt: Date() - ) - } - - messagesStore.set(elements: messageRecords, for: subscription.topic) - } - - coldStartStore.set(Date(), forKey: account.absoluteString) - } - - func isIdentityRegistered(account: Account) -> Bool { - return identityClient.isIdentityRegistered(account: account) - } - - func isSyncRegistered(account: Account) -> Bool { - return syncClient.isRegistered(account: account) - } -} - -private extension NotifySyncService { - - struct StoreSetDelete: Codable, Equatable { - let key: String - let value: String? - } - - func isColdStart(account: Account) throws -> Bool { - guard let lastFetch = try coldStartStore.get(key: account.absoluteString) else { - return true - } - guard let days = Calendar.current.dateComponents([.day], from: lastFetch, to: Date()).day else { - return true - } - - return days >= 30 - } -} diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift index 0b84e961d..ce74dea16 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_notifyUpdate/NotifyUpdateResponseSubscriber.swift @@ -7,10 +7,6 @@ class NotifyUpdateResponseSubscriber { private let logger: ConsoleLogging private let notifyStorage: NotifyStorage private let subscriptionScopeProvider: SubscriptionScopeProvider - private var subscriptionPublisherSubject = PassthroughSubject, Never>() - var updateSubscriptionPublisher: AnyPublisher, Never> { - return subscriptionPublisherSubject.eraseToAnyPublisher() - } init(networkingInteractor: NetworkInteracting, logger: ConsoleLogging, @@ -49,16 +45,10 @@ private extension NotifyUpdateResponseSubscriber { guard let oldSubscription = notifyStorage.getSubscription(topic: subscriptionTopic) else { logger.debug("NotifyUpdateResponseSubscriber Subscription does not exist") - subscriptionPublisherSubject.send(.failure(Errors.subscriptionDoesNotExist)) return } - let expiry = Date(timeIntervalSince1970: TimeInterval(requestClaims.exp)) - - let updatedSubscription = NotifySubscription(topic: subscriptionTopic, account: oldSubscription.account, relay: oldSubscription.relay, metadata: oldSubscription.metadata, scope: scope, expiry: expiry, symKey: oldSubscription.symKey) - - try await notifyStorage.setSubscription(updatedSubscription) - subscriptionPublisherSubject.send(.success(updatedSubscription)) + notifyStorage.updateSubscription(oldSubscription, scope: scope, expiry: requestClaims.exp) logger.debug("Updated Subscription") } diff --git a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift index 48d32401b..9577413f2 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/ProtocolEngine/wc_pushSubscribe/NotifySubscribeResponseSubscriber.swift @@ -93,7 +93,7 @@ class NotifySubscribeResponseSubscriber { 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) diff --git a/Sources/WalletConnectNotify/Notify.swift b/Sources/WalletConnectNotify/Notify.swift index 129291010..3a8a0bb14 100644 --- a/Sources/WalletConnectNotify/Notify.swift +++ b/Sources/WalletConnectNotify/Notify.swift @@ -10,8 +10,6 @@ public class Notify { networkInteractor: Networking.interactor, pairingRegisterer: Pair.registerer, pushClient: Push.instance, - syncClient: Sync.instance, - historyClient: History.instance, crypto: config.crypto ) }() diff --git a/Sources/WalletConnectNotify/NotifyImports.swift b/Sources/WalletConnectNotify/NotifyImports.swift index 1c0a1db16..74fcfa250 100644 --- a/Sources/WalletConnectNotify/NotifyImports.swift +++ b/Sources/WalletConnectNotify/NotifyImports.swift @@ -2,6 +2,5 @@ @_exported import WalletConnectPairing @_exported import WalletConnectPush @_exported import WalletConnectIdentity -@_exported import WalletConnectSync -@_exported import WalletConnectHistory +@_exported import WalletConnectSigner #endif From 62607306758520c2cce3f087aaf3e8030485794e Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 1 Sep 2023 19:20:24 +0800 Subject: [PATCH 29/32] Web3Inbox fix --- .../NotifyClientRequestSubscriber.swift | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequestSubscriber.swift b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequestSubscriber.swift index 73b85c486..8b255bd81 100644 --- a/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequestSubscriber.swift +++ b/Sources/Web3Inbox/NotifyClientProxy/NotifyClientRequestSubscriber.swift @@ -30,14 +30,8 @@ final class NotifyClientRequestSubscriber { handle(event: .notifyDelete, params: topic) }.store(in: &publishers) - client.updateSubscriptionPublisher.sink { [unowned self] record in - switch record { - case .success(let subscription): - handle(event: .notifyUpdate, params: subscription) - case .failure: - //TODO - handle error - break - } + client.updateSubscriptionPublisher.sink { [unowned self] subscription in + handle(event: .notifyUpdate, params: subscription) }.store(in: &publishers) } } From c4a0eb2d9bffc072993844049cd4ae5c9d1faf8f Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 1 Sep 2023 19:34:25 +0800 Subject: [PATCH 30/32] Space removed --- Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 6ef82ad5b..b35e4e41b 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -78,7 +78,6 @@ public class NotifyClient { public func register(account: Account, onSign: @escaping SigningCallback) async throws { _ = try await identityClient.register(account: account, onSign: onSign) - } public func subscribe(metadata: AppMetadata, account: Account, onSign: @escaping SigningCallback) async throws { From 1d08e85078b5933d174cb5a1c8af35a420647c0b Mon Sep 17 00:00:00 2001 From: llbartekll Date: Sat, 2 Sep 2023 11:33:23 +0000 Subject: [PATCH 31/32] 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 86f515d51..b0a94210e 100644 --- a/Sources/WalletConnectRelay/PackageConfig.json +++ b/Sources/WalletConnectRelay/PackageConfig.json @@ -1 +1 @@ -{"version": "1.7.0"} +{"version": "1.7.1"} From d89e0bec0de8bab35d4429a997d8837bc4b6ec0c Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sat, 2 Sep 2023 12:40:48 +0100 Subject: [PATCH 32/32] add more logs --- .../Client/Common/NotifyResubscribeService.swift | 5 ++++- .../Client/Wallet/NotifyClientFactory.swift | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectNotify/Client/Common/NotifyResubscribeService.swift b/Sources/WalletConnectNotify/Client/Common/NotifyResubscribeService.swift index 4d48f7a7c..80fbd12ec 100644 --- a/Sources/WalletConnectNotify/Client/Common/NotifyResubscribeService.swift +++ b/Sources/WalletConnectNotify/Client/Common/NotifyResubscribeService.swift @@ -4,13 +4,15 @@ import Combine final class NotifyResubscribeService { private var publishers = Set() + private let logger: ConsoleLogging private let networkInteractor: NetworkInteracting private let notifyStorage: NotifyStorage - init(networkInteractor: NetworkInteracting, notifyStorage: NotifyStorage) { + init(networkInteractor: NetworkInteracting, notifyStorage: NotifyStorage, logger: ConsoleLogging) { self.networkInteractor = networkInteractor self.notifyStorage = notifyStorage + self.logger = logger setUpResubscription() } @@ -19,6 +21,7 @@ final class NotifyResubscribeService { .sink { [unowned self] status in guard status == .connected else { return } let topics = notifyStorage.getSubscriptions().map{$0.topic} + logger.debug("Resubscribing to notify subscription topics: \(topics)", properties: ["topics": topics.joined(separator: ", ")]) Task(priority: .high) { try await networkInteractor.batchSubscribe(topics: topics) } diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift index 2e15e4266..f032473cc 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClientFactory.swift @@ -48,7 +48,7 @@ public struct NotifyClientFactory { 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 resubscribeService = NotifyResubscribeService(networkInteractor: networkInteractor, notifyStorage: notifyStorage) + let resubscribeService = NotifyResubscribeService(networkInteractor: networkInteractor, notifyStorage: notifyStorage, logger: logger) let dappsMetadataStore = CodableStore(defaults: keyValueStorage, identifier: NotifyStorageIdntifiers.dappsMetadataStore) let subscriptionScopeProvider = SubscriptionScopeProvider()