From 4def83f2c9286e8a4241b667da32869ebb6352f9 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 1 Feb 2023 11:29:50 +0100 Subject: [PATCH 01/42] add main module --- Example/ExampleApp.xcodeproj/project.pbxproj | 36 ++++++++++++++++++ .../Wallet/Main/MainModule.swift | 16 ++++++++ .../Wallet/Main/MainPresenter.swift | 22 +++++++++++ .../Wallet/Main/MainRouter.swift | 21 ++++++++++ .../Wallet/Main/MainViewController.swift | 38 +++++++++++++++++++ .../Wallet/Main/Model/TabPage.swift | 32 ++++++++++++++++ .../Wallet/Welcome/WelcomeRouter.swift | 5 +-- 7 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Main/MainViewController.swift create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 1c486bd81..67048c1e7 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -33,6 +33,11 @@ 84494388278D9C1B00CC26BB /* UIAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84494387278D9C1B00CC26BB /* UIAlertController.swift */; }; 845B8D8C2934B36C0084A966 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845B8D8B2934B36C0084A966 /* Account.swift */; }; 8460DCFC274F98A10081F94C /* RequestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8460DCFB274F98A10081F94C /* RequestViewController.swift */; }; + 847BD1D62989492500076C90 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D12989492500076C90 /* MainViewController.swift */; }; + 847BD1D82989492500076C90 /* MainModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D32989492500076C90 /* MainModule.swift */; }; + 847BD1D92989492500076C90 /* MainPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D42989492500076C90 /* MainPresenter.swift */; }; + 847BD1DA2989492500076C90 /* MainRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D52989492500076C90 /* MainRouter.swift */; }; + 847BD1DD2989494F00076C90 /* TabPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1DC2989494F00076C90 /* TabPage.swift */; }; 847CF3AF28E3141700F1D760 /* WalletConnectPush in Frameworks */ = {isa = PBXBuildFile; productRef = 847CF3AE28E3141700F1D760 /* WalletConnectPush */; settings = {ATTRIBUTES = (Required, ); }; }; 8485617D295079730064877B /* WalletConnectPairing in Frameworks */ = {isa = PBXBuildFile; productRef = 8485617C295079730064877B /* WalletConnectPairing */; }; 8485617F295307C20064877B /* PushNotificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8485617E295307C20064877B /* PushNotificationTests.swift */; }; @@ -364,6 +369,11 @@ 84494387278D9C1B00CC26BB /* UIAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAlertController.swift; sourceTree = ""; }; 845B8D8B2934B36C0084A966 /* Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = ""; }; 8460DCFB274F98A10081F94C /* RequestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestViewController.swift; sourceTree = ""; }; + 847BD1D12989492500076C90 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; + 847BD1D32989492500076C90 /* MainModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainModule.swift; sourceTree = ""; }; + 847BD1D42989492500076C90 /* MainPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainPresenter.swift; sourceTree = ""; }; + 847BD1D52989492500076C90 /* MainRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainRouter.swift; sourceTree = ""; }; + 847BD1DC2989494F00076C90 /* TabPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabPage.swift; sourceTree = ""; }; 8485617E295307C20064877B /* PushNotificationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationTests.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 = ""; }; @@ -801,6 +811,26 @@ path = SessionDetails; sourceTree = ""; }; + 847BD1DB2989493F00076C90 /* Main */ = { + isa = PBXGroup; + children = ( + 847BD1D32989492500076C90 /* MainModule.swift */, + 847BD1D42989492500076C90 /* MainPresenter.swift */, + 847BD1D52989492500076C90 /* MainRouter.swift */, + 847BD1D12989492500076C90 /* MainViewController.swift */, + 847BD1DE2989495C00076C90 /* Model */, + ); + path = Main; + sourceTree = ""; + }; + 847BD1DE2989495C00076C90 /* Model */ = { + isa = PBXGroup; + children = ( + 847BD1DC2989494F00076C90 /* TabPage.swift */, + ); + path = Model; + sourceTree = ""; + }; 849D7A91292E2115006A2BD4 /* Push */ = { isa = PBXGroup; children = ( @@ -1463,6 +1493,7 @@ C56EE229293F5668004840D1 /* Wallet */ = { isa = PBXGroup; children = ( + 847BD1DB2989493F00076C90 /* Main */, C55D3477295DD4AA0004314A /* Welcome */, C55D3474295DCB850004314A /* AuthRequest */, C55D349E2965FAC30004314A /* SessionProposal */, @@ -2174,19 +2205,23 @@ 84E6B8582981624F00428BAF /* PushRequestModule.swift in Sources */, C55D3480295DD7140004314A /* AuthRequestPresenter.swift in Sources */, 84E6B85B298162EF00428BAF /* PushRequestPresenter.swift in Sources */, + 847BD1DA2989492500076C90 /* MainRouter.swift in Sources */, C5F32A2E2954814A00A6476E /* ConnectionDetailsRouter.swift in Sources */, C55D3482295DD7140004314A /* AuthRequestInteractor.swift in Sources */, C55D34B12965FB750004314A /* SessionProposalInteractor.swift in Sources */, C56EE247293F566D004840D1 /* ScanModule.swift in Sources */, C56EE28D293F5757004840D1 /* AppearanceConfigurator.swift in Sources */, + 847BD1D82989492500076C90 /* MainModule.swift in Sources */, C5B2F7112970583B000DBA0E /* SessionInfo.swift in Sources */, C56EE241293F566D004840D1 /* WalletModule.swift in Sources */, C56EE245293F566D004840D1 /* WalletPresenter.swift in Sources */, C56EE240293F566D004840D1 /* ScanQRView.swift in Sources */, C56EE250293F566D004840D1 /* ScanTargetView.swift in Sources */, C56EE28F293F5757004840D1 /* MigrationConfigurator.swift in Sources */, + 847BD1DD2989494F00076C90 /* TabPage.swift in Sources */, C55D348B295DD8CA0004314A /* PasteUriRouter.swift in Sources */, C55D348C295DD8CA0004314A /* PasteUriInteractor.swift in Sources */, + 847BD1D92989492500076C90 /* MainPresenter.swift in Sources */, C55D3497295DFA750004314A /* WelcomeView.swift in Sources */, C5B2F71029705827000DBA0E /* EthereumTransaction.swift in Sources */, C56EE271293F56D7004840D1 /* View.swift in Sources */, @@ -2208,6 +2243,7 @@ C55D3483295DD7140004314A /* AuthRequestView.swift in Sources */, C56EE243293F566D004840D1 /* ScanView.swift in Sources */, C56EE288293F5757004840D1 /* ThirdPartyConfigurator.swift in Sources */, + 847BD1D62989492500076C90 /* MainViewController.swift in Sources */, C5B2F6FA29705293000DBA0E /* SessionRequestInteractor.swift in Sources */, C55D34AE2965FB750004314A /* SessionProposalModule.swift in Sources */, C55D34B02965FB750004314A /* SessionProposalRouter.swift in Sources */, diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift new file mode 100644 index 000000000..f60ff5d77 --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift @@ -0,0 +1,16 @@ +import SwiftUI + +final class MainModule { + + @discardableResult + static func create(app: Application) -> UIViewController { + let router = MainRouter(app: app) + let presenter = MainPresenter(router: router) + let viewController = MainViewController(presenter: presenter) + + router.viewController = viewController + + return viewController + } + +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift new file mode 100644 index 000000000..3c7165f27 --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift @@ -0,0 +1,22 @@ +import UIKit +import Combine + +final class MainPresenter { + + private let router: MainRouter + + var tabs: [TabPage] { + return TabPage.allCases + } + + var viewControllers: [UIViewController] { + return [ + router.walletViewController(), + router.notificationsViewController(), + ] + } + + init(router: MainRouter) { + self.router = router + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift new file mode 100644 index 000000000..62d1d0033 --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift @@ -0,0 +1,21 @@ +import UIKit + +final class MainRouter { + + weak var viewController: UIViewController! + + private let app: Application + + func walletViewController() -> UIViewController { + return WalletModule.create(app: app) + } + + func notificationsViewController() -> UIViewController { + return WalletModule.create(app: app) +// return Web3InboxModule.create(app: app, account: account).wrapToNavigationController() + } + + init(app: Application) { + self.app = app + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainViewController.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainViewController.swift new file mode 100644 index 000000000..5fd88ac40 --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainViewController.swift @@ -0,0 +1,38 @@ +import UIKit + +final class MainViewController: UITabBarController { + + private let presenter: MainPresenter + + init(presenter: MainPresenter) { + self.presenter = presenter + super.init(nibName: nil, bundle: nil) + } + + override func viewDidLoad() { + super.viewDidLoad() + + setupTabs() + } + + private func setupTabs() { + let viewControllers = presenter.viewControllers + + for (index, viewController) in viewControllers.enumerated() { + let model = presenter.tabs[index] + let item = UITabBarItem() + item.title = model.title + item.image = model.icon + item.isEnabled = TabPage.enabledTabs.contains(model) + viewController.tabBarItem = item + viewController.view.backgroundColor = .w_background + } + + self.viewControllers = viewControllers + self.selectedIndex = TabPage.selectedIndex + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift new file mode 100644 index 000000000..688099081 --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift @@ -0,0 +1,32 @@ +import UIKit + +enum TabPage: CaseIterable { + case wallet + case notifications + + var title: String { + switch self { + case .wallet: + return "Apps" + case .notifications: + return "Notifications" + } + } + + var icon: UIImage { + switch self { + case .wallet: + return UIImage(systemName: "message.fill")! + case .notifications: + return UIImage(systemName: "safari.fill")! + } + } + + static var selectedIndex: Int { + return 0 + } + + static var enabledTabs: [TabPage] { + return [.wallet, .notifications] + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Welcome/WelcomeRouter.swift b/Example/WalletApp/PresentationLayer/Wallet/Welcome/WelcomeRouter.swift index 9ebd6c7bf..e7c495e62 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Welcome/WelcomeRouter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Welcome/WelcomeRouter.swift @@ -10,8 +10,7 @@ final class WelcomeRouter { } func presentWallet() { - WalletModule.create(app: app) - .wrapToNavigationController() - .presentFullScreen(from: viewController) + MainModule.create(app: app) + .present() } } From 03865860fb759a3e27b42dc4c69e197f9b42857b Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 1 Feb 2023 11:47:31 +0100 Subject: [PATCH 02/42] update tab images --- .../PresentationLayer/Wallet/Main/Model/TabPage.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift index 688099081..0416f515c 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/Model/TabPage.swift @@ -16,9 +16,9 @@ enum TabPage: CaseIterable { var icon: UIImage { switch self { case .wallet: - return UIImage(systemName: "message.fill")! + return UIImage(systemName: "house.fill")! case .notifications: - return UIImage(systemName: "safari.fill")! + return UIImage(systemName: "bell.fill")! } } From 09c45244aefa5f3db1e4f384f263651676cf1b93 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 1 Feb 2023 13:08:09 +0100 Subject: [PATCH 03/42] add basic notifications list --- Example/ExampleApp.xcodeproj/project.pbxproj | 40 +++++++++ .../Wallet/Main/MainRouter.swift | 4 +- .../Models/SubscriptionsViewModel.swift | 18 ++++ .../NotificationsInteractor.swift | 8 ++ .../Notifications/NotificationsModule.swift | 18 ++++ .../NotificationsPresenter.swift | 53 ++++++++++++ .../Notifications/NotificationsRouter.swift | 17 ++++ .../Notifications/NotificationsView.swift | 85 +++++++++++++++++++ Makefile | 0 9 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsModule.swift create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsRouter.swift create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift mode change 100644 => 100755 Makefile diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 67048c1e7..aaa500ef6 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -38,6 +38,12 @@ 847BD1D92989492500076C90 /* MainPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D42989492500076C90 /* MainPresenter.swift */; }; 847BD1DA2989492500076C90 /* MainRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D52989492500076C90 /* MainRouter.swift */; }; 847BD1DD2989494F00076C90 /* TabPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1DC2989494F00076C90 /* TabPage.swift */; }; + 847BD1E4298A806800076C90 /* NotificationsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1DF298A806800076C90 /* NotificationsModule.swift */; }; + 847BD1E5298A806800076C90 /* NotificationsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1E0298A806800076C90 /* NotificationsPresenter.swift */; }; + 847BD1E6298A806800076C90 /* NotificationsRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1E1298A806800076C90 /* NotificationsRouter.swift */; }; + 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, ); }; }; 8485617D295079730064877B /* WalletConnectPairing in Frameworks */ = {isa = PBXBuildFile; productRef = 8485617C295079730064877B /* WalletConnectPairing */; }; 8485617F295307C20064877B /* PushNotificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8485617E295307C20064877B /* PushNotificationTests.swift */; }; @@ -374,6 +380,12 @@ 847BD1D42989492500076C90 /* MainPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainPresenter.swift; sourceTree = ""; }; 847BD1D52989492500076C90 /* MainRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainRouter.swift; sourceTree = ""; }; 847BD1DC2989494F00076C90 /* TabPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabPage.swift; sourceTree = ""; }; + 847BD1DF298A806800076C90 /* NotificationsModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsModule.swift; sourceTree = ""; }; + 847BD1E0298A806800076C90 /* NotificationsPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsPresenter.swift; sourceTree = ""; }; + 847BD1E1298A806800076C90 /* NotificationsRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsRouter.swift; sourceTree = ""; }; + 847BD1E2298A806800076C90 /* NotificationsInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsInteractor.swift; sourceTree = ""; }; + 847BD1E3298A806800076C90 /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = ""; }; + 847BD1EA298A87AB00076C90 /* SubscriptionsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsViewModel.swift; sourceTree = ""; }; 8485617E295307C20064877B /* PushNotificationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationTests.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 = ""; }; @@ -831,6 +843,27 @@ path = Model; sourceTree = ""; }; + 847BD1E9298A807000076C90 /* Notifications */ = { + isa = PBXGroup; + children = ( + 847BD1DF298A806800076C90 /* NotificationsModule.swift */, + 847BD1E0298A806800076C90 /* NotificationsPresenter.swift */, + 847BD1E1298A806800076C90 /* NotificationsRouter.swift */, + 847BD1E2298A806800076C90 /* NotificationsInteractor.swift */, + 847BD1E3298A806800076C90 /* NotificationsView.swift */, + 847BD1EC298A87C300076C90 /* Models */, + ); + path = Notifications; + sourceTree = ""; + }; + 847BD1EC298A87C300076C90 /* Models */ = { + isa = PBXGroup; + children = ( + 847BD1EA298A87AB00076C90 /* SubscriptionsViewModel.swift */, + ); + path = Models; + sourceTree = ""; + }; 849D7A91292E2115006A2BD4 /* Push */ = { isa = PBXGroup; children = ( @@ -1503,6 +1536,7 @@ C56EE236293F566A004840D1 /* Scan */, C56EE22A293F5668004840D1 /* Wallet */, 84E6B8592981625A00428BAF /* PushRequest */, + 847BD1E9298A807000076C90 /* Notifications */, ); path = Wallet; sourceTree = ""; @@ -2213,6 +2247,7 @@ C56EE28D293F5757004840D1 /* AppearanceConfigurator.swift in Sources */, 847BD1D82989492500076C90 /* MainModule.swift in Sources */, C5B2F7112970583B000DBA0E /* SessionInfo.swift in Sources */, + 847BD1E7298A806800076C90 /* NotificationsInteractor.swift in Sources */, C56EE241293F566D004840D1 /* WalletModule.swift in Sources */, C56EE245293F566D004840D1 /* WalletPresenter.swift in Sources */, C56EE240293F566D004840D1 /* ScanQRView.swift in Sources */, @@ -2220,6 +2255,7 @@ C56EE28F293F5757004840D1 /* MigrationConfigurator.swift in Sources */, 847BD1DD2989494F00076C90 /* TabPage.swift in Sources */, C55D348B295DD8CA0004314A /* PasteUriRouter.swift in Sources */, + 847BD1E4298A806800076C90 /* NotificationsModule.swift in Sources */, C55D348C295DD8CA0004314A /* PasteUriInteractor.swift in Sources */, 847BD1D92989492500076C90 /* MainPresenter.swift in Sources */, C55D3497295DFA750004314A /* WelcomeView.swift in Sources */, @@ -2238,6 +2274,7 @@ C55D3493295DFA750004314A /* WelcomeModule.swift in Sources */, C56EE270293F56D7004840D1 /* String.swift in Sources */, C56EE279293F56D7004840D1 /* Color.swift in Sources */, + 847BD1E6298A806800076C90 /* NotificationsRouter.swift in Sources */, 84E6B8612981630C00428BAF /* PushRequestView.swift in Sources */, 84E6B85F2981630000428BAF /* PushRequestInteractor.swift in Sources */, C55D3483295DD7140004314A /* AuthRequestView.swift in Sources */, @@ -2252,6 +2289,7 @@ C56EE24F293F566D004840D1 /* WalletView.swift in Sources */, C55D34B22965FB750004314A /* SessionProposalView.swift in Sources */, C56EE248293F566D004840D1 /* ScanQR.swift in Sources */, + 847BD1EB298A87AB00076C90 /* SubscriptionsViewModel.swift in Sources */, C55D349B2965BC2F0004314A /* TagsView.swift in Sources */, C56EE289293F5757004840D1 /* Application.swift in Sources */, C56EE273293F56D7004840D1 /* UIColor.swift in Sources */, @@ -2267,6 +2305,7 @@ 84DB38F32983CDAE00BFEE37 /* PushRegisterer.swift in Sources */, C5B2F6FB297055B0000DBA0E /* ETHSigner.swift in Sources */, C56EE274293F56D7004840D1 /* SceneViewController.swift in Sources */, + 847BD1E5298A806800076C90 /* NotificationsPresenter.swift in Sources */, C55D3496295DFA750004314A /* WelcomeInteractor.swift in Sources */, 84E6B85D298162F700428BAF /* PushRequestRouter.swift in Sources */, C5B2F6FC297055B0000DBA0E /* SOLSigner.swift in Sources */, @@ -2279,6 +2318,7 @@ C56EE24E293F566D004840D1 /* WalletInteractor.swift in Sources */, C55D34AF2965FB750004314A /* SessionProposalPresenter.swift in Sources */, C5F32A302954816100A6476E /* ConnectionDetailsInteractor.swift in Sources */, + 847BD1E8298A806800076C90 /* NotificationsView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift index 62d1d0033..2bf1c1888 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift @@ -11,8 +11,8 @@ final class MainRouter { } func notificationsViewController() -> UIViewController { - return WalletModule.create(app: app) -// return Web3InboxModule.create(app: app, account: account).wrapToNavigationController() + return NotificationsModule.create(app: app) + .wrapToNavigationController() } init(app: Application) { diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift new file mode 100644 index 000000000..0a511f3de --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift @@ -0,0 +1,18 @@ +import Foundation +import WalletConnectPush + +struct SubscriptionsViewModel: Identifiable { + let subscription: WalletConnectPush.PushSubscription + + var id: String { + return subscription.topic + } + + var title: String { + return subscription.metadata.name + } + + var subtitle: String { + return subscription.metadata.description + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift new file mode 100644 index 000000000..ff04ba809 --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift @@ -0,0 +1,8 @@ +import WalletConnectPush + +final class NotificationsInteractor { + + func getSubscriptions() -> [PushSubscription] { + Push.wallet.getActiveSubscriptions() + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsModule.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsModule.swift new file mode 100644 index 000000000..f7b2b620c --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsModule.swift @@ -0,0 +1,18 @@ +import SwiftUI + +final class NotificationsModule { + + @discardableResult + static func create(app: Application) -> UIViewController { + let router = NotificationsRouter(app: app) + let interactor = NotificationsInteractor() + let presenter = NotificationsPresenter(interactor: interactor, router: router) + let view = NotificationsView().environmentObject(presenter) + let viewController = SceneViewController(viewModel: presenter, content: view) + + router.viewController = viewController + + return viewController + } + +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift new file mode 100644 index 000000000..52c6aad03 --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift @@ -0,0 +1,53 @@ +import UIKit +import Combine + +final class NotificationsPresenter: ObservableObject { + + private let interactor: NotificationsInteractor + private let router: NotificationsRouter + private var disposeBag = Set() + + @Published var subscriptions: [SubscriptionsViewModel] = [] + + init(interactor: NotificationsInteractor, router: NotificationsRouter) { + defer { setupInitialState() } + self.interactor = interactor + self.router = router + } + + func didPress(_ subscription: SubscriptionsViewModel) { + router.presentNotifications(subscription: subscription.subscription) + } + + func setupInitialState() { + + Task(priority: .userInitiated) { + await setupSubscriptions() + } + } +} + +// MARK: SceneViewModel + +extension NotificationsPresenter: SceneViewModel { + +} + +// MARK: Privates + +private extension NotificationsPresenter { + @MainActor + func setupSubscriptions() async { + await loadSubscriptions() + +// for await _ in interactor.subscriptionsSubscription() { +// await loadSubscriptions() +// } + } + + @MainActor + func loadSubscriptions() async { + self.subscriptions = interactor.getSubscriptions() + .map { SubscriptionsViewModel(subscription: $0) } + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsRouter.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsRouter.swift new file mode 100644 index 000000000..61d90dcfc --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsRouter.swift @@ -0,0 +1,17 @@ +import UIKit +import WalletConnectPush + +final class NotificationsRouter { + + weak var viewController: UIViewController! + + private let app: Application + + init(app: Application) { + self.app = app + } + + func presentNotifications(subscription: WalletConnectPush.PushSubscription) { + + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift new file mode 100644 index 000000000..523732b9e --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift @@ -0,0 +1,85 @@ +import SwiftUI + +struct NotificationsView: View { + + @EnvironmentObject var presenter: NotificationsPresenter + + + + + + + var body: some View { + GeometryReader { geometry in + VStack { + ScrollView(showsIndicators: false) { + VStack { + if presenter.subscriptions.isEmpty { + Spacer() + emptyView(size: geometry.size) + Spacer() + } else { + subscriptionsList() + } + } + } + } + .onAppear { + presenter.setupInitialState() + } + } + } + + + + + + private func subscriptionsList() -> some View { + ForEach(presenter.subscriptions) { subscription in + Button(action: { + presenter.didPress(subscription) + }) { + HStack(spacing: 16.0) { + Image("avatar") + .resizable() + .frame(width: 64.0, height: 64.0) + + VStack(alignment: .leading) { + Text(subscription.title) + .font(.title3) + .foregroundColor(.blue) + .lineLimit(1) + + Text(subscription.subtitle) + .font(.subheadline) + .foregroundColor(.yellow) + .multilineTextAlignment(.leading) + } + } + .frame(height: 64.0) + } + } + .padding(16.0) + } + + + + private func emptyView(size: CGSize) -> some View { + VStack(spacing: 8.0) { + Text("It’s empty in here") + .font(.system(.title3)) + .foregroundColor(.blue) + + } + .frame(width: size.width) + .frame(minHeight: size.height) + } +} + +#if DEBUG +struct NotificationsView_Previews: PreviewProvider { + static var previews: some View { + NotificationsView() + } +} +#endif diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 From 8d8819fd1b9782ad5e65ce4da8917c415d4ad2e7 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 1 Feb 2023 15:03:39 +0100 Subject: [PATCH 04/42] fix wallet navigation bar --- Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift index 2bf1c1888..d092ab59e 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift @@ -8,6 +8,7 @@ final class MainRouter { func walletViewController() -> UIViewController { return WalletModule.create(app: app) + .wrapToNavigationController() } func notificationsViewController() -> UIViewController { From bf3f2ffca171d932af514f5d60f107550c372a3e Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 1 Feb 2023 15:06:19 +0100 Subject: [PATCH 05/42] Add notification screen title --- .../Wallet/Notifications/NotificationsPresenter.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift index 52c6aad03..b1b8c5689 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift @@ -30,7 +30,13 @@ final class NotificationsPresenter: ObservableObject { // MARK: SceneViewModel extension NotificationsPresenter: SceneViewModel { + var sceneTitle: String? { + return "Notifications" + } + var largeTitleDisplayMode: UINavigationItem.LargeTitleDisplayMode { + return .always + } } // MARK: Privates From a3b4d887e6c089d35a3ef71505fd5fd57b8768d3 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 1 Feb 2023 16:04:46 +0100 Subject: [PATCH 06/42] update notifications view --- .../Models/SubscriptionsViewModel.swift | 4 + .../NotificationsPresenter.swift | 4 + .../Notifications/NotificationsView.swift | 116 +++++++++++------- 3 files changed, 77 insertions(+), 47 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift index 0a511f3de..caf9826ee 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/Models/SubscriptionsViewModel.swift @@ -8,6 +8,10 @@ struct SubscriptionsViewModel: Identifiable { return subscription.topic } + var imageUrl: String { + return subscription.metadata.url + } + var title: String { return subscription.metadata.name } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift index b1b8c5689..018e82ad9 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift @@ -25,6 +25,10 @@ final class NotificationsPresenter: ObservableObject { await setupSubscriptions() } } + + func removeSubscribtion(at index: IndexSet) async { + //todo + } } // MARK: SceneViewModel diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift index 523732b9e..f6596f652 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift @@ -5,28 +5,50 @@ struct NotificationsView: View { @EnvironmentObject var presenter: NotificationsPresenter - - - - var body: some View { - GeometryReader { geometry in - VStack { - ScrollView(showsIndicators: false) { + ZStack { + Color.grey100 + .edgesIgnoringSafeArea(.all) + + VStack(alignment: .leading, spacing: 16) { + ZStack { + if presenter.subscriptions.isEmpty { + VStack(spacing: 10) { + Image(systemName: "bell.badge.fill") + .resizable() + .frame(width: 32, height: 32) + .aspectRatio(contentMode: .fit) + .foregroundColor(.grey50) + + Text("Notifications from connected apps will appear here. To enable notifications, visit the app in your browser and look for a \(Image(systemName: "bell.fill")) notifications toggle \(Image(systemName: "switch.2"))") + .foregroundColor(.grey50) + .font(.system(size: 15, weight: .regular, design: .rounded)) + .multilineTextAlignment(.center) + .lineSpacing(4) + } + .padding(20) + } + VStack { - if presenter.subscriptions.isEmpty { - Spacer() - emptyView(size: geometry.size) - Spacer() - } else { - subscriptionsList() + if !presenter.subscriptions.isEmpty { + List { + ForEach(presenter.subscriptions, id: \.title) { subscription in + subscriptionsView(subscription: subscription) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0)) + } + .onDelete { indexSet in + Task(priority: .high) { + await presenter.removeSubscribtion(at: indexSet) + } + } + } + .listStyle(PlainListStyle()) } } } } - .onAppear { - presenter.setupInitialState() - } + .padding(.vertical, 20) } } @@ -34,45 +56,45 @@ struct NotificationsView: View { - private func subscriptionsList() -> some View { - ForEach(presenter.subscriptions) { subscription in - Button(action: { - presenter.didPress(subscription) - }) { - HStack(spacing: 16.0) { - Image("avatar") - .resizable() - .frame(width: 64.0, height: 64.0) + private func subscriptionsView(subscription: SubscriptionsViewModel) -> some View { + Button { + presenter.didPress(subscription) + } label: { + VStack { + HStack(spacing: 10) { + AsyncImage(url: URL(string: subscription.imageUrl)) { phase in + if let image = phase.image { + image + .resizable() + .frame(width: 60, height: 60) + .background(Color.black) + .cornerRadius(30, corners: .allCorners) + } else { + Color.black + .frame(width: 60, height: 60) + .cornerRadius(30, corners: .allCorners) + } + } + .padding(.leading, 20) - VStack(alignment: .leading) { + VStack(alignment: .leading, spacing: 2) { Text(subscription.title) - .font(.title3) - .foregroundColor(.blue) - .lineLimit(1) + .foregroundColor(.grey8) + .font(.system(size: 20, weight: .semibold, design: .rounded)) Text(subscription.subtitle) - .font(.subheadline) - .foregroundColor(.yellow) - .multilineTextAlignment(.leading) + .foregroundColor(.grey50) + .font(.system(size: 13, weight: .medium, design: .rounded)) } - } - .frame(height: 64.0) - } - } - .padding(16.0) - } - - - private func emptyView(size: CGSize) -> some View { - VStack(spacing: 8.0) { - Text("It’s empty in here") - .font(.system(.title3)) - .foregroundColor(.blue) + Spacer() + Image("forward-shevron") + .foregroundColor(.grey8) + .padding(.trailing, 20) + } + } } - .frame(width: size.width) - .frame(minHeight: size.height) } } From ec405ea7560e364e3028bceec99ce690da9d4490 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 2 Feb 2023 09:31:02 +0100 Subject: [PATCH 07/42] savepoint - remove subscription --- .../Wallet/Notifications/NotificationsInteractor.swift | 8 ++++++++ .../Wallet/Notifications/NotificationsPresenter.swift | 6 ++++-- Sources/WalletConnectEcho/EchoClientFactory.swift | 2 +- Sources/WalletConnectEcho/Register/EchoService.swift | 2 +- .../WalletConnectNetworking/NetworkingClientFactory.swift | 2 +- .../Client/Common/DeletePushSubscriptionService.swift | 1 + .../Client/Wallet/WalletPushClient.swift | 5 +++++ .../Client/Wallet/WalletPushClientFactory.swift | 2 +- .../Engine/Common/DeleteSessionService.swift | 1 + Sources/WalletConnectSign/Sign/SignClientFactory.swift | 2 +- 10 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift index ff04ba809..09bcb8e61 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift @@ -5,4 +5,12 @@ final class NotificationsInteractor { func getSubscriptions() -> [PushSubscription] { Push.wallet.getActiveSubscriptions() } + + func removeSubscription(_ subscription: PushSubscription) async { + do { + try await Push.wallet.delete(topic: subscription.topic) + } catch { + print(error) + } + } } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift index 018e82ad9..97923afe7 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift @@ -26,8 +26,10 @@ final class NotificationsPresenter: ObservableObject { } } - func removeSubscribtion(at index: IndexSet) async { - //todo + func removeSubscribtion(at indexSet: IndexSet) async { + if let index = indexSet.first { + await interactor.removeSubscription(subscriptions[index].subscription) + } } } diff --git a/Sources/WalletConnectEcho/EchoClientFactory.swift b/Sources/WalletConnectEcho/EchoClientFactory.swift index ff7b8cbb6..f1515d5a8 100644 --- a/Sources/WalletConnectEcho/EchoClientFactory.swift +++ b/Sources/WalletConnectEcho/EchoClientFactory.swift @@ -16,7 +16,7 @@ public struct EchoClientFactory { clientId: String, httpClient: HTTPClient) -> EchoClient { - let logger = ConsoleLogger(loggingLevel: .off) + let logger = ConsoleLogger(loggingLevel: .debug) let registerService = EchoRegisterService(httpClient: httpClient, projectId: projectId, clientId: clientId, logger: logger) return EchoClient( diff --git a/Sources/WalletConnectEcho/Register/EchoService.swift b/Sources/WalletConnectEcho/Register/EchoService.swift index c792cc098..181cd6c66 100644 --- a/Sources/WalletConnectEcho/Register/EchoService.swift +++ b/Sources/WalletConnectEcho/Register/EchoService.swift @@ -28,7 +28,7 @@ enum EchoAPI: HTTPService { case .register(let clientId, let token, _): return try? JSONEncoder().encode([ "client_id": clientId, - "type": "apns", + "type": "apns-sandbox", "token": token ]) case .unregister: diff --git a/Sources/WalletConnectNetworking/NetworkingClientFactory.swift b/Sources/WalletConnectNetworking/NetworkingClientFactory.swift index b1d249880..6b5e39a2c 100644 --- a/Sources/WalletConnectNetworking/NetworkingClientFactory.swift +++ b/Sources/WalletConnectNetworking/NetworkingClientFactory.swift @@ -3,7 +3,7 @@ import Foundation public struct NetworkingClientFactory { public static func create(relayClient: RelayClient) -> NetworkingInteractor { - let logger = ConsoleLogger(loggingLevel: .off) + let logger = ConsoleLogger(loggingLevel: .debug) let keyValueStorage = UserDefaults.standard let keychainStorage = KeychainStorage(serviceIdentifier: "com.walletconnect.sdk") return NetworkingClientFactory.create(relayClient: relayClient, logger: logger, keychainStorage: keychainStorage, keyValueStorage: keyValueStorage) diff --git a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift index 14c3bba6b..cc4e07a23 100644 --- a/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift +++ b/Sources/WalletConnectPush/Client/Common/DeletePushSubscriptionService.swift @@ -32,6 +32,7 @@ class DeletePushSubscriptionService { networkingInteractor.unsubscribe(topic: topic) pushSubscriptionStore.delete(forKey: topic) + logger.debug("Subscription removed") kms.deleteSymmetricKey(for: topic) } diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift index 65ef69e89..4c39c4b31 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift @@ -9,6 +9,11 @@ public class WalletPushClient { private var publishers = Set() + public var subscriptionsPublisher: AnyPublisher<[PushSubscription], Never> { + subscriptionsPublisherSubject.eraseToAnyPublisher() + } + private let subscriptionsPublisherSubject = PassthroughSubject<[PushSubscription], Never>() + private let requestPublisherSubject = PassthroughSubject() public var requestPublisher: AnyPublisher { diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift index 2ed976c16..4b8d1115a 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift @@ -5,7 +5,7 @@ import WalletConnectEcho public struct WalletPushClientFactory { public static func create(networkInteractor: NetworkInteracting, pairingRegisterer: PairingRegisterer, echoClient: EchoClient) -> WalletPushClient { - let logger = ConsoleLogger(loggingLevel: .off) + let logger = ConsoleLogger(loggingLevel: .debug) let keyValueStorage = UserDefaults.standard let keychainStorage = KeychainStorage(serviceIdentifier: "com.walletconnect.sdk") diff --git a/Sources/WalletConnectSign/Engine/Common/DeleteSessionService.swift b/Sources/WalletConnectSign/Engine/Common/DeleteSessionService.swift index d4a40f52a..a1c617e49 100644 --- a/Sources/WalletConnectSign/Engine/Common/DeleteSessionService.swift +++ b/Sources/WalletConnectSign/Engine/Common/DeleteSessionService.swift @@ -24,6 +24,7 @@ class DeleteSessionService { let request = RPCRequest(method: protocolMethod.method, params: reason) try await networkingInteractor.request(request, topic: topic, protocolMethod: protocolMethod) sessionStore.delete(topic: topic) + logger.debug("Session disconnected") kms.deleteSymmetricKey(for: topic) networkingInteractor.unsubscribe(topic: topic) } diff --git a/Sources/WalletConnectSign/Sign/SignClientFactory.swift b/Sources/WalletConnectSign/Sign/SignClientFactory.swift index ef68dd39e..16ff60a7c 100644 --- a/Sources/WalletConnectSign/Sign/SignClientFactory.swift +++ b/Sources/WalletConnectSign/Sign/SignClientFactory.swift @@ -12,7 +12,7 @@ public struct SignClientFactory { /// /// WalletConnect Client is not a singleton but once you create an instance, you should not deinitialize it. Usually only one instance of a client is required in the application. public static func create(metadata: AppMetadata, pairingClient: PairingClient, networkingClient: NetworkingInteractor) -> SignClient { - let logger = ConsoleLogger(loggingLevel: .off) + let logger = ConsoleLogger(loggingLevel: .debug) let keyValueStorage = UserDefaults.standard let keychainStorage = KeychainStorage(serviceIdentifier: "com.walletconnect.sdk") return SignClientFactory.create(metadata: metadata, logger: logger, keyValueStorage: keyValueStorage, keychainStorage: keychainStorage, pairingClient: pairingClient, networkingClient: networkingClient) From d2ad755c59c32b89aef92792113b0a4cd1e64d77 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 2 Feb 2023 09:44:43 +0100 Subject: [PATCH 08/42] Add push subscription observer --- .../Client/Wallet/WalletPushClient.swift | 28 +++++++++++++++++-- .../Wallet/WalletPushClientFactory.swift | 4 ++- Sources/WalletConnectUtils/CodableStore.swift | 4 +++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift index 4c39c4b31..4b15a0fa4 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift @@ -10,9 +10,10 @@ public class WalletPushClient { private var publishers = Set() public var subscriptionsPublisher: AnyPublisher<[PushSubscription], Never> { - subscriptionsPublisherSubject.eraseToAnyPublisher() + return pushSubscriptionsObserver.subscriptionsPublisher } - private let subscriptionsPublisherSubject = PassthroughSubject<[PushSubscription], Never>() + + private let pushSubscriptionsObserver: PushSubscriptionsObserver private let requestPublisherSubject = PassthroughSubject() @@ -55,7 +56,8 @@ public class WalletPushClient { pushMessagesProvider: PushMessagesProvider, deletePushSubscriptionService: DeletePushSubscriptionService, deletePushSubscriptionSubscriber: DeletePushSubscriptionSubscriber, - resubscribeService: PushResubscribeService) { + resubscribeService: PushResubscribeService, + pushSubscriptionsObserver: PushSubscriptionsObserver) { self.logger = logger self.pairingRegisterer = pairingRegisterer self.proposeResponder = proposeResponder @@ -66,6 +68,7 @@ public class WalletPushClient { self.deletePushSubscriptionService = deletePushSubscriptionService self.deletePushSubscriptionSubscriber = deletePushSubscriptionSubscriber self.resubscribeService = resubscribeService + self.pushSubscriptionsObserver = pushSubscriptionsObserver setupSubscriptions() } @@ -120,3 +123,22 @@ extension WalletPushClient { } } #endif + +class PushSubscriptionsObserver { + public var subscriptionsPublisher: AnyPublisher<[PushSubscription], Never> { + subscriptionsPublisherSubject.eraseToAnyPublisher() + } + private let subscriptionsPublisherSubject = PassthroughSubject<[PushSubscription], Never>() + + private let store: CodableStore + + init(store: CodableStore) { + self.store = store + } + + func setUpSubscription() { + store.onStoreUpdate = { [unowned self] in + subscriptionsPublisherSubject.send(store.getAll()) + } + } +} diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift index 4b8d1115a..22358f13f 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClientFactory.swift @@ -37,6 +37,7 @@ public struct WalletPushClientFactory { let deletePushSubscriptionSubscriber = DeletePushSubscriptionSubscriber(networkingInteractor: networkInteractor, kms: kms, logger: logger, pushSubscriptionStore: subscriptionStore) let resubscribeService = PushResubscribeService(networkInteractor: networkInteractor, subscriptionsStorage: subscriptionStore) let pushMessagesProvider = PushMessagesProvider(history: history) + let pushSubscriptionsObserver = PushSubscriptionsObserver(store: subscriptionStore) return WalletPushClient( logger: logger, kms: kms, @@ -48,7 +49,8 @@ public struct WalletPushClientFactory { pushMessagesProvider: pushMessagesProvider, deletePushSubscriptionService: deletePushSubscriptionService, deletePushSubscriptionSubscriber: deletePushSubscriptionSubscriber, - resubscribeService: resubscribeService + resubscribeService: resubscribeService, + pushSubscriptionsObserver: pushSubscriptionsObserver ) } } diff --git a/Sources/WalletConnectUtils/CodableStore.swift b/Sources/WalletConnectUtils/CodableStore.swift index 184988696..00c34fb2c 100644 --- a/Sources/WalletConnectUtils/CodableStore.swift +++ b/Sources/WalletConnectUtils/CodableStore.swift @@ -3,6 +3,7 @@ import Foundation public final class CodableStore where T: Codable { private let defaults: KeyValueStorage private let prefix: String + public var onStoreUpdate: (() -> Void)? public init(defaults: KeyValueStorage, identifier: String) { self.defaults = defaults @@ -13,6 +14,7 @@ public final class CodableStore where T: Codable { // This force-unwrap is safe because T are JSON Encodable let encoded = try! JSONEncoder().encode(item) defaults.set(encoded, forKey: getContextPrefixedKey(for: key)) + onStoreUpdate?() } public func get(key: String) throws -> T? { @@ -33,11 +35,13 @@ public final class CodableStore where T: Codable { public func delete(forKey key: String) { defaults.removeObject(forKey: getContextPrefixedKey(for: key)) + onStoreUpdate?() } public func deleteAll() { dictionaryForIdentifier() .forEach { defaults.removeObject(forKey: $0.key) } + onStoreUpdate?() } private func getContextPrefixedKey(for key: String) -> String { From ad7579e3ec42cc9774f4de40f5bf2632561d574d Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 2 Feb 2023 11:25:04 +0100 Subject: [PATCH 09/42] refresh push subscriptions in wallet app --- .../NotificationsInteractor.swift | 5 ++++ .../NotificationsPresenter.swift | 25 ++++++++----------- .../Client/Wallet/WalletPushClient.swift | 1 + 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift index 09bcb8e61..48077e2a3 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsInteractor.swift @@ -1,7 +1,12 @@ import WalletConnectPush +import Combine final class NotificationsInteractor { + var subscriptionsPublisher: AnyPublisher<[PushSubscription], Never> { + return Push.wallet.subscriptionsPublisher + } + func getSubscriptions() -> [PushSubscription] { Push.wallet.getActiveSubscriptions() } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift index 97923afe7..2a694bfe7 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsPresenter.swift @@ -13,6 +13,7 @@ final class NotificationsPresenter: ObservableObject { defer { setupInitialState() } self.interactor = interactor self.router = router + } func didPress(_ subscription: SubscriptionsViewModel) { @@ -20,10 +21,7 @@ final class NotificationsPresenter: ObservableObject { } func setupInitialState() { - - Task(priority: .userInitiated) { - await setupSubscriptions() - } + setupSubscriptions() } func removeSubscribtion(at indexSet: IndexSet) async { @@ -48,18 +46,17 @@ extension NotificationsPresenter: SceneViewModel { // MARK: Privates private extension NotificationsPresenter { - @MainActor - func setupSubscriptions() async { - await loadSubscriptions() -// for await _ in interactor.subscriptionsSubscription() { -// await loadSubscriptions() -// } - } - - @MainActor - func loadSubscriptions() async { + func setupSubscriptions() { self.subscriptions = interactor.getSubscriptions() .map { SubscriptionsViewModel(subscription: $0) } + interactor.subscriptionsPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] pushSubscriptions in + self?.subscriptions = pushSubscriptions + .map { SubscriptionsViewModel(subscription: $0) } + } + .store(in: &disposeBag) } + } diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift index 4b15a0fa4..69bf7c092 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift @@ -134,6 +134,7 @@ class PushSubscriptionsObserver { init(store: CodableStore) { self.store = store + setUpSubscription() } func setUpSubscription() { From 583fb07ac7aa9bf375d17dca16847db0979488ec Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 2 Feb 2023 11:45:25 +0100 Subject: [PATCH 10/42] show proposals on top on main screen --- Example/ExampleApp.xcodeproj/project.pbxproj | 4 +++ .../Wallet/Main/MainInteractor.swift | 15 ++++++++++ .../Wallet/Main/MainModule.swift | 3 +- .../Wallet/Main/MainPresenter.swift | 28 ++++++++++++++++++- .../Wallet/Main/MainRouter.swift | 13 ++++++++- .../Wallet/Wallet/WalletInteractor.swift | 10 +------ .../Wallet/Wallet/WalletPresenter.swift | 13 --------- .../Wallet/Wallet/WalletRouter.swift | 14 +--------- 8 files changed, 62 insertions(+), 38 deletions(-) create mode 100644 Example/WalletApp/PresentationLayer/Wallet/Main/MainInteractor.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index aaa500ef6..f5f1e79e4 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ 76B149F02821C03B00F05F91 /* Proposal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76B149EF2821C03B00F05F91 /* Proposal.swift */; }; 76B6E39F2807A3B6004DF775 /* WalletViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76B6E39E2807A3B6004DF775 /* WalletViewController.swift */; }; 840BCF142949B9F900CB0655 /* WalletConnectPush in Frameworks */ = {isa = PBXBuildFile; productRef = 840BCF132949B9F900CB0655 /* WalletConnectPush */; }; + 84310D05298BC980000C15B6 /* MainInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84310D04298BC980000C15B6 /* MainInteractor.swift */; }; 8439CB89293F658E00F2F2E2 /* PushMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8439CB88293F658E00F2F2E2 /* PushMessage.swift */; }; 8448F1D427E4726F0000B866 /* WalletConnect in Frameworks */ = {isa = PBXBuildFile; productRef = 8448F1D327E4726F0000B866 /* WalletConnect */; }; 84494388278D9C1B00CC26BB /* UIAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84494387278D9C1B00CC26BB /* UIAlertController.swift */; }; @@ -371,6 +372,7 @@ 76B149EF2821C03B00F05F91 /* Proposal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Proposal.swift; sourceTree = ""; }; 76B6E39E2807A3B6004DF775 /* WalletViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletViewController.swift; sourceTree = ""; }; 8414FC832962F3D9007E20C9 /* PushDecryptionService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PushDecryptionService.entitlements; sourceTree = ""; }; + 84310D04298BC980000C15B6 /* MainInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainInteractor.swift; sourceTree = ""; }; 8439CB88293F658E00F2F2E2 /* PushMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushMessage.swift; sourceTree = ""; }; 84494387278D9C1B00CC26BB /* UIAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAlertController.swift; sourceTree = ""; }; 845B8D8B2934B36C0084A966 /* Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = ""; }; @@ -828,6 +830,7 @@ children = ( 847BD1D32989492500076C90 /* MainModule.swift */, 847BD1D42989492500076C90 /* MainPresenter.swift */, + 84310D04298BC980000C15B6 /* MainInteractor.swift */, 847BD1D52989492500076C90 /* MainRouter.swift */, 847BD1D12989492500076C90 /* MainViewController.swift */, 847BD1DE2989495C00076C90 /* Model */, @@ -2279,6 +2282,7 @@ 84E6B85F2981630000428BAF /* PushRequestInteractor.swift in Sources */, C55D3483295DD7140004314A /* AuthRequestView.swift in Sources */, C56EE243293F566D004840D1 /* ScanView.swift in Sources */, + 84310D05298BC980000C15B6 /* MainInteractor.swift in Sources */, C56EE288293F5757004840D1 /* ThirdPartyConfigurator.swift in Sources */, 847BD1D62989492500076C90 /* MainViewController.swift in Sources */, C5B2F6FA29705293000DBA0E /* SessionRequestInteractor.swift in Sources */, diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainInteractor.swift new file mode 100644 index 000000000..7487db34c --- /dev/null +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainInteractor.swift @@ -0,0 +1,15 @@ +import Combine +import Web3Wallet +import WalletConnectPush +import Foundation + +final class MainInteractor { + + var sessionProposalPublisher: AnyPublisher { + return Web3Wallet.instance.sessionProposalPublisher + } + + var pushRequestPublisher: AnyPublisher<(id: RPCID, account: Account, metadata: AppMetadata), Never> { + return Push.wallet.requestPublisher + } +} diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift index f60ff5d77..da47d310c 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift @@ -5,7 +5,8 @@ final class MainModule { @discardableResult static func create(app: Application) -> UIViewController { let router = MainRouter(app: app) - let presenter = MainPresenter(router: router) + let interactor = MainInteractor() + let presenter = MainPresenter(router: router, interactor: interactor) let viewController = MainViewController(presenter: presenter) router.viewController = viewController diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift index 3c7165f27..d33cd6bf3 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainPresenter.swift @@ -3,7 +3,9 @@ import Combine final class MainPresenter { + private let interactor: MainInteractor private let router: MainRouter + private var disposeBag = Set() var tabs: [TabPage] { return TabPage.allCases @@ -16,7 +18,31 @@ final class MainPresenter { ] } - init(router: MainRouter) { + init(router: MainRouter, + interactor: MainInteractor) { + defer { + setupInitialState() + } self.router = router + self.interactor = interactor } } + +// MARK: - Private functions +extension MainPresenter { + private func setupInitialState() { + interactor.pushRequestPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] request in + self?.router.present(pushRequest: request) + }.store(in: &disposeBag) + + interactor.sessionProposalPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] proposal in + self?.router.present(proposal: proposal) + } + .store(in: &disposeBag) + } +} + diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift index d092ab59e..75d71e842 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainRouter.swift @@ -1,5 +1,6 @@ import UIKit - +import WalletConnectPush +import Web3Wallet final class MainRouter { weak var viewController: UIViewController! @@ -11,11 +12,21 @@ final class MainRouter { .wrapToNavigationController() } + func present(proposal: Session.Proposal) { + SessionProposalModule.create(app: app, proposal: proposal) + .presentFullScreen(from: viewController, transparentBackground: true) + } + func notificationsViewController() -> UIViewController { return NotificationsModule.create(app: app) .wrapToNavigationController() } + func present(pushRequest: PushRequest) { + PushRequestModule.create(app: app, pushRequest: pushRequest) + .presentFullScreen(from: viewController, transparentBackground: true) + } + init(app: Application) { self.app = app } diff --git a/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletInteractor.swift index 3a4e3601e..e709edeae 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletInteractor.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletInteractor.swift @@ -7,18 +7,10 @@ final class WalletInteractor { var requestPublisher: AnyPublisher { return Web3Wallet.instance.authRequestPublisher } - - var sessionProposalPublisher: AnyPublisher { - return Web3Wallet.instance.sessionProposalPublisher - } - + var sessionRequestPublisher: AnyPublisher { return Web3Wallet.instance.sessionRequestPublisher } - - var pushRequestPublisher: AnyPublisher<(id: RPCID, account: Account, metadata: AppMetadata), Never> { - return Push.wallet.requestPublisher - } var sessionsPublisher: AnyPublisher<[Session], Never> { return Web3Wallet.instance.sessionsPublisher diff --git a/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletPresenter.swift index 1e129ae89..7a98087ad 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletPresenter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletPresenter.swift @@ -72,19 +72,6 @@ extension WalletPresenter { self?.router.present(sessionRequest: sessionRequest) }.store(in: &disposeBag) - interactor.pushRequestPublisher - .receive(on: DispatchQueue.main) - .sink { [weak self] request in - self?.router.present(pushRequest: request) - }.store(in: &disposeBag) - - interactor.sessionProposalPublisher - .receive(on: DispatchQueue.main) - .sink { [weak self] proposal in - self?.router.present(proposal: proposal) - } - .store(in: &disposeBag) - interactor.sessionsPublisher .receive(on: DispatchQueue.main) .sink { [weak self] sessions in diff --git a/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletRouter.swift b/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletRouter.swift index 8cc1c31ed..2eb2fcfd4 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletRouter.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletRouter.swift @@ -1,7 +1,5 @@ import UIKit - import Web3Wallet -import WalletConnectPush final class WalletRouter { weak var viewController: UIViewController! @@ -16,21 +14,11 @@ final class WalletRouter { AuthRequestModule.create(app: app, request: request) .presentFullScreen(from: viewController, transparentBackground: true) } - - func present(proposal: Session.Proposal) { - SessionProposalModule.create(app: app, proposal: proposal) - .presentFullScreen(from: viewController, transparentBackground: true) - } - + func present(sessionRequest: Request) { SessionRequestModule.create(app: app, sessionRequest: sessionRequest) .presentFullScreen(from: viewController, transparentBackground: true) } - - func present(pushRequest: PushRequest) { - PushRequestModule.create(app: app, pushRequest: pushRequest) - .presentFullScreen(from: viewController, transparentBackground: true) - } func presentPaste(onValue: @escaping (String) -> Void, onError: @escaping (Error) -> Void) { PasteUriModule.create(app: app, onValue: onValue, onError: onError) From 8addd79887d939fd486d850d010734cb5225c309 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 2 Feb 2023 12:00:48 +0100 Subject: [PATCH 11/42] fix ui issue --- .../WalletApp/PresentationLayer/Wallet/Wallet/WalletView.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletView.swift b/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletView.swift index a465e86d3..b9749aa9c 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletView.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Wallet/WalletView.swift @@ -27,8 +27,7 @@ struct WalletView: View { VStack { if !presenter.sessions.isEmpty { List { - ForEach(presenter.sessions, id: \.peer.name) { session in - connectionView(session: session) + ForEach(presenter.sessions, id: \.topic) { session in connectionView(session: session) .listRowSeparator(.hidden) .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0)) } From 7d52c5bb49cf36911569ac975bc98af3875b20c1 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 2 Feb 2023 12:03:47 +0100 Subject: [PATCH 12/42] extract PushSubscriptionsObserver --- .../Wallet/PushSubscriptionsObserver.swift | 22 +++++++++++++++++++ .../Client/Wallet/WalletPushClient.swift | 19 ---------------- 2 files changed, 22 insertions(+), 19 deletions(-) create mode 100644 Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift diff --git a/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift b/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift new file mode 100644 index 000000000..ae1e026a5 --- /dev/null +++ b/Sources/WalletConnectPush/Client/Wallet/PushSubscriptionsObserver.swift @@ -0,0 +1,22 @@ +import Combine +import Foundation + +class PushSubscriptionsObserver { + public var subscriptionsPublisher: AnyPublisher<[PushSubscription], Never> { + subscriptionsPublisherSubject.eraseToAnyPublisher() + } + private let subscriptionsPublisherSubject = PassthroughSubject<[PushSubscription], Never>() + + private let store: CodableStore + + init(store: CodableStore) { + self.store = store + setUpSubscription() + } + + func setUpSubscription() { + store.onStoreUpdate = { [unowned self] in + subscriptionsPublisherSubject.send(store.getAll()) + } + } +} diff --git a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift index 69bf7c092..30624d062 100644 --- a/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift +++ b/Sources/WalletConnectPush/Client/Wallet/WalletPushClient.swift @@ -124,22 +124,3 @@ extension WalletPushClient { } #endif -class PushSubscriptionsObserver { - public var subscriptionsPublisher: AnyPublisher<[PushSubscription], Never> { - subscriptionsPublisherSubject.eraseToAnyPublisher() - } - private let subscriptionsPublisherSubject = PassthroughSubject<[PushSubscription], Never>() - - private let store: CodableStore - - init(store: CodableStore) { - self.store = store - setUpSubscription() - } - - func setUpSubscription() { - store.onStoreUpdate = { [unowned self] in - subscriptionsPublisherSubject.send(store.getAll()) - } - } -} From 384c762bc898a9f9eeffd64722b07b42d4d58ca6 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 3 Feb 2023 15:15:25 +0100 Subject: [PATCH 13/42] lover pn service deployment target --- Example/ExampleApp.xcodeproj/project.pbxproj | 6 ++++-- Example/WalletApp/Other/Info.plist | 10 ++++++---- Sources/WalletConnectEcho/Register/EchoService.swift | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index f5f1e79e4..820ea7f82 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -2688,7 +2688,7 @@ INFOPLIST_FILE = PNDecryptionService/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = PNDecryptionService; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2717,7 +2717,7 @@ INFOPLIST_FILE = PNDecryptionService/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = PNDecryptionService; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2887,6 +2887,7 @@ ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = WalletApp/Other/Info.plist; + INFOPLIST_KEY_NSCameraUsageDescription = "Camera access for scanning QR code"; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; @@ -2920,6 +2921,7 @@ ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = WalletApp/Other/Info.plist; + INFOPLIST_KEY_NSCameraUsageDescription = "Camera access for scanning QR code"; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; diff --git a/Example/WalletApp/Other/Info.plist b/Example/WalletApp/Other/Info.plist index ef4c6367a..05eb571d8 100644 --- a/Example/WalletApp/Other/Info.plist +++ b/Example/WalletApp/Other/Info.plist @@ -24,8 +24,8 @@ PROJECT_ID $(PROJECT_ID) - NSCameraUsageDescription - Camera access for scanning QR code + SIMULATOR_IDENTIFIER + $(SIMULATOR_IDENTIFIER) UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -43,7 +43,9 @@ - SIMULATOR_IDENTIFIER - $(SIMULATOR_IDENTIFIER) + UIBackgroundModes + + remote-notification + diff --git a/Sources/WalletConnectEcho/Register/EchoService.swift b/Sources/WalletConnectEcho/Register/EchoService.swift index 181cd6c66..c792cc098 100644 --- a/Sources/WalletConnectEcho/Register/EchoService.swift +++ b/Sources/WalletConnectEcho/Register/EchoService.swift @@ -28,7 +28,7 @@ enum EchoAPI: HTTPService { case .register(let clientId, let token, _): return try? JSONEncoder().encode([ "client_id": clientId, - "type": "apns-sandbox", + "type": "apns", "token": token ]) case .unregister: From 6c362a56ed0a3977a1d990a94f3a23017e33a898 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 6 Feb 2023 11:12:22 +0100 Subject: [PATCH 14/42] add apns env, add build config to wallet app --- Example/ExampleApp.xcodeproj/project.pbxproj | 4 ++++ .../WalletApp/Common/BuildConfiguration.swift | 17 +++++++++++++++++ Example/WalletApp/Other/Info.plist | 2 ++ Sources/WalletConnectEcho/Echo.swift | 8 +++++--- .../WalletConnectEcho/EchoClientFactory.swift | 10 ++++++---- Sources/WalletConnectEcho/EchoConfig.swift | 1 + .../Register/EchoRegisterService.swift | 9 ++++++--- .../Register/EchoService.swift | 13 +++++++++---- 8 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 Example/WalletApp/Common/BuildConfiguration.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 820ea7f82..0bc18b710 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -54,6 +54,7 @@ 84B767792954554A00E92316 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B767782954554A00E92316 /* NotificationService.swift */; }; 84B7677D2954554A00E92316 /* PushDecryptionService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 84B767762954554A00E92316 /* PushDecryptionService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 84B76789295494D500E92316 /* WalletConnectPush in Frameworks */ = {isa = PBXBuildFile; productRef = 84B76788295494D500E92316 /* WalletConnectPush */; }; + 84B8154E2991099000FAD54E /* BuildConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B8154D2991099000FAD54E /* BuildConfiguration.swift */; }; 84CE641F27981DED00142511 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE641E27981DED00142511 /* AppDelegate.swift */; }; 84CE642127981DED00142511 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE642027981DED00142511 /* SceneDelegate.swift */; }; 84CE642827981DF000142511 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84CE642727981DF000142511 /* Assets.xcassets */; }; @@ -396,6 +397,7 @@ 84B767762954554A00E92316 /* PushDecryptionService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = PushDecryptionService.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 84B767782954554A00E92316 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; 84B7677A2954554A00E92316 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 84B8154D2991099000FAD54E /* BuildConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildConfiguration.swift; sourceTree = ""; }; 84CE641C27981DED00142511 /* DApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 84CE641E27981DED00142511 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 84CE642027981DED00142511 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -1583,6 +1585,7 @@ isa = PBXGroup; children = ( C56EE25D293F56D6004840D1 /* InputConfig.swift */, + 84B8154D2991099000FAD54E /* BuildConfiguration.swift */, C56EE267293F56D6004840D1 /* Style */, C56EE2A1293F6B9E004840D1 /* Helpers */, C56EE262293F56D6004840D1 /* Extensions */, @@ -2295,6 +2298,7 @@ C56EE248293F566D004840D1 /* ScanQR.swift in Sources */, 847BD1EB298A87AB00076C90 /* SubscriptionsViewModel.swift in Sources */, C55D349B2965BC2F0004314A /* TagsView.swift in Sources */, + 84B8154E2991099000FAD54E /* BuildConfiguration.swift in Sources */, C56EE289293F5757004840D1 /* Application.swift in Sources */, C56EE273293F56D7004840D1 /* UIColor.swift in Sources */, C5F32A322954816C00A6476E /* ConnectionDetailsPresenter.swift in Sources */, diff --git a/Example/WalletApp/Common/BuildConfiguration.swift b/Example/WalletApp/Common/BuildConfiguration.swift new file mode 100644 index 000000000..13fc3cf7f --- /dev/null +++ b/Example/WalletApp/Common/BuildConfiguration.swift @@ -0,0 +1,17 @@ +import Foundation + +enum Environment: String { + case debug = "Debug" + case release = "Release" +} + +class BuildConfiguration { + static let shared = BuildConfiguration() + + var environment: Environment + + init() { + let currentConfiguration = Bundle.main.object(forInfoDictionaryKey: "CONFIGURATION") as! String + environment = Environment(rawValue: currentConfiguration)! + } +} diff --git a/Example/WalletApp/Other/Info.plist b/Example/WalletApp/Other/Info.plist index 05eb571d8..ab74bf653 100644 --- a/Example/WalletApp/Other/Info.plist +++ b/Example/WalletApp/Other/Info.plist @@ -26,6 +26,8 @@ $(PROJECT_ID) SIMULATOR_IDENTIFIER $(SIMULATOR_IDENTIFIER) + CONFIGURATION + $(CONFIGURATION) UIApplicationSceneManifest UIApplicationSupportsMultipleScenes diff --git a/Sources/WalletConnectEcho/Echo.swift b/Sources/WalletConnectEcho/Echo.swift index 6ebc721e2..13f91a4b8 100644 --- a/Sources/WalletConnectEcho/Echo.swift +++ b/Sources/WalletConnectEcho/Echo.swift @@ -11,7 +11,8 @@ public class Echo { return EchoClientFactory.create( projectId: Networking.projectId, clientId: config.clientId, - echoHost: config.echoHost) + echoHost: config.echoHost, + environment: config.environment) }() private static var config: Config? @@ -22,8 +23,9 @@ public class Echo { /// - Parameter clientId: https://github.com/WalletConnect/walletconnect-docs/blob/main/docs/specs/clients/core/relay/relay-client-auth.md#overview static public func configure( clientId: String, - echoHost: String = echoHost + echoHost: String = echoHost, + environment: APNSEnvironment ) { - Echo.config = Echo.Config(clientId: clientId, echoHost: echoHost) + Echo.config = Echo.Config(clientId: clientId, echoHost: echoHost, environment: environment) } } diff --git a/Sources/WalletConnectEcho/EchoClientFactory.swift b/Sources/WalletConnectEcho/EchoClientFactory.swift index f1515d5a8..b8beb2c87 100644 --- a/Sources/WalletConnectEcho/EchoClientFactory.swift +++ b/Sources/WalletConnectEcho/EchoClientFactory.swift @@ -2,22 +2,24 @@ import Foundation import WalletConnectNetworking public struct EchoClientFactory { - public static func create(projectId: String, clientId: String, echoHost: String) -> EchoClient { + public static func create(projectId: String, clientId: String, echoHost: String, environment: APNSEnvironment) -> EchoClient { let httpClient = HTTPNetworkClient(host: echoHost) return EchoClientFactory.create( projectId: projectId, clientId: clientId, - httpClient: httpClient) + httpClient: httpClient, + environment: environment) } static func create(projectId: String, clientId: String, - httpClient: HTTPClient) -> EchoClient { + httpClient: HTTPClient, + environment: APNSEnvironment) -> EchoClient { let logger = ConsoleLogger(loggingLevel: .debug) - let registerService = EchoRegisterService(httpClient: httpClient, projectId: projectId, clientId: clientId, logger: logger) + let registerService = EchoRegisterService(httpClient: httpClient, projectId: projectId, clientId: clientId, logger: logger, environment: environment) return EchoClient( registerService: registerService) diff --git a/Sources/WalletConnectEcho/EchoConfig.swift b/Sources/WalletConnectEcho/EchoConfig.swift index d1eab366f..6bc29d0f9 100644 --- a/Sources/WalletConnectEcho/EchoConfig.swift +++ b/Sources/WalletConnectEcho/EchoConfig.swift @@ -4,5 +4,6 @@ extension Echo { struct Config { let clientId: String let echoHost: String + let environment: APNSEnvironment } } diff --git a/Sources/WalletConnectEcho/Register/EchoRegisterService.swift b/Sources/WalletConnectEcho/Register/EchoRegisterService.swift index 51fbd7560..9a3bbb6d5 100644 --- a/Sources/WalletConnectEcho/Register/EchoRegisterService.swift +++ b/Sources/WalletConnectEcho/Register/EchoRegisterService.swift @@ -6,6 +6,7 @@ actor EchoRegisterService { private let projectId: String private let clientId: String private let logger: ConsoleLogging + private let environment: APNSEnvironment // DID method specific identifier private var clientIdMutlibase: String { return clientId.replacingOccurrences(of: "did:key:", with: "") @@ -18,11 +19,13 @@ actor EchoRegisterService { init(httpClient: HTTPClient, projectId: String, clientId: String, - logger: ConsoleLogging) { + logger: ConsoleLogging, + environment: APNSEnvironment) { self.httpClient = httpClient self.clientId = clientId self.projectId = projectId self.logger = logger + self.environment = environment } func register(deviceToken: Data) async throws { @@ -31,7 +34,7 @@ actor EchoRegisterService { logger.debug("APNS device token: \(token)") let response = try await httpClient.request( EchoResponse.self, - at: EchoAPI.register(clientId: clientIdMutlibase, token: token, projectId: projectId) + at: EchoAPI.register(clientId: clientIdMutlibase, token: token, projectId: projectId, environment: environment) ) guard response.status == .success else { throw Errors.registrationFailed @@ -43,7 +46,7 @@ actor EchoRegisterService { public func register(deviceToken: String) async throws { let response = try await httpClient.request( EchoResponse.self, - at: EchoAPI.register(clientId: clientIdMutlibase, token: deviceToken, projectId: projectId) + at: EchoAPI.register(clientId: clientIdMutlibase, token: deviceToken, projectId: projectId, environment: environment) ) guard response.status == .success else { throw Errors.registrationFailed diff --git a/Sources/WalletConnectEcho/Register/EchoService.swift b/Sources/WalletConnectEcho/Register/EchoService.swift index c792cc098..44450f03a 100644 --- a/Sources/WalletConnectEcho/Register/EchoService.swift +++ b/Sources/WalletConnectEcho/Register/EchoService.swift @@ -2,12 +2,12 @@ import Foundation import WalletConnectNetworking enum EchoAPI: HTTPService { - case register(clientId: String, token: String, projectId: String) + case register(clientId: String, token: String, projectId: String, environment: APNSEnvironment) case unregister(clientId: String, projectId: String) var path: String { switch self { - case .register(_, _, let projectId): + case .register(_, _, let projectId, _): return "/\(projectId)/clients" case .unregister(let clientId, let projectId): return "/\(projectId)/clients\(clientId)" @@ -25,10 +25,10 @@ enum EchoAPI: HTTPService { var body: Data? { switch self { - case .register(let clientId, let token, _): + case .register(let clientId, let token, _, let environment): return try? JSONEncoder().encode([ "client_id": clientId, - "type": "apns", + "type": environment.rawValue, "token": token ]) case .unregister: @@ -44,3 +44,8 @@ enum EchoAPI: HTTPService { return "https" } } + +public enum APNSEnvironment: String { + case production = "apns" + case sandbox = "apns-sandbox" +} From a4638c64759241881c4fb27654140aec72c7deca Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 6 Feb 2023 11:27:04 +0100 Subject: [PATCH 15/42] update echo env --- .../xcschemes/WalletConnectEcho.xcscheme | 67 +++++++++++++++++++ .../Configurator/ThirdPartyConfigurator.swift | 3 +- .../WalletApp/Common/BuildConfiguration.swift | 20 ++++-- .../WalletConnectEcho/APNSEnvironment.swift | 6 ++ .../Register/EchoService.swift | 5 -- .../WalletConnectPush/APNSEnvironment.swift | 3 + Sources/WalletConnectPush/Push.swift | 6 +- Sources/WalletConnectPush/PushConfig.swift | 2 + 8 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/WalletConnectEcho.xcscheme create mode 100644 Sources/WalletConnectEcho/APNSEnvironment.swift create mode 100644 Sources/WalletConnectPush/APNSEnvironment.swift diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnectEcho.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnectEcho.xcscheme new file mode 100644 index 000000000..f788c492b --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnectEcho.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift b/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift index 298207e2b..f06ba1b35 100644 --- a/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift +++ b/Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift @@ -15,8 +15,7 @@ struct ThirdPartyConfigurator: Configurator { ) Web3Wallet.configure(metadata: metadata, signerFactory: DefaultSignerFactory()) - Push.configure() - + Push.configure(environment: BuildConfiguration.shared.apnsEnvironment) } } diff --git a/Example/WalletApp/Common/BuildConfiguration.swift b/Example/WalletApp/Common/BuildConfiguration.swift index 13fc3cf7f..f17d08e73 100644 --- a/Example/WalletApp/Common/BuildConfiguration.swift +++ b/Example/WalletApp/Common/BuildConfiguration.swift @@ -1,15 +1,25 @@ import Foundation - -enum Environment: String { - case debug = "Debug" - case release = "Release" -} +import WalletConnectPush class BuildConfiguration { + enum Environment: String { + case debug = "Debug" + case release = "Release" + } + static let shared = BuildConfiguration() var environment: Environment + var apnsEnvironment: APNSEnvironment { + switch environment { + case .debug: + return .sandbox + case .release: + return .production + } + } + init() { let currentConfiguration = Bundle.main.object(forInfoDictionaryKey: "CONFIGURATION") as! String environment = Environment(rawValue: currentConfiguration)! diff --git a/Sources/WalletConnectEcho/APNSEnvironment.swift b/Sources/WalletConnectEcho/APNSEnvironment.swift new file mode 100644 index 000000000..2e8b1343d --- /dev/null +++ b/Sources/WalletConnectEcho/APNSEnvironment.swift @@ -0,0 +1,6 @@ +import Foundation + +public enum APNSEnvironment: String { + case production = "apns" + case sandbox = "apns-sandbox" +} diff --git a/Sources/WalletConnectEcho/Register/EchoService.swift b/Sources/WalletConnectEcho/Register/EchoService.swift index 44450f03a..998c81c6c 100644 --- a/Sources/WalletConnectEcho/Register/EchoService.swift +++ b/Sources/WalletConnectEcho/Register/EchoService.swift @@ -44,8 +44,3 @@ enum EchoAPI: HTTPService { return "https" } } - -public enum APNSEnvironment: String { - case production = "apns" - case sandbox = "apns-sandbox" -} diff --git a/Sources/WalletConnectPush/APNSEnvironment.swift b/Sources/WalletConnectPush/APNSEnvironment.swift new file mode 100644 index 000000000..567373443 --- /dev/null +++ b/Sources/WalletConnectPush/APNSEnvironment.swift @@ -0,0 +1,3 @@ +import WalletConnectEcho + +public typealias APNSEnvironment = WalletConnectEcho.APNSEnvironment diff --git a/Sources/WalletConnectPush/Push.swift b/Sources/WalletConnectPush/Push.swift index 5b159bf58..2fafa4fdc 100644 --- a/Sources/WalletConnectPush/Push.swift +++ b/Sources/WalletConnectPush/Push.swift @@ -16,7 +16,7 @@ public class Push { guard let config = Push.config else { fatalError("Error - you must call Push.configure(_:) before accessing the shared wallet instance.") } - Echo.configure(clientId: config.clientId, echoHost: config.echoHost) + Echo.configure(clientId: config.clientId, echoHost: config.echoHost, environment: config.environment) return WalletPushClientFactory.create( networkInteractor: Networking.interactor, pairingRegisterer: Pair.registerer, @@ -29,9 +29,9 @@ public class Push { private init() { } /// Wallet's configuration method - static public func configure(echoHost: String = "echo.walletconnect.com") { + static public func configure(echoHost: String = "echo.walletconnect.com", environment: APNSEnvironment) { let clientId = try! Networking.interactor.getClientId() - Push.config = Push.Config(clientId: clientId, echoHost: echoHost) + Push.config = Push.Config(clientId: clientId, echoHost: echoHost, environment: environment) } } diff --git a/Sources/WalletConnectPush/PushConfig.swift b/Sources/WalletConnectPush/PushConfig.swift index 8c7445dcc..d4bd4c1af 100644 --- a/Sources/WalletConnectPush/PushConfig.swift +++ b/Sources/WalletConnectPush/PushConfig.swift @@ -1,8 +1,10 @@ import Foundation +import WalletConnectEcho extension Push { struct Config { let clientId: String let echoHost: String + let environment: APNSEnvironment } } From be07044f6dd2fd7ada2548a54050cad11d5bb00d Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 6 Feb 2023 11:39:26 +0100 Subject: [PATCH 16/42] fix tests --- Example/IntegrationTests/Pairing/PairingTests.swift | 2 +- Example/IntegrationTests/Push/PushTests.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Example/IntegrationTests/Pairing/PairingTests.swift b/Example/IntegrationTests/Pairing/PairingTests.swift index b0f51314a..83e44ca16 100644 --- a/Example/IntegrationTests/Pairing/PairingTests.swift +++ b/Example/IntegrationTests/Pairing/PairingTests.swift @@ -69,7 +69,7 @@ final class PairingTests: XCTestCase { let (pairingClient, networkingInteractor, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) let pushLogger = ConsoleLogger(suffix: prefix + " [Push]", loggingLevel: .debug) walletPairingClient = pairingClient - let echoClient = EchoClientFactory.create(projectId: "", clientId: "", echoHost: "echo.walletconnect.com") + let echoClient = EchoClientFactory.create(projectId: "", clientId: "", echoHost: "echo.walletconnect.com", environment: .sandbox) walletPushClient = WalletPushClientFactory.create(logger: pushLogger, keyValueStorage: keyValueStorage, keychainStorage: keychain, diff --git a/Example/IntegrationTests/Push/PushTests.swift b/Example/IntegrationTests/Push/PushTests.swift index a8619ba30..6e14ee3ec 100644 --- a/Example/IntegrationTests/Push/PushTests.swift +++ b/Example/IntegrationTests/Push/PushTests.swift @@ -69,7 +69,7 @@ final class PushTests: XCTestCase { let (pairingClient, networkingInteractor, keychain, keyValueStorage) = makeClientDependencies(prefix: prefix) let pushLogger = ConsoleLogger(suffix: prefix + " [Push]", loggingLevel: .debug) walletPairingClient = pairingClient - let echoClient = EchoClientFactory.create(projectId: "", clientId: "", echoHost: "echo.walletconnect.com") + let echoClient = EchoClientFactory.create(projectId: "", clientId: "", echoHost: "echo.walletconnect.com", environment: .sandbox) walletPushClient = WalletPushClientFactory.create(logger: pushLogger, keyValueStorage: keyValueStorage, keychainStorage: keychain, From 694149b2592b17e0a172caa3a9ad223ba9669aa3 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 1 Feb 2023 17:58:02 +0530 Subject: [PATCH 17/42] Cacao moved to utills --- .../Common/SIWEMessageFormatter.swift | 92 ++----------------- .../Wallet/WalletRespondService.swift | 2 +- Sources/Auth/Types/AuthPayload.swift | 16 ++++ Sources/Auth/Types/Cacao/Cacao.swift | 10 -- Sources/Auth/Types/Cacao/CacaoHeader.swift | 5 - Sources/Auth/Types/Cacao/CacaoPayload.swift | 29 ------ .../AuthenticationService.swift | 12 +++ .../AuthenticationStorage.swift | 12 +++ .../Authentication/IdentityKeyService.swift | 38 ++++++++ Sources/WalletConnectUtils/Cacao/Cacao.swift | 16 ++++ .../Cacao/CacaoHeader.swift | 9 ++ .../Cacao/CacaoPayload.swift | 41 +++++++++ .../Cacao/CacaoSignature.swift | 6 +- .../DIDPKH}/DIDPKH.swift | 13 +-- .../SIWE/SIWECacaoFormatter.swift | 30 ++++++ .../WalletConnectUtils/SIWE/SIWEMessage.swift | 72 +++++++++++++++ .../AuthTests/AppRespondSubscriberTests.swift | 2 +- 17 files changed, 264 insertions(+), 141 deletions(-) delete mode 100644 Sources/Auth/Types/Cacao/Cacao.swift delete mode 100644 Sources/Auth/Types/Cacao/CacaoHeader.swift delete mode 100644 Sources/Auth/Types/Cacao/CacaoPayload.swift create mode 100644 Sources/Chat/ProtocolServices/Authentication/AuthenticationService.swift create mode 100644 Sources/Chat/ProtocolServices/Authentication/AuthenticationStorage.swift create mode 100644 Sources/Chat/ProtocolServices/Authentication/IdentityKeyService.swift create mode 100644 Sources/WalletConnectUtils/Cacao/Cacao.swift create mode 100644 Sources/WalletConnectUtils/Cacao/CacaoHeader.swift create mode 100644 Sources/WalletConnectUtils/Cacao/CacaoPayload.swift rename Sources/{Auth/Types => WalletConnectUtils}/Cacao/CacaoSignature.swift (76%) rename Sources/{Auth/Services/Signer => WalletConnectUtils/DIDPKH}/DIDPKH.swift (73%) create mode 100644 Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift create mode 100644 Sources/WalletConnectUtils/SIWE/SIWEMessage.swift diff --git a/Sources/Auth/Services/Common/SIWEMessageFormatter.swift b/Sources/Auth/Services/Common/SIWEMessageFormatter.swift index 5e8c82d57..0e4034d5f 100644 --- a/Sources/Auth/Services/Common/SIWEMessageFormatter.swift +++ b/Sources/Auth/Services/Common/SIWEMessageFormatter.swift @@ -14,96 +14,16 @@ public struct SIWEMessageFormatter: SIWEMessageFormatting { public init() { } public func formatMessage(from payload: AuthPayload, address: String) throws -> String { - guard let chain = Blockchain(payload.chainId) else { + guard + let blockchain = Blockchain(payload.chainId), + let account = Account(blockchain: blockchain, address: address) else { throw Errors.invalidChainID } - let message = SIWEMessage( - domain: payload.domain, - uri: payload.aud, - address: address, - version: payload.version, - nonce: payload.nonce, - chainId: chain.reference, - iat: payload.iat, - nbf: payload.nbf, - exp: payload.exp, - statement: payload.statement, - requestId: payload.requestId, - resources: payload.resources - ) - return message.formatted + let payload = payload.cacaoPayload(didpkh: DIDPKH(account: account)) + return try formatMessage(from: payload) } func formatMessage(from payload: CacaoPayload) throws -> String { - let address = try DIDPKH(iss: payload.iss).account.address - let iss = try DIDPKH(iss: payload.iss) - let message = SIWEMessage( - domain: payload.domain, - uri: payload.aud, - address: address, - version: payload.version, - nonce: payload.nonce, - chainId: iss.account.reference, - iat: payload.iat, - nbf: payload.nbf, - exp: payload.exp, - statement: payload.statement, - requestId: payload.requestId, - resources: payload.resources - ) - return message.formatted - } -} - -private struct SIWEMessage: Equatable { - let domain: String - let uri: String // aud - let address: String - let version: String - let nonce: String - let chainId: String - let iat: String - let nbf: String? - let exp: String? - let statement: String? - let requestId: String? - let resources: [String]? - - var formatted: String { - return """ - \(domain) wants you to sign in with your Ethereum account: - \(address) - \(statementLine) - URI: \(uri) - Version: \(version) - Chain ID: \(chainId) - Nonce: \(nonce) - Issued At: \(iat)\(expLine)\(nbfLine)\(requestIdLine)\(resourcesSection) - """ - } - - var expLine: String { - guard let exp = exp else { return "" } - return "\nExpiration Time: \(exp)" - } - - var statementLine: String { - guard let statement = statement else { return "" } - return "\n\(statement)\n" - } - - var nbfLine: String { - guard let nbf = nbf else { return "" } - return "\nNot Before: \(nbf)" - } - - var requestIdLine: String { - guard let requestId = requestId else { return "" } - return "\nRequest ID: \(requestId)" - } - - var resourcesSection: String { - guard let resources = resources else { return "" } - return resources.reduce("\nResources:") { $0 + "\n- \($1)" } + return try SIWECacaoFormatter().formatMessage(from: payload) } } diff --git a/Sources/Auth/Services/Wallet/WalletRespondService.swift b/Sources/Auth/Services/Wallet/WalletRespondService.swift index 595489aa3..8ea1946e9 100644 --- a/Sources/Auth/Services/Wallet/WalletRespondService.swift +++ b/Sources/Auth/Services/Wallet/WalletRespondService.swift @@ -31,7 +31,7 @@ actor WalletRespondService { let didpkh = DIDPKH(account: account) let header = CacaoHeader(t: "eip4361") - let payload = CacaoPayload(params: authRequestParams.payloadParams, didpkh: didpkh) + let payload = authRequestParams.payloadParams.cacaoPayload(didpkh: didpkh) let responseParams = AuthResponseParams(h: header, p: payload, s: signature) let response = RPCResponse(id: requestId, result: responseParams) diff --git a/Sources/Auth/Types/AuthPayload.swift b/Sources/Auth/Types/AuthPayload.swift index 621df1ea3..00d8b934b 100644 --- a/Sources/Auth/Types/AuthPayload.swift +++ b/Sources/Auth/Types/AuthPayload.swift @@ -28,4 +28,20 @@ public struct AuthPayload: Codable, Equatable { self.requestId = requestParams.requestId self.resources = requestParams.resources } + + func cacaoPayload(didpkh: DIDPKH) -> CacaoPayload { + return CacaoPayload( + iss: didpkh.iss, + domain: domain, + aud: aud, + version: version, + nonce: nonce, + iat: iat, + nbf: nbf, + exp: exp, + statement: statement, + requestId: requestId, + resources: resources + ) + } } diff --git a/Sources/Auth/Types/Cacao/Cacao.swift b/Sources/Auth/Types/Cacao/Cacao.swift deleted file mode 100644 index a82da2ab4..000000000 --- a/Sources/Auth/Types/Cacao/Cacao.swift +++ /dev/null @@ -1,10 +0,0 @@ -import Foundation - -/// CAIP-74 Cacao object -/// -/// specs at: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-74.md -public struct Cacao: Codable, Equatable { - let h: CacaoHeader - let p: CacaoPayload - let s: CacaoSignature -} diff --git a/Sources/Auth/Types/Cacao/CacaoHeader.swift b/Sources/Auth/Types/Cacao/CacaoHeader.swift deleted file mode 100644 index 1461f3ae4..000000000 --- a/Sources/Auth/Types/Cacao/CacaoHeader.swift +++ /dev/null @@ -1,5 +0,0 @@ -import Foundation - -struct CacaoHeader: Codable, Equatable { - let t: String -} diff --git a/Sources/Auth/Types/Cacao/CacaoPayload.swift b/Sources/Auth/Types/Cacao/CacaoPayload.swift deleted file mode 100644 index 41f66e736..000000000 --- a/Sources/Auth/Types/Cacao/CacaoPayload.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Foundation - -struct CacaoPayload: Codable, Equatable { - let iss: String - let domain: String - let aud: String - let version: String - let nonce: String - let iat: String - let nbf: String? - let exp: String? - let statement: String? - let requestId: String? - let resources: [String]? - - init(params: AuthPayload, didpkh: DIDPKH) { - self.iss = didpkh.iss - self.domain = params.domain - self.aud = params.aud - self.version = "1" - self.nonce = params.nonce - self.iat = params.iat - self.nbf = params.nbf - self.exp = params.exp - self.statement = params.statement - self.requestId = params.requestId - self.resources = params.resources - } -} diff --git a/Sources/Chat/ProtocolServices/Authentication/AuthenticationService.swift b/Sources/Chat/ProtocolServices/Authentication/AuthenticationService.swift new file mode 100644 index 000000000..b1dead4ed --- /dev/null +++ b/Sources/Chat/ProtocolServices/Authentication/AuthenticationService.swift @@ -0,0 +1,12 @@ +import Foundation + +final class AuthenticationService { + + private let accountService: AccountService + + init(accountService: AccountService) { + self.accountService = accountService + } + + +} diff --git a/Sources/Chat/ProtocolServices/Authentication/AuthenticationStorage.swift b/Sources/Chat/ProtocolServices/Authentication/AuthenticationStorage.swift new file mode 100644 index 000000000..f5430e7bf --- /dev/null +++ b/Sources/Chat/ProtocolServices/Authentication/AuthenticationStorage.swift @@ -0,0 +1,12 @@ +import Foundation + +typealias IdentityKey = SigningPrivateKey + +final class AuthenticationStorage { + + private let kms: KeychainServiceProtocol + + init(kms: KeychainServiceProtocol) { + self.kms = kms + } +} diff --git a/Sources/Chat/ProtocolServices/Authentication/IdentityKeyService.swift b/Sources/Chat/ProtocolServices/Authentication/IdentityKeyService.swift new file mode 100644 index 000000000..256eec8c6 --- /dev/null +++ b/Sources/Chat/ProtocolServices/Authentication/IdentityKeyService.swift @@ -0,0 +1,38 @@ +import Foundation + +enum IdentityKeyAPI: HTTPService { + + case register(cacao: String) // TODO: Cacao + case resolve(publicKey: String) + + var path: String { + return "/identity" + } + + var method: WalletConnectNetworking.HTTPMethod { + switch self { + case .register: + return .post + case .resolve: + return .get + } + } + + var body: Data? { + switch self { + case .register(let cacao): + return try? JSONEncoder().encode(cacao) + case .resolve: + return nil + } + } + + var queryParameters: [String : String]? { + switch self { + case .register: + return nil + case .resolve(let publicKey): + return ["publicKey": publicKey] + } + } +} diff --git a/Sources/WalletConnectUtils/Cacao/Cacao.swift b/Sources/WalletConnectUtils/Cacao/Cacao.swift new file mode 100644 index 000000000..5c938594b --- /dev/null +++ b/Sources/WalletConnectUtils/Cacao/Cacao.swift @@ -0,0 +1,16 @@ +import Foundation + +/// CAIP-74 Cacao object +/// +/// specs at: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-74.md +public struct Cacao: Codable, Equatable { + public let h: CacaoHeader + public let p: CacaoPayload + public let s: CacaoSignature + + public init(h: CacaoHeader, p: CacaoPayload, s: CacaoSignature) { + self.h = h + self.p = p + self.s = s + } +} diff --git a/Sources/WalletConnectUtils/Cacao/CacaoHeader.swift b/Sources/WalletConnectUtils/Cacao/CacaoHeader.swift new file mode 100644 index 000000000..897c314d4 --- /dev/null +++ b/Sources/WalletConnectUtils/Cacao/CacaoHeader.swift @@ -0,0 +1,9 @@ +import Foundation + +public struct CacaoHeader: Codable, Equatable { + public let t: String + + public init(t: String) { + self.t = t + } +} diff --git a/Sources/WalletConnectUtils/Cacao/CacaoPayload.swift b/Sources/WalletConnectUtils/Cacao/CacaoPayload.swift new file mode 100644 index 000000000..3711f3ef0 --- /dev/null +++ b/Sources/WalletConnectUtils/Cacao/CacaoPayload.swift @@ -0,0 +1,41 @@ +import Foundation + +public struct CacaoPayload: Codable, Equatable { + public let iss: String + public let domain: String + public let aud: String + public let version: String + public let nonce: String + public let iat: String + public let nbf: String? + public let exp: String? + public let statement: String? + public let requestId: String? + public let resources: [String]? + + public init( + iss: String, + domain: String, + aud: String, + version: String, + nonce: String, + iat: String, + nbf: String?, + exp: String?, + statement: String?, + requestId: String?, + resources: [String]? + ) { + self.iss = iss + self.domain = domain + self.aud = aud + self.version = version + self.nonce = nonce + self.iat = iat + self.nbf = nbf + self.exp = exp + self.statement = statement + self.requestId = requestId + self.resources = resources + } +} diff --git a/Sources/Auth/Types/Cacao/CacaoSignature.swift b/Sources/WalletConnectUtils/Cacao/CacaoSignature.swift similarity index 76% rename from Sources/Auth/Types/Cacao/CacaoSignature.swift rename to Sources/WalletConnectUtils/Cacao/CacaoSignature.swift index 7137f9dea..d272f0279 100644 --- a/Sources/Auth/Types/Cacao/CacaoSignature.swift +++ b/Sources/WalletConnectUtils/Cacao/CacaoSignature.swift @@ -6,9 +6,9 @@ public enum CacaoSignatureType: String, Codable { } public struct CacaoSignature: Codable, Equatable { - let t: CacaoSignatureType - let s: String - let m: String? + public let t: CacaoSignatureType + public let s: String + public let m: String? public init(t: CacaoSignatureType, s: String, m: String? = nil) { self.t = t diff --git a/Sources/Auth/Services/Signer/DIDPKH.swift b/Sources/WalletConnectUtils/DIDPKH/DIDPKH.swift similarity index 73% rename from Sources/Auth/Services/Signer/DIDPKH.swift rename to Sources/WalletConnectUtils/DIDPKH/DIDPKH.swift index 1475a6530..a625b231a 100644 --- a/Sources/Auth/Services/Signer/DIDPKH.swift +++ b/Sources/WalletConnectUtils/DIDPKH/DIDPKH.swift @@ -1,17 +1,18 @@ import Foundation -struct DIDPKH { - static let didPrefix: String = "did:pkh" +public struct DIDPKH { + + private static let didPrefix: String = "did:pkh" enum Errors: Error { case invalidDIDPKH case invalidAccount } - let account: Account - let iss: String + public let account: Account + public let iss: String - init(iss: String) throws { + public init(iss: String) throws { guard iss.starts(with: DIDPKH.didPrefix) else { throw Errors.invalidDIDPKH } @@ -25,7 +26,7 @@ struct DIDPKH { self.account = account } - init(account: Account) { + public init(account: Account) { self.iss = "\(DIDPKH.didPrefix):\(account.absoluteString)" self.account = account } diff --git a/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift b/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift new file mode 100644 index 000000000..c361677a3 --- /dev/null +++ b/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift @@ -0,0 +1,30 @@ +import Foundation + +public protocol SIWECacaoFormatting { + func formatMessage(from payload: CacaoPayload) throws -> String +} + +public struct SIWECacaoFormatter: SIWECacaoFormatting { + + public init() { } + + public func formatMessage(from payload: CacaoPayload) throws -> String { + let address = try DIDPKH(iss: payload.iss).account.address + let iss = try DIDPKH(iss: payload.iss) + let message = SIWEMessage( + domain: payload.domain, + uri: payload.aud, + address: address, + version: payload.version, + nonce: payload.nonce, + chainId: iss.account.reference, + iat: payload.iat, + nbf: payload.nbf, + exp: payload.exp, + statement: payload.statement, + requestId: payload.requestId, + resources: payload.resources + ) + return message.formatted + } +} diff --git a/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift b/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift new file mode 100644 index 000000000..0a7fc18df --- /dev/null +++ b/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift @@ -0,0 +1,72 @@ +import Foundation + +public struct SIWEMessage: Equatable { + public let domain: String + public let uri: String // aud + public let address: String + public let version: String + public let nonce: String + public let chainId: String + public let iat: String + public let nbf: String? + public let exp: String? + public let statement: String? + public let requestId: String? + public let resources: [String]? + + public init(domain: String, uri: String, address: String, version: String, nonce: String, chainId: String, iat: String, nbf: String?, exp: String?, statement: String?, requestId: String?, resources: [String]?) { + self.domain = domain + self.uri = uri + self.address = address + self.version = version + self.nonce = nonce + self.chainId = chainId + self.iat = iat + self.nbf = nbf + self.exp = exp + self.statement = statement + self.requestId = requestId + self.resources = resources + } + + public var formatted: String { + return """ + \(domain) wants you to sign in with your Ethereum account: + \(address) + \(statementLine) + URI: \(uri) + Version: \(version) + Chain ID: \(chainId) + Nonce: \(nonce) + Issued At: \(iat)\(expLine)\(nbfLine)\(requestIdLine)\(resourcesSection) + """ + } +} + +private extension SIWEMessage { + + var expLine: String { + guard let exp = exp else { return "" } + return "\nExpiration Time: \(exp)" + } + + var statementLine: String { + guard let statement = statement else { return "" } + return "\n\(statement)\n" + } + + var nbfLine: String { + guard let nbf = nbf else { return "" } + return "\nNot Before: \(nbf)" + } + + var requestIdLine: String { + guard let requestId = requestId else { return "" } + return "\nRequest ID: \(requestId)" + } + + var resourcesSection: String { + guard let resources = resources else { return "" } + return resources.reduce("\nResources:") { $0 + "\n- \($1)" } + } +} diff --git a/Tests/AuthTests/AppRespondSubscriberTests.swift b/Tests/AuthTests/AppRespondSubscriberTests.swift index 72f3f4f51..71baa80ef 100644 --- a/Tests/AuthTests/AppRespondSubscriberTests.swift +++ b/Tests/AuthTests/AppRespondSubscriberTests.swift @@ -60,7 +60,7 @@ class AppRespondSubscriberTests: XCTestCase { // subscribe on compromised cacao let account = Account(chainIdentifier: "eip155:1", address: "0x724d0D2DaD3fbB0C168f947B87Fa5DBe36F1A8bf")! let cacaoHeader = CacaoHeader(t: "eip4361") - let cacaoPayload = CacaoPayload(params: compromissedParams.payloadParams, didpkh: DIDPKH(account: account)) + let cacaoPayload = compromissedParams.payloadParams.cacaoPayload(didpkh: DIDPKH(account: account)) let cacaoSignature = CacaoSignature(t: .eip191, s: "") let cacao = Cacao(h: cacaoHeader, p: cacaoPayload, s: cacaoSignature) From 075390ee8067daa12f1dc61344fea37f1056b50b Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 2 Feb 2023 14:30:39 +0530 Subject: [PATCH 18/42] IdentityNetworkService --- .../AuthenticationService.swift | 12 ---- .../Authentication/IdentityKeyService.swift | 35 +++++++---- .../IdentityNetworkService.swift | 59 +++++++++++++++++++ 3 files changed, 84 insertions(+), 22 deletions(-) delete mode 100644 Sources/Chat/ProtocolServices/Authentication/AuthenticationService.swift create mode 100644 Sources/Chat/ProtocolServices/Authentication/IdentityNetworkService.swift diff --git a/Sources/Chat/ProtocolServices/Authentication/AuthenticationService.swift b/Sources/Chat/ProtocolServices/Authentication/AuthenticationService.swift deleted file mode 100644 index b1dead4ed..000000000 --- a/Sources/Chat/ProtocolServices/Authentication/AuthenticationService.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Foundation - -final class AuthenticationService { - - private let accountService: AccountService - - init(accountService: AccountService) { - self.accountService = accountService - } - - -} diff --git a/Sources/Chat/ProtocolServices/Authentication/IdentityKeyService.swift b/Sources/Chat/ProtocolServices/Authentication/IdentityKeyService.swift index 256eec8c6..131a143df 100644 --- a/Sources/Chat/ProtocolServices/Authentication/IdentityKeyService.swift +++ b/Sources/Chat/ProtocolServices/Authentication/IdentityKeyService.swift @@ -2,37 +2,52 @@ import Foundation enum IdentityKeyAPI: HTTPService { - case register(cacao: String) // TODO: Cacao - case resolve(publicKey: String) + case registerIdentity(cacao: Cacao) + case resolveIdentity(publicKey: String) + case removeIdentity(cacao: Cacao) + case registerInvite(idAuth: String) + case resolveInvite(account: String) + case removeInvite(idAuth: String) var path: String { - return "/identity" + switch self { + case .registerIdentity, .resolveIdentity, .removeIdentity: + return "/identity" + case .registerInvite, .resolveInvite, .removeInvite: + return "/invite" + } } var method: WalletConnectNetworking.HTTPMethod { switch self { - case .register: + case .registerIdentity, .registerInvite: return .post - case .resolve: + case .resolveIdentity, .resolveInvite: return .get + case .removeInvite, .removeIdentity: + return .delete } } var body: Data? { switch self { - case .register(let cacao): + case .registerIdentity(let cacao), .removeIdentity(let cacao): return try? JSONEncoder().encode(cacao) - case .resolve: + case .registerInvite(let idAuth), .removeInvite(let idAuth): + return try? JSONEncoder().encode(["idAuth": idAuth]) + case .resolveIdentity, .resolveInvite: return nil } } var queryParameters: [String : String]? { switch self { - case .register: - return nil - case .resolve(let publicKey): + case .resolveIdentity(let publicKey): return ["publicKey": publicKey] + case .resolveInvite(let account): + return ["account": account] + case .registerIdentity, .registerInvite, .removeInvite, .removeIdentity: + return nil } } } diff --git a/Sources/Chat/ProtocolServices/Authentication/IdentityNetworkService.swift b/Sources/Chat/ProtocolServices/Authentication/IdentityNetworkService.swift new file mode 100644 index 000000000..51e77b1e2 --- /dev/null +++ b/Sources/Chat/ProtocolServices/Authentication/IdentityNetworkService.swift @@ -0,0 +1,59 @@ +import Foundation + +actor IdentityNetworkService { + + private let accountService: AccountService + private let httpService: HTTPClient + + init(accountService: AccountService, httpService: HTTPClient) { + self.accountService = accountService + self.httpService = httpService + } + + // MARK: - IdentityKey + + func registerIdentity(cacao: Cacao) async throws { + let api = IdentityKeyAPI.registerIdentity(cacao: cacao) + try await httpService.request(service: api) + } + + func resolveIdentity(publicKey: String) async throws -> Cacao { + let api = IdentityKeyAPI.resolveIdentity(publicKey: publicKey) + let response = try await httpService.request(ResolveIdentityResponse.self, at: api) + return response.cacao + } + + func removeIdentity(cacao: Cacao) async throws { + let api = IdentityKeyAPI.removeIdentity(cacao: cacao) + try await httpService.request(service: api) + } + + // MARK: - InviteKey + + func registerInvite(idAuth: String) async throws { + let api = IdentityKeyAPI.registerInvite(idAuth: idAuth) + try await httpService.request(service: api) + } + + func resolveInvite(account: String) async throws -> String { + let api = IdentityKeyAPI.resolveInvite(account: account) + let response = try await httpService.request(ResolveInviteResponse.self, at: api) + return response.inviteKey + } + + func removeInvite(idAuth: String) async throws { + let api = IdentityKeyAPI.removeInvite(idAuth: idAuth) + try await httpService.request(service: api) + } +} + +private extension IdentityNetworkService { + + struct ResolveIdentityResponse: Codable { + let cacao: Cacao + } + + struct ResolveInviteResponse: Codable { + let inviteKey: String + } +} From 1dad95bad4d8519efcb321f809b43be235924688 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 2 Feb 2023 14:46:11 +0530 Subject: [PATCH 19/42] IdentityStorage --- .../AuthenticationStorage.swift | 12 ----- .../Authentication/IdentityStorage.swift | 44 +++++++++++++++++++ 2 files changed, 44 insertions(+), 12 deletions(-) delete mode 100644 Sources/Chat/ProtocolServices/Authentication/AuthenticationStorage.swift create mode 100644 Sources/Chat/ProtocolServices/Authentication/IdentityStorage.swift diff --git a/Sources/Chat/ProtocolServices/Authentication/AuthenticationStorage.swift b/Sources/Chat/ProtocolServices/Authentication/AuthenticationStorage.swift deleted file mode 100644 index f5430e7bf..000000000 --- a/Sources/Chat/ProtocolServices/Authentication/AuthenticationStorage.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Foundation - -typealias IdentityKey = SigningPrivateKey - -final class AuthenticationStorage { - - private let kms: KeychainServiceProtocol - - init(kms: KeychainServiceProtocol) { - self.kms = kms - } -} diff --git a/Sources/Chat/ProtocolServices/Authentication/IdentityStorage.swift b/Sources/Chat/ProtocolServices/Authentication/IdentityStorage.swift new file mode 100644 index 000000000..f8100471b --- /dev/null +++ b/Sources/Chat/ProtocolServices/Authentication/IdentityStorage.swift @@ -0,0 +1,44 @@ +import Foundation + +typealias IdentityKey = SigningPrivateKey +typealias InviteKey = SigningPrivateKey + +final class IdentityStorage { + + private let keychain: KeychainStorageProtocol + + init(keychain: KeychainStorageProtocol) { + self.keychain = keychain + } + + func createIdentityKey(for account: Account) throws -> IdentityKey { + let key = IdentityKey() + try keychain.add(key, forKey: identityKeyIdentifier(for: account)) + return key + } + + func createInviteKey(for account: Account) throws -> InviteKey { + let key = InviteKey() + try keychain.add(key, forKey: inviteKeyIdentifier(for: account)) + return key + } + + func getIdentityKey(for account: Account) -> IdentityKey? { + return try? keychain.read(key: identityKeyIdentifier(for: account)) + } + + func getInviteKey(for account: Account) -> InviteKey? { + return try? keychain.read(key: inviteKeyIdentifier(for: account)) + } +} + +private extension IdentityStorage { + + func identityKeyIdentifier(for account: Account) -> String { + return "com.walletconnect.chat.identity.\(account.absoluteString)" + } + + func inviteKeyIdentifier(for account: Account) -> String { + return "com.walletconnect.chat.invite.\(account.absoluteString)" + } +} From a492d80fbae4bce53ea725a3fb93e52d48281d41 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 2 Feb 2023 15:55:39 +0530 Subject: [PATCH 20/42] MessageSigner use CacaoPayload --- Example/IntegrationTests/Auth/AuthTests.swift | 3 +- .../Auth/Signer/CacaoSignerTests.swift | 8 ++--- .../AuthRequest/AuthRequestInteractor.swift | 3 +- Sources/Auth/AuthClient.swift | 2 +- Sources/Auth/AuthClientFactory.swift | 2 +- .../Services/App/AppRespondSubscriber.swift | 7 ++--- .../Common/SIWEMessageFormatter.swift | 29 ------------------- .../Auth/Services/Signer/MessageSigner.swift | 12 ++++---- .../Signer/MessageSignerFactory.swift | 2 +- .../Wallet/WalletRespondService.swift | 3 +- Sources/Auth/Types/AuthPayload.swift | 16 ++++++++-- .../IdentityKeyService.swift | 0 .../IdentityNetworkService.swift | 0 .../Identity/IdentityRegisterService.swift | 5 ++++ .../IdentityStorage.swift | 0 .../AuthTests/AppRespondSubscriberTests.swift | 7 ++--- .../Mocks/SIWEMessageFormatterMock.swift | 6 +--- .../AuthTests/SIWEMessageFormatterTests.swift | 20 ++++++------- Tests/AuthTests/Stubs/MessageSignerMock.swift | 3 +- 19 files changed, 52 insertions(+), 76 deletions(-) delete mode 100644 Sources/Auth/Services/Common/SIWEMessageFormatter.swift rename Sources/Chat/ProtocolServices/{Authentication => Identity}/IdentityKeyService.swift (100%) rename Sources/Chat/ProtocolServices/{Authentication => Identity}/IdentityNetworkService.swift (100%) create mode 100644 Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift rename Sources/Chat/ProtocolServices/{Authentication => Identity}/IdentityStorage.swift (100%) diff --git a/Example/IntegrationTests/Auth/AuthTests.swift b/Example/IntegrationTests/Auth/AuthTests.swift index 8bede13a1..436091772 100644 --- a/Example/IntegrationTests/Auth/AuthTests.swift +++ b/Example/IntegrationTests/Auth/AuthTests.swift @@ -83,7 +83,8 @@ final class AuthTests: XCTestCase { Task(priority: .high) { let signerFactory = DefaultSignerFactory() let signer = MessageSignerFactory(signerFactory: signerFactory).create(projectId: InputConfig.projectId) - let signature = try! signer.sign(payload: request.payload, address: walletAccount.address, privateKey: prvKey, type: .eip191) + let payload = try! request.payload.cacaoPayload(address: walletAccount.address) + let signature = try! signer.sign(payload: payload, privateKey: prvKey, type: .eip191) try! await walletAuthClient.respond(requestId: request.id, signature: signature, from: walletAccount) } } diff --git a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift index c6481015b..8066c147d 100644 --- a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift @@ -45,12 +45,10 @@ class CacaoSignerTest: XCTestCase { func testCacaoSign() throws { let address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - let formatted = try SIWEMessageFormatter().formatMessage( - from: payload, - address: address - ) + let cacaoPayload = try payload.cacaoPayload(address: address) + let formatted = try SIWECacaoFormatter().formatMessage(from: cacaoPayload) XCTAssertEqual(formatted, message) - XCTAssertEqual(try signer.sign(payload: payload, address: address, privateKey: privateKey, type: .eip191), signature) + XCTAssertEqual(try signer.sign(payload: cacaoPayload, privateKey: privateKey, type: .eip191), signature) } func testCacaoVerify() async throws { diff --git a/Example/WalletApp/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift index 361d0b8fe..90f554f02 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift @@ -8,8 +8,7 @@ final class AuthRequestInteractor { func approve(request: AuthRequest) async throws { let privateKey = Data(hex: "e56da0e170b5e09a8bb8f1b693392c7d56c3739a9c75740fbc558a2877868540") let signature = try signer.sign( - payload: request.payload, - address: account.address, + payload: request.payload.cacaoPayload(address: account.address), privateKey: privateKey, type: .eip191) try await Web3Wallet.instance.respond(requestId: request.id, signature: signature, from: account) diff --git a/Sources/Auth/AuthClient.swift b/Sources/Auth/AuthClient.swift index 9ea611488..f654fb4c9 100644 --- a/Sources/Auth/AuthClient.swift +++ b/Sources/Auth/AuthClient.swift @@ -94,7 +94,7 @@ public class AuthClient: AuthClientProtocol { } public func formatMessage(payload: AuthPayload, address: String) throws -> String { - return try SIWEMessageFormatter().formatMessage(from: payload, address: address) + return try SIWECacaoFormatter().formatMessage(from: payload.cacaoPayload(address: address)) } private func setUpPublishers() { diff --git a/Sources/Auth/AuthClientFactory.swift b/Sources/Auth/AuthClientFactory.swift index 5fc6cb188..f9688eaf6 100644 --- a/Sources/Auth/AuthClientFactory.swift +++ b/Sources/Auth/AuthClientFactory.swift @@ -42,7 +42,7 @@ public struct AuthClientFactory { let kms = KeyManagementService(keychain: keychainStorage) let history = RPCHistoryFactory.createForNetwork(keyValueStorage: keyValueStorage) - let messageFormatter = SIWEMessageFormatter() + let messageFormatter = SIWECacaoFormatter() let appRequestService = AppRequestService(networkingInteractor: networkingClient, kms: kms, appMetadata: metadata, logger: logger, iatProvader: iatProvider) let messageSignerFactory = MessageSignerFactory(signerFactory: signerFactory) let messageSigner = messageSignerFactory.create(projectId: projectId) diff --git a/Sources/Auth/Services/App/AppRespondSubscriber.swift b/Sources/Auth/Services/App/AppRespondSubscriber.swift index d070880f5..70b48f95a 100644 --- a/Sources/Auth/Services/App/AppRespondSubscriber.swift +++ b/Sources/Auth/Services/App/AppRespondSubscriber.swift @@ -6,7 +6,7 @@ class AppRespondSubscriber { private let logger: ConsoleLogging private let rpcHistory: RPCHistory private let signatureVerifier: MessageSignatureVerifying - private let messageFormatter: SIWEMessageFormatting + private let messageFormatter: SIWECacaoFormatting private let pairingRegisterer: PairingRegisterer private var publishers = [AnyCancellable]() @@ -17,7 +17,7 @@ class AppRespondSubscriber { rpcHistory: RPCHistory, signatureVerifier: MessageSignatureVerifying, pairingRegisterer: PairingRegisterer, - messageFormatter: SIWEMessageFormatting) { + messageFormatter: SIWECacaoFormatting) { self.networkingInteractor = networkingInteractor self.logger = logger self.rpcHistory = rpcHistory @@ -52,8 +52,7 @@ class AppRespondSubscriber { guard let recovered = try? messageFormatter.formatMessage( - from: requestPayload.payloadParams, - address: address + from: requestPayload.payloadParams.cacaoPayload(address: address) ), recovered == message else { self.onResponse?(requestId, .failure(.messageCompromised)); return } diff --git a/Sources/Auth/Services/Common/SIWEMessageFormatter.swift b/Sources/Auth/Services/Common/SIWEMessageFormatter.swift deleted file mode 100644 index 0e4034d5f..000000000 --- a/Sources/Auth/Services/Common/SIWEMessageFormatter.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Foundation - -protocol SIWEMessageFormatting { - func formatMessage(from payload: AuthPayload, address: String) throws -> String - func formatMessage(from payload: CacaoPayload) throws -> String -} - -public struct SIWEMessageFormatter: SIWEMessageFormatting { - - enum Errors: Error { - case invalidChainID - } - - public init() { } - - public func formatMessage(from payload: AuthPayload, address: String) throws -> String { - guard - let blockchain = Blockchain(payload.chainId), - let account = Account(blockchain: blockchain, address: address) else { - throw Errors.invalidChainID - } - let payload = payload.cacaoPayload(didpkh: DIDPKH(account: account)) - return try formatMessage(from: payload) - } - - func formatMessage(from payload: CacaoPayload) throws -> String { - return try SIWECacaoFormatter().formatMessage(from: payload) - } -} diff --git a/Sources/Auth/Services/Signer/MessageSigner.swift b/Sources/Auth/Services/Signer/MessageSigner.swift index 7af8792a2..6b958dec5 100644 --- a/Sources/Auth/Services/Signer/MessageSigner.swift +++ b/Sources/Auth/Services/Signer/MessageSigner.swift @@ -9,8 +9,7 @@ public protocol MessageSignatureVerifying { } public protocol MessageSigning { - func sign(payload: AuthPayload, - address: String, + func sign(payload: CacaoPayload, privateKey: Data, type: CacaoSignatureType ) throws -> CacaoSignature @@ -27,22 +26,21 @@ struct MessageSigner: AuthMessageSigner { private let signer: EthereumSigner private let eip191Verifier: EIP191Verifier private let eip1271Verifier: EIP1271Verifier - private let messageFormatter: SIWEMessageFormatting + private let messageFormatter: SIWECacaoFormatting - init(signer: EthereumSigner, eip191Verifier: EIP191Verifier, eip1271Verifier: EIP1271Verifier, messageFormatter: SIWEMessageFormatting) { + init(signer: EthereumSigner, eip191Verifier: EIP191Verifier, eip1271Verifier: EIP1271Verifier, messageFormatter: SIWECacaoFormatting) { self.signer = signer self.eip191Verifier = eip191Verifier self.eip1271Verifier = eip1271Verifier self.messageFormatter = messageFormatter } - func sign(payload: AuthPayload, - address: String, + func sign(payload: CacaoPayload, privateKey: Data, type: CacaoSignatureType ) throws -> CacaoSignature { - let message = try messageFormatter.formatMessage(from: payload, address: address) + let message = try messageFormatter.formatMessage(from: payload) guard let messageData = message.data(using: .utf8)else { throw Errors.utf8EncodingFailed diff --git a/Sources/Auth/Services/Signer/MessageSignerFactory.swift b/Sources/Auth/Services/Signer/MessageSignerFactory.swift index 88d56d374..60ad7657a 100644 --- a/Sources/Auth/Services/Signer/MessageSignerFactory.swift +++ b/Sources/Auth/Services/Signer/MessageSignerFactory.swift @@ -21,7 +21,7 @@ public struct MessageSignerFactory { httpClient: HTTPNetworkClient(host: "rpc.walletconnect.com"), signer: signerFactory.createEthereumSigner() ), - messageFormatter: SIWEMessageFormatter() + messageFormatter: SIWECacaoFormatter() ) } } diff --git a/Sources/Auth/Services/Wallet/WalletRespondService.swift b/Sources/Auth/Services/Wallet/WalletRespondService.swift index 8ea1946e9..62bb3427a 100644 --- a/Sources/Auth/Services/Wallet/WalletRespondService.swift +++ b/Sources/Auth/Services/Wallet/WalletRespondService.swift @@ -29,9 +29,8 @@ actor WalletRespondService { try kms.setAgreementSecret(keys, topic: topic) - let didpkh = DIDPKH(account: account) let header = CacaoHeader(t: "eip4361") - let payload = authRequestParams.payloadParams.cacaoPayload(didpkh: didpkh) + let payload = try authRequestParams.payloadParams.cacaoPayload(address: account.address) let responseParams = AuthResponseParams(h: header, p: payload, s: signature) let response = RPCResponse(id: requestId, result: responseParams) diff --git a/Sources/Auth/Types/AuthPayload.swift b/Sources/Auth/Types/AuthPayload.swift index 00d8b934b..0e6f7fd1d 100644 --- a/Sources/Auth/Types/AuthPayload.swift +++ b/Sources/Auth/Types/AuthPayload.swift @@ -29,9 +29,14 @@ public struct AuthPayload: Codable, Equatable { self.resources = requestParams.resources } - func cacaoPayload(didpkh: DIDPKH) -> CacaoPayload { + public func cacaoPayload(address: String) throws -> CacaoPayload { + guard + let blockchain = Blockchain(chainId), + let account = Account(blockchain: blockchain, address: address) else { + throw Errors.invalidChainID + } return CacaoPayload( - iss: didpkh.iss, + iss: DIDPKH(account: account).iss, domain: domain, aud: aud, version: version, @@ -45,3 +50,10 @@ public struct AuthPayload: Codable, Equatable { ) } } + +private extension AuthPayload { + + enum Errors: Error { + case invalidChainID + } +} diff --git a/Sources/Chat/ProtocolServices/Authentication/IdentityKeyService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityKeyService.swift similarity index 100% rename from Sources/Chat/ProtocolServices/Authentication/IdentityKeyService.swift rename to Sources/Chat/ProtocolServices/Identity/IdentityKeyService.swift diff --git a/Sources/Chat/ProtocolServices/Authentication/IdentityNetworkService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityNetworkService.swift similarity index 100% rename from Sources/Chat/ProtocolServices/Authentication/IdentityNetworkService.swift rename to Sources/Chat/ProtocolServices/Identity/IdentityNetworkService.swift diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift new file mode 100644 index 000000000..b109d9742 --- /dev/null +++ b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift @@ -0,0 +1,5 @@ +import Foundation + +actor IdentityRegisterService { + +} diff --git a/Sources/Chat/ProtocolServices/Authentication/IdentityStorage.swift b/Sources/Chat/ProtocolServices/Identity/IdentityStorage.swift similarity index 100% rename from Sources/Chat/ProtocolServices/Authentication/IdentityStorage.swift rename to Sources/Chat/ProtocolServices/Identity/IdentityStorage.swift diff --git a/Tests/AuthTests/AppRespondSubscriberTests.swift b/Tests/AuthTests/AppRespondSubscriberTests.swift index 71baa80ef..e5a64db4b 100644 --- a/Tests/AuthTests/AppRespondSubscriberTests.swift +++ b/Tests/AuthTests/AppRespondSubscriberTests.swift @@ -11,7 +11,7 @@ class AppRespondSubscriberTests: XCTestCase { var networkingInteractor: NetworkingInteractorMock! var sut: AppRespondSubscriber! - var messageFormatter: SIWEMessageFormatter! + var messageFormatter: SIWECacaoFormatter! var rpcHistory: RPCHistory! let defaultTimeout: TimeInterval = 0.01 var messageSigner: AuthMessageSigner! @@ -20,7 +20,7 @@ class AppRespondSubscriberTests: XCTestCase { override func setUp() { networkingInteractor = NetworkingInteractorMock() - messageFormatter = SIWEMessageFormatter() + messageFormatter = SIWECacaoFormatter() messageSigner = MessageSignerMock() rpcHistory = RPCHistoryFactory.createForNetwork(keyValueStorage: RuntimeKeyValueStorage()) pairingStorage = WCPairingStorageMock() @@ -58,9 +58,8 @@ class AppRespondSubscriberTests: XCTestCase { } // subscribe on compromised cacao - let account = Account(chainIdentifier: "eip155:1", address: "0x724d0D2DaD3fbB0C168f947B87Fa5DBe36F1A8bf")! let cacaoHeader = CacaoHeader(t: "eip4361") - let cacaoPayload = compromissedParams.payloadParams.cacaoPayload(didpkh: DIDPKH(account: account)) + let cacaoPayload = try! compromissedParams.payloadParams.cacaoPayload(address: "0x724d0D2DaD3fbB0C168f947B87Fa5DBe36F1A8bf") let cacaoSignature = CacaoSignature(t: .eip191, s: "") let cacao = Cacao(h: cacaoHeader, p: cacaoPayload, s: cacaoSignature) diff --git a/Tests/AuthTests/Mocks/SIWEMessageFormatterMock.swift b/Tests/AuthTests/Mocks/SIWEMessageFormatterMock.swift index 64adc7c96..0796eb6ce 100644 --- a/Tests/AuthTests/Mocks/SIWEMessageFormatterMock.swift +++ b/Tests/AuthTests/Mocks/SIWEMessageFormatterMock.swift @@ -1,13 +1,9 @@ import Foundation @testable import Auth -class SIWEMessageFormatterMock: SIWEMessageFormatting { +class SIWEMessageFormatterMock: SIWECacaoFormatting { var formattedMessage: String! - func formatMessage(from authPayload: AuthPayload, address: String) throws -> String { - return formattedMessage - } - func formatMessage(from payload: CacaoPayload) throws -> String { return formattedMessage } diff --git a/Tests/AuthTests/SIWEMessageFormatterTests.swift b/Tests/AuthTests/SIWEMessageFormatterTests.swift index 859b2cf41..129fe4c52 100644 --- a/Tests/AuthTests/SIWEMessageFormatterTests.swift +++ b/Tests/AuthTests/SIWEMessageFormatterTests.swift @@ -3,11 +3,11 @@ import Foundation import XCTest class SIWEMessageFormatterTests: XCTestCase { - var sut: SIWEMessageFormatter! + var sut: SIWECacaoFormatter! let address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" override func setUp() { - sut = SIWEMessageFormatter() + sut = SIWECacaoFormatter() } func testFormatMessage() throws { @@ -27,7 +27,7 @@ class SIWEMessageFormatterTests: XCTestCase { - ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/ - https://example.com/my-web2-claim.json """ - let message = try sut.formatMessage(from: AuthPayload.stub(), address: address) + let message = try sut.formatMessage(from: AuthPayload.stub().cacaoPayload(address: address)) XCTAssertEqual(message, expectedMessage) } @@ -48,8 +48,9 @@ class SIWEMessageFormatterTests: XCTestCase { """ let message = try sut.formatMessage( from: AuthPayload.stub( - requestParams: RequestParams.stub(statement: nil)), - address: address) + requestParams: RequestParams.stub(statement: nil) + ).cacaoPayload(address: address) + ) XCTAssertEqual(message, expectedMessage) } @@ -69,8 +70,8 @@ class SIWEMessageFormatterTests: XCTestCase { """ let message = try sut.formatMessage( from: AuthPayload.stub( - requestParams: RequestParams.stub(resources: nil)), - address: address) + requestParams: RequestParams.stub(resources: nil)).cacaoPayload(address: address) + ) XCTAssertEqual(message, expectedMessage) } @@ -88,9 +89,8 @@ class SIWEMessageFormatterTests: XCTestCase { """ let message = try sut.formatMessage( from: AuthPayload.stub( - requestParams: RequestParams.stub(statement: nil, - resources: nil)), - address: address) + requestParams: RequestParams.stub(statement: nil, resources: nil)).cacaoPayload(address: address) + ) XCTAssertEqual(message, expectedMessage) } } diff --git a/Tests/AuthTests/Stubs/MessageSignerMock.swift b/Tests/AuthTests/Stubs/MessageSignerMock.swift index 4275cd1b9..bc48a36d6 100644 --- a/Tests/AuthTests/Stubs/MessageSignerMock.swift +++ b/Tests/AuthTests/Stubs/MessageSignerMock.swift @@ -11,8 +11,7 @@ struct MessageSignerMock: AuthMessageSigner { } - func sign(payload: AuthPayload, - address: String, + func sign(payload: CacaoPayload, privateKey: Data, type: CacaoSignatureType ) throws -> CacaoSignature { From 5ff9dcfd33c6e17ea2448c8a3373d83719880e1a Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 2 Feb 2023 16:25:21 +0530 Subject: [PATCH 21/42] WalletConnectSigner --- Example/ExampleApp.xcodeproj/project.pbxproj | 7 ++ .../xcschemes/WalletConnectSigner.xcscheme | 67 +++++++++++++++++++ .../Auth/Signer/EIP1271VerifierTests.swift | 1 + .../Auth/Signer/EIP191VerifierTests.swift | 1 + Package.swift | 6 ++ Sources/Auth/AuthImports.swift | 1 + Sources/Chat/ChatImports.swift | 2 +- .../Cacao/Cacao.swift | 0 .../Cacao/CacaoHeader.swift | 0 .../Cacao/CacaoPayload.swift | 0 .../Cacao/CacaoSignature.swift | 0 .../DIDPKH/DIDPKH.swift | 0 .../SIWE/SIWECacaoFormatter.swift | 0 .../SIWE/SIWEMessage.swift | 0 .../Ethereum/EIP1271/EIP1271Verifier.swift | 0 .../Signer/Ethereum/EIP1271/RPCService.swift | 0 .../EIP1271/ValidSignatureMethod.swift | 0 .../Ethereum/EIP191/EIP191Verifier.swift | 0 .../Signer}/EthereumSignature.swift | 0 .../Signer}/EthereumSigner.swift | 0 .../Signer/MessageSigner.swift | 4 +- .../Signer/MessageSignerFactory.swift | 4 +- .../Signer/SignerFactory.swift | 0 .../WalletConnectSigner/SignerImports.swift | 3 + .../AuthTests/AppRespondSubscriberTests.swift | 2 +- Tests/AuthTests/Stubs/MessageSignerMock.swift | 2 +- 26 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectSigner.xcscheme rename Sources/{WalletConnectUtils => WalletConnectSigner}/Cacao/Cacao.swift (100%) rename Sources/{WalletConnectUtils => WalletConnectSigner}/Cacao/CacaoHeader.swift (100%) rename Sources/{WalletConnectUtils => WalletConnectSigner}/Cacao/CacaoPayload.swift (100%) rename Sources/{WalletConnectUtils => WalletConnectSigner}/Cacao/CacaoSignature.swift (100%) rename Sources/{WalletConnectUtils => WalletConnectSigner}/DIDPKH/DIDPKH.swift (100%) rename Sources/{WalletConnectUtils => WalletConnectSigner}/SIWE/SIWECacaoFormatter.swift (100%) rename Sources/{WalletConnectUtils => WalletConnectSigner}/SIWE/SIWEMessage.swift (100%) rename Sources/{Auth/Services => WalletConnectSigner}/Signer/Ethereum/EIP1271/EIP1271Verifier.swift (100%) rename Sources/{Auth/Services => WalletConnectSigner}/Signer/Ethereum/EIP1271/RPCService.swift (100%) rename Sources/{Auth/Services => WalletConnectSigner}/Signer/Ethereum/EIP1271/ValidSignatureMethod.swift (100%) rename Sources/{Auth/Services => WalletConnectSigner}/Signer/Ethereum/EIP191/EIP191Verifier.swift (100%) rename Sources/{Auth/Services/Signer/Ethereum => WalletConnectSigner/Signer}/EthereumSignature.swift (100%) rename Sources/{Auth/Services/Signer/Ethereum => WalletConnectSigner/Signer}/EthereumSigner.swift (100%) rename Sources/{Auth/Services => WalletConnectSigner}/Signer/MessageSigner.swift (95%) rename Sources/{Auth/Services => WalletConnectSigner}/Signer/MessageSignerFactory.swift (86%) rename Sources/{Auth/Services => WalletConnectSigner}/Signer/SignerFactory.swift (100%) create mode 100644 Sources/WalletConnectSigner/SignerImports.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 2982ae6f2..0ca4e2635 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -209,6 +209,7 @@ A5E22D222840C8D300E36487 /* WalletEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D212840C8D300E36487 /* WalletEngine.swift */; }; A5E22D242840C8DB00E36487 /* SafariEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D232840C8DB00E36487 /* SafariEngine.swift */; }; A5E22D2C2840EAC300E36487 /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D2B2840EAC300E36487 /* XCUIElement.swift */; }; + A5F145D7298BCCDD0051B18A /* WalletConnectSigner in Frameworks */ = {isa = PBXBuildFile; productRef = A5F145D6298BCCDD0051B18A /* WalletConnectSigner */; }; C5133A78294125CC00A8314C /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = C5133A77294125CC00A8314C /* Web3 */; }; C53AA4362941251C008EA57C /* DefaultSignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59CF4F5292F83D50031A42F /* DefaultSignerFactory.swift */; }; C55D347F295DD7140004314A /* AuthRequestModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55D347A295DD7140004314A /* AuthRequestModule.swift */; }; @@ -675,6 +676,7 @@ A5C8BE85292FE20B006CC85C /* Web3 in Frameworks */, 84DDB4ED28ABB663003D66ED /* WalletConnectAuth in Frameworks */, C5DD5BE1294E09E3008FD3A4 /* Web3Wallet in Frameworks */, + A5F145D7298BCCDD0051B18A /* WalletConnectSigner in Frameworks */, A5E03E01286466EA00888481 /* WalletConnectChat in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1869,6 +1871,7 @@ 847CF3AE28E3141700F1D760 /* WalletConnectPush */, A5C8BE84292FE20B006CC85C /* Web3 */, C5DD5BE0294E09E3008FD3A4 /* Web3Wallet */, + A5F145D6298BCCDD0051B18A /* WalletConnectSigner */, ); productName = IntegrationTests; productReference = A5E03DED286464DB00888481 /* IntegrationTests.xctest */; @@ -3172,6 +3175,10 @@ isa = XCSwiftPackageProductDependency; productName = WalletConnectChat; }; + A5F145D6298BCCDD0051B18A /* WalletConnectSigner */ = { + isa = XCSwiftPackageProductDependency; + productName = WalletConnectSigner; + }; C5133A77294125CC00A8314C /* Web3 */ = { isa = XCSwiftPackageProductDependency; package = A5AE354528A1A2AC0059AE8A /* XCRemoteSwiftPackageReference "Web3" */; diff --git a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectSigner.xcscheme b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectSigner.xcscheme new file mode 100644 index 000000000..5fadfb8e0 --- /dev/null +++ b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectSigner.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift b/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift index 45c5c1bdd..40b66bcb4 100644 --- a/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift +++ b/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift @@ -1,6 +1,7 @@ import Foundation import XCTest @testable import Auth +@testable import WalletConnectSigner import JSONRPC class EIP1271VerifierTests: XCTestCase { diff --git a/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift b/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift index 2e5c9c1f3..5d5aa2c25 100644 --- a/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift +++ b/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift @@ -1,6 +1,7 @@ import Foundation import XCTest @testable import Auth +@testable import WalletConnectSigner class EIP191VerifierTests: XCTestCase { diff --git a/Package.swift b/Package.swift index c633746d6..214912491 100644 --- a/Package.swift +++ b/Package.swift @@ -43,6 +43,9 @@ let package = Package( .library( name: "Web3Inbox", targets: ["Web3Inbox"]), + .library( + name: "WalletConnectSigner", + targets: ["WalletConnectSigner"]), ], dependencies: [], targets: [ @@ -85,6 +88,9 @@ let package = Package( .target( name: "Web3Inbox", dependencies: ["WalletConnectChat"]), + .target( + name: "WalletConnectSigner", + dependencies: ["WalletConnectNetworking"]), .target( name: "WalletConnectUtils", dependencies: ["JSONRPC"]), diff --git a/Sources/Auth/AuthImports.swift b/Sources/Auth/AuthImports.swift index 27245bda6..f27efa95c 100644 --- a/Sources/Auth/AuthImports.swift +++ b/Sources/Auth/AuthImports.swift @@ -1,3 +1,4 @@ #if !CocoaPods @_exported import WalletConnectPairing +@_exported import WalletConnectSigner #endif diff --git a/Sources/Chat/ChatImports.swift b/Sources/Chat/ChatImports.swift index 23c1738ef..338babe27 100644 --- a/Sources/Chat/ChatImports.swift +++ b/Sources/Chat/ChatImports.swift @@ -1,3 +1,3 @@ #if !CocoaPods -@_exported import WalletConnectNetworking +@_exported import WalletConnectSigner #endif diff --git a/Sources/WalletConnectUtils/Cacao/Cacao.swift b/Sources/WalletConnectSigner/Cacao/Cacao.swift similarity index 100% rename from Sources/WalletConnectUtils/Cacao/Cacao.swift rename to Sources/WalletConnectSigner/Cacao/Cacao.swift diff --git a/Sources/WalletConnectUtils/Cacao/CacaoHeader.swift b/Sources/WalletConnectSigner/Cacao/CacaoHeader.swift similarity index 100% rename from Sources/WalletConnectUtils/Cacao/CacaoHeader.swift rename to Sources/WalletConnectSigner/Cacao/CacaoHeader.swift diff --git a/Sources/WalletConnectUtils/Cacao/CacaoPayload.swift b/Sources/WalletConnectSigner/Cacao/CacaoPayload.swift similarity index 100% rename from Sources/WalletConnectUtils/Cacao/CacaoPayload.swift rename to Sources/WalletConnectSigner/Cacao/CacaoPayload.swift diff --git a/Sources/WalletConnectUtils/Cacao/CacaoSignature.swift b/Sources/WalletConnectSigner/Cacao/CacaoSignature.swift similarity index 100% rename from Sources/WalletConnectUtils/Cacao/CacaoSignature.swift rename to Sources/WalletConnectSigner/Cacao/CacaoSignature.swift diff --git a/Sources/WalletConnectUtils/DIDPKH/DIDPKH.swift b/Sources/WalletConnectSigner/DIDPKH/DIDPKH.swift similarity index 100% rename from Sources/WalletConnectUtils/DIDPKH/DIDPKH.swift rename to Sources/WalletConnectSigner/DIDPKH/DIDPKH.swift diff --git a/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift b/Sources/WalletConnectSigner/SIWE/SIWECacaoFormatter.swift similarity index 100% rename from Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift rename to Sources/WalletConnectSigner/SIWE/SIWECacaoFormatter.swift diff --git a/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift b/Sources/WalletConnectSigner/SIWE/SIWEMessage.swift similarity index 100% rename from Sources/WalletConnectUtils/SIWE/SIWEMessage.swift rename to Sources/WalletConnectSigner/SIWE/SIWEMessage.swift diff --git a/Sources/Auth/Services/Signer/Ethereum/EIP1271/EIP1271Verifier.swift b/Sources/WalletConnectSigner/Signer/Ethereum/EIP1271/EIP1271Verifier.swift similarity index 100% rename from Sources/Auth/Services/Signer/Ethereum/EIP1271/EIP1271Verifier.swift rename to Sources/WalletConnectSigner/Signer/Ethereum/EIP1271/EIP1271Verifier.swift diff --git a/Sources/Auth/Services/Signer/Ethereum/EIP1271/RPCService.swift b/Sources/WalletConnectSigner/Signer/Ethereum/EIP1271/RPCService.swift similarity index 100% rename from Sources/Auth/Services/Signer/Ethereum/EIP1271/RPCService.swift rename to Sources/WalletConnectSigner/Signer/Ethereum/EIP1271/RPCService.swift diff --git a/Sources/Auth/Services/Signer/Ethereum/EIP1271/ValidSignatureMethod.swift b/Sources/WalletConnectSigner/Signer/Ethereum/EIP1271/ValidSignatureMethod.swift similarity index 100% rename from Sources/Auth/Services/Signer/Ethereum/EIP1271/ValidSignatureMethod.swift rename to Sources/WalletConnectSigner/Signer/Ethereum/EIP1271/ValidSignatureMethod.swift diff --git a/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift b/Sources/WalletConnectSigner/Signer/Ethereum/EIP191/EIP191Verifier.swift similarity index 100% rename from Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift rename to Sources/WalletConnectSigner/Signer/Ethereum/EIP191/EIP191Verifier.swift diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift b/Sources/WalletConnectSigner/Signer/EthereumSignature.swift similarity index 100% rename from Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift rename to Sources/WalletConnectSigner/Signer/EthereumSignature.swift diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift b/Sources/WalletConnectSigner/Signer/EthereumSigner.swift similarity index 100% rename from Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift rename to Sources/WalletConnectSigner/Signer/EthereumSigner.swift diff --git a/Sources/Auth/Services/Signer/MessageSigner.swift b/Sources/WalletConnectSigner/Signer/MessageSigner.swift similarity index 95% rename from Sources/Auth/Services/Signer/MessageSigner.swift rename to Sources/WalletConnectSigner/Signer/MessageSigner.swift index 6b958dec5..5ecfdf8fa 100644 --- a/Sources/Auth/Services/Signer/MessageSigner.swift +++ b/Sources/WalletConnectSigner/Signer/MessageSigner.swift @@ -15,9 +15,9 @@ public protocol MessageSigning { ) throws -> CacaoSignature } -public typealias AuthMessageSigner = MessageSignatureVerifying & MessageSigning +public typealias CacaoMessageSigner = MessageSignatureVerifying & MessageSigning -struct MessageSigner: AuthMessageSigner { +struct MessageSigner: CacaoMessageSigner { enum Errors: Error { case utf8EncodingFailed diff --git a/Sources/Auth/Services/Signer/MessageSignerFactory.swift b/Sources/WalletConnectSigner/Signer/MessageSignerFactory.swift similarity index 86% rename from Sources/Auth/Services/Signer/MessageSignerFactory.swift rename to Sources/WalletConnectSigner/Signer/MessageSignerFactory.swift index 60ad7657a..ef4f53879 100644 --- a/Sources/Auth/Services/Signer/MessageSignerFactory.swift +++ b/Sources/WalletConnectSigner/Signer/MessageSignerFactory.swift @@ -8,11 +8,11 @@ public struct MessageSignerFactory { self.signerFactory = signerFactory } - public func create() -> AuthMessageSigner { + public func create() -> CacaoMessageSigner { return create(projectId: Networking.projectId) } - func create(projectId: String) -> AuthMessageSigner { + public func create(projectId: String) -> CacaoMessageSigner { return MessageSigner( signer: signerFactory.createEthereumSigner(), eip191Verifier: EIP191Verifier(signer: signerFactory.createEthereumSigner()), diff --git a/Sources/Auth/Services/Signer/SignerFactory.swift b/Sources/WalletConnectSigner/Signer/SignerFactory.swift similarity index 100% rename from Sources/Auth/Services/Signer/SignerFactory.swift rename to Sources/WalletConnectSigner/Signer/SignerFactory.swift diff --git a/Sources/WalletConnectSigner/SignerImports.swift b/Sources/WalletConnectSigner/SignerImports.swift new file mode 100644 index 000000000..23c1738ef --- /dev/null +++ b/Sources/WalletConnectSigner/SignerImports.swift @@ -0,0 +1,3 @@ +#if !CocoaPods +@_exported import WalletConnectNetworking +#endif diff --git a/Tests/AuthTests/AppRespondSubscriberTests.swift b/Tests/AuthTests/AppRespondSubscriberTests.swift index e5a64db4b..473ea5d1d 100644 --- a/Tests/AuthTests/AppRespondSubscriberTests.swift +++ b/Tests/AuthTests/AppRespondSubscriberTests.swift @@ -14,7 +14,7 @@ class AppRespondSubscriberTests: XCTestCase { var messageFormatter: SIWECacaoFormatter! var rpcHistory: RPCHistory! let defaultTimeout: TimeInterval = 0.01 - var messageSigner: AuthMessageSigner! + var messageSigner: CacaoMessageSigner! var pairingStorage: WCPairingStorageMock! var pairingRegisterer: PairingRegistererMock! diff --git a/Tests/AuthTests/Stubs/MessageSignerMock.swift b/Tests/AuthTests/Stubs/MessageSignerMock.swift index bc48a36d6..1d3cf358d 100644 --- a/Tests/AuthTests/Stubs/MessageSignerMock.swift +++ b/Tests/AuthTests/Stubs/MessageSignerMock.swift @@ -1,7 +1,7 @@ import Foundation import Auth -struct MessageSignerMock: AuthMessageSigner { +struct MessageSignerMock: CacaoMessageSigner { func verify(signature: CacaoSignature, message: String, From ad20fc09956baaae3b71d5b733ff03a0e586070a Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 2 Feb 2023 17:23:14 +0530 Subject: [PATCH 22/42] IdentityRegisterService --- .../Auth/Services/Common/IATProvider.swift | 11 ---- .../Identity/IdentityRegisterService.swift | 60 ++++++++++++++++++- .../Identity/IdentityStorage.swift | 8 +-- .../ClientAuth/DIDKeyFactory.swift | 8 ++- .../Cacao/IATProvider.swift | 14 +++++ 5 files changed, 80 insertions(+), 21 deletions(-) delete mode 100644 Sources/Auth/Services/Common/IATProvider.swift create mode 100644 Sources/WalletConnectSigner/Cacao/IATProvider.swift diff --git a/Sources/Auth/Services/Common/IATProvider.swift b/Sources/Auth/Services/Common/IATProvider.swift deleted file mode 100644 index 1d386c11e..000000000 --- a/Sources/Auth/Services/Common/IATProvider.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -protocol IATProvider { - var iat: String { get } -} - -struct DefaultIATProvider: IATProvider { - var iat: String { - return ISO8601DateFormatter().string(from: Date()) - } -} diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift index b109d9742..34daae0a3 100644 --- a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift +++ b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift @@ -1,5 +1,63 @@ import Foundation actor IdentityRegisterService { - + + private let keyserverURL: URL + private let identityStorage: IdentityStorage + private let identityNetworkService: IdentityNetworkService + private let iatProvader: IATProvider + private let messageFormatter: SIWECacaoFormatting + + init( + keyserverURL: URL, + identityStorage: IdentityStorage, + identityNetworkService: IdentityNetworkService, + iatProvader: IATProvider, + messageFormatter: SIWECacaoFormatting + ) { + self.keyserverURL = keyserverURL + self.identityStorage = identityStorage + self.identityNetworkService = identityNetworkService + self.iatProvader = iatProvader + self.messageFormatter = messageFormatter + } + + func register(account: Account, isPrivate: Bool, onSign: (String) -> CacaoSignature) async throws -> String { + if let identityKey = identityStorage.getIdentityKey(for: account) { + return identityKey.publicKey.hexRepresentation + } + + let identityKey = IdentityKey() + let identityPublicKey = identityKey.publicKey + let identityKeyDID = ED25519DIDKeyFactory().make( + pubKey: identityPublicKey.rawRepresentation, prefix: true + ) + let cacaoHeader = CacaoHeader(t: "eip4361") + let cacaoPayload = makeCacaoPayload(identityKeyDID: identityKeyDID, account: account) + let cacaoSignature = onSign(try messageFormatter.formatMessage(from: cacaoPayload)) + + let cacao = Cacao(h: cacaoHeader, p: cacaoPayload, s: cacaoSignature) + try await identityNetworkService.registerIdentity(cacao: cacao) + + // TODO: Handle private mode + + try identityStorage.saveIdentityKey(identityKey, for: account) + return identityPublicKey.hexRepresentation + } +} + +private extension IdentityRegisterService { + + func makeCacaoPayload(identityKeyDID: String, account: Account) -> CacaoPayload { + return CacaoPayload( + iss: DIDPKH(account: account).iss, + domain: keyserverURL.host!, + aud: keyserverURL.absoluteString, + version: "1", + nonce: Data.randomBytes(count: 32).toHexString(), + iat: iatProvader.iat, + nbf: nil, exp: nil, statement: nil, requestId: nil, + resources: [identityKeyDID] + ) + } } diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityStorage.swift b/Sources/Chat/ProtocolServices/Identity/IdentityStorage.swift index f8100471b..db1d873f0 100644 --- a/Sources/Chat/ProtocolServices/Identity/IdentityStorage.swift +++ b/Sources/Chat/ProtocolServices/Identity/IdentityStorage.swift @@ -11,16 +11,12 @@ final class IdentityStorage { self.keychain = keychain } - func createIdentityKey(for account: Account) throws -> IdentityKey { - let key = IdentityKey() + func saveIdentityKey(_ key: IdentityKey, for account: Account) throws { try keychain.add(key, forKey: identityKeyIdentifier(for: account)) - return key } - func createInviteKey(for account: Account) throws -> InviteKey { - let key = InviteKey() + func saveInviteKey(_ key: InviteKey, for account: Account) throws { try keychain.add(key, forKey: inviteKeyIdentifier(for: account)) - return key } func getIdentityKey(for account: Account) -> IdentityKey? { diff --git a/Sources/WalletConnectRelay/ClientAuth/DIDKeyFactory.swift b/Sources/WalletConnectRelay/ClientAuth/DIDKeyFactory.swift index 2a062c090..1d3bb7066 100644 --- a/Sources/WalletConnectRelay/ClientAuth/DIDKeyFactory.swift +++ b/Sources/WalletConnectRelay/ClientAuth/DIDKeyFactory.swift @@ -1,19 +1,21 @@ import Foundation -protocol DIDKeyFactory { +public protocol DIDKeyFactory { func make(pubKey: Data, prefix: Bool) -> String } /// A DID Method for Static Cryptographic Keys /// did-key-format := did:key:MULTIBASE(base58-btc, MULTICODEC(public-key-type, raw-public-key-bytes)) -struct ED25519DIDKeyFactory: DIDKeyFactory { +public struct ED25519DIDKeyFactory: DIDKeyFactory { private let DID_DELIMITER = ":" private let DID_PREFIX = "did" private let DID_METHOD = "key" private let MULTICODEC_ED25519_HEADER: [UInt8] = [0xed, 0x01] private let MULTICODEC_ED25519_BASE = "z" - func make(pubKey: Data, prefix: Bool) -> String { + public init() { } + + public func make(pubKey: Data, prefix: Bool) -> String { let multibase = multibase(pubKey: pubKey) guard prefix else { return multibase } diff --git a/Sources/WalletConnectSigner/Cacao/IATProvider.swift b/Sources/WalletConnectSigner/Cacao/IATProvider.swift new file mode 100644 index 000000000..22aefa45d --- /dev/null +++ b/Sources/WalletConnectSigner/Cacao/IATProvider.swift @@ -0,0 +1,14 @@ +import Foundation + +public protocol IATProvider { + var iat: String { get } +} + +public struct DefaultIATProvider: IATProvider { + + public init() { } + + public var iat: String { + return ISO8601DateFormatter().string(from: Date()) + } +} From 015b7fd5744b0607f2c25ae7b348ab342ac34544 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 2 Feb 2023 19:23:12 +0530 Subject: [PATCH 23/42] WalletConnectSigner scheme --- .../xcshareddata/xcschemes/WalletConnectSigner.xcscheme | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectSigner.xcscheme b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectSigner.xcscheme index 5fadfb8e0..7d2425bad 100644 --- a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectSigner.xcscheme +++ b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectSigner.xcscheme @@ -17,7 +17,7 @@ BlueprintIdentifier = "WalletConnectSigner" BuildableName = "WalletConnectSigner" BlueprintName = "WalletConnectSigner" - ReferencedContainer = "container:"> + ReferencedContainer = "container:.."> @@ -53,7 +53,7 @@ BlueprintIdentifier = "WalletConnectSigner" BuildableName = "WalletConnectSigner" BlueprintName = "WalletConnectSigner" - ReferencedContainer = "container:"> + ReferencedContainer = "container:.."> From c107d3c6850278b09e36c5c36c2ab57c3c223312 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 3 Feb 2023 18:32:26 +0530 Subject: [PATCH 24/42] Account removed from getPendingRequests --- Sources/Auth/AuthClient.swift | 4 ++-- Sources/Auth/AuthClientProtocol.swift | 2 +- Sources/Auth/Services/Wallet/PendingRequestsProvider.swift | 2 +- Sources/Web3Wallet/Web3WalletClient.swift | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/Auth/AuthClient.swift b/Sources/Auth/AuthClient.swift index f654fb4c9..2ab5e242a 100644 --- a/Sources/Auth/AuthClient.swift +++ b/Sources/Auth/AuthClient.swift @@ -89,8 +89,8 @@ public class AuthClient: AuthClientProtocol { /// Query pending authentication requests /// - Returns: Pending authentication requests - public func getPendingRequests(account: Account) throws -> [AuthRequest] { - return try pendingRequestsProvider.getPendingRequests(account: account) + public func getPendingRequests() throws -> [AuthRequest] { + return try pendingRequestsProvider.getPendingRequests() } public func formatMessage(payload: AuthPayload, address: String) throws -> String { diff --git a/Sources/Auth/AuthClientProtocol.swift b/Sources/Auth/AuthClientProtocol.swift index 9e1a1fb62..31413cb76 100644 --- a/Sources/Auth/AuthClientProtocol.swift +++ b/Sources/Auth/AuthClientProtocol.swift @@ -7,5 +7,5 @@ public protocol AuthClientProtocol { func formatMessage(payload: AuthPayload, address: String) throws -> String func respond(requestId: RPCID, signature: CacaoSignature, from account: Account) async throws func reject(requestId: RPCID) async throws - func getPendingRequests(account: Account) throws -> [AuthRequest] + func getPendingRequests() throws -> [AuthRequest] } diff --git a/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift b/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift index 4aa8c04c0..524c029d5 100644 --- a/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift +++ b/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift @@ -7,7 +7,7 @@ class PendingRequestsProvider { self.rpcHistory = rpcHistory } - public func getPendingRequests(account: Account) throws -> [AuthRequest] { + public func getPendingRequests() throws -> [AuthRequest] { let pendingRequests: [AuthRequest] = rpcHistory.getPending() .filter {$0.request.method == "wc_authRequest"} .compactMap { diff --git a/Sources/Web3Wallet/Web3WalletClient.swift b/Sources/Web3Wallet/Web3WalletClient.swift index 43c709b95..d9397de4e 100644 --- a/Sources/Web3Wallet/Web3WalletClient.swift +++ b/Sources/Web3Wallet/Web3WalletClient.swift @@ -169,7 +169,7 @@ public class Web3WalletClient { /// Query pending authentication requests /// - Returns: Pending authentication requests - public func getPendingRequests(account: Account) throws -> [AuthRequest] { - try authClient.getPendingRequests(account: account) + public func getPendingRequests() throws -> [AuthRequest] { + try authClient.getPendingRequests() } } From 877a6c552f0da68bf21355450edd22a1f67ccad2 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 6 Feb 2023 17:18:24 +0530 Subject: [PATCH 25/42] registerInvite implemented --- .../xcschemes/WalletConnectJWT.xcscheme | 67 +++++++++++++ Package.swift | 12 ++- .../Identity/IdentityKey.swift | 3 + .../Identity/IdentityRegisterService.swift | 93 +++++++++++++++---- .../Identity/IdentityStorage.swift | 7 +- .../JWT => WalletConnectJWT}/JWT+Claims.swift | 1 + .../JWT => WalletConnectJWT}/JWT+Header.swift | 0 .../JWT => WalletConnectJWT}/JWT.swift | 4 +- .../JWT => WalletConnectJWT}/JWTEncoder.swift | 0 Sources/WalletConnectJWT/JWTFactory.swift | 28 ++++++ Sources/WalletConnectJWT/JWTImports.swift | 3 + .../JWT => WalletConnectJWT}/JWTSigning.swift | 0 .../SigningKeyCryptoKit.swift | 6 ++ .../ClientAuth/SocketAuthenticator.swift | 22 ++--- Sources/WalletConnectRelay/RelayImports.swift | 2 +- .../Cacao/Cacao.swift | 0 .../Cacao/CacaoHeader.swift | 0 .../Cacao/CacaoPayload.swift | 0 .../Cacao/CacaoSignature.swift | 0 .../Cacao/IATProvider.swift | 0 .../DID}/Base58.swift | 0 .../DID}/DIDKeyFactory.swift | 0 .../DID}/DIDPKH.swift | 7 ++ .../SIWE/SIWECacaoFormatter.swift | 0 .../SIWE/SIWEMessage.swift | 0 25 files changed, 213 insertions(+), 42 deletions(-) create mode 100644 Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectJWT.xcscheme create mode 100644 Sources/Chat/ProtocolServices/Identity/IdentityKey.swift rename Sources/{WalletConnectRelay/ClientAuth/JWT => WalletConnectJWT}/JWT+Claims.swift (95%) rename Sources/{WalletConnectRelay/ClientAuth/JWT => WalletConnectJWT}/JWT+Header.swift (100%) rename Sources/{WalletConnectRelay/ClientAuth/JWT => WalletConnectJWT}/JWT.swift (85%) rename Sources/{WalletConnectRelay/ClientAuth/JWT => WalletConnectJWT}/JWTEncoder.swift (100%) create mode 100644 Sources/WalletConnectJWT/JWTFactory.swift create mode 100644 Sources/WalletConnectJWT/JWTImports.swift rename Sources/{WalletConnectRelay/ClientAuth/JWT => WalletConnectJWT}/JWTSigning.swift (100%) rename Sources/{WalletConnectSigner => WalletConnectUtils}/Cacao/Cacao.swift (100%) rename Sources/{WalletConnectSigner => WalletConnectUtils}/Cacao/CacaoHeader.swift (100%) rename Sources/{WalletConnectSigner => WalletConnectUtils}/Cacao/CacaoPayload.swift (100%) rename Sources/{WalletConnectSigner => WalletConnectUtils}/Cacao/CacaoSignature.swift (100%) rename Sources/{WalletConnectSigner => WalletConnectUtils}/Cacao/IATProvider.swift (100%) rename Sources/{WalletConnectRelay/ClientAuth => WalletConnectUtils/DID}/Base58.swift (100%) rename Sources/{WalletConnectRelay/ClientAuth => WalletConnectUtils/DID}/DIDKeyFactory.swift (100%) rename Sources/{WalletConnectSigner/DIDPKH => WalletConnectUtils/DID}/DIDPKH.swift (88%) rename Sources/{WalletConnectSigner => WalletConnectUtils}/SIWE/SIWECacaoFormatter.swift (100%) rename Sources/{WalletConnectSigner => WalletConnectUtils}/SIWE/SIWEMessage.swift (100%) diff --git a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectJWT.xcscheme b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectJWT.xcscheme new file mode 100644 index 000000000..0bfec5ddc --- /dev/null +++ b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletConnectJWT.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Package.swift b/Package.swift index 214912491..9455df255 100644 --- a/Package.swift +++ b/Package.swift @@ -43,6 +43,11 @@ let package = Package( .library( name: "Web3Inbox", targets: ["Web3Inbox"]), + // TODO: Remove library + .library( + name: "WalletConnectJWT", + targets: ["WalletConnectJWT"]), + // TODO: Remove library .library( name: "WalletConnectSigner", targets: ["WalletConnectSigner"]), @@ -59,7 +64,7 @@ let package = Package( path: "Sources/Chat"), .target( name: "Auth", - dependencies: ["WalletConnectPairing"], + dependencies: ["WalletConnectPairing", "WalletConnectSigner"], path: "Sources/Auth"), .target( name: "Web3Wallet", @@ -75,7 +80,7 @@ let package = Package( path: "Sources/WalletConnectEcho"), .target( name: "WalletConnectRelay", - dependencies: ["WalletConnectKMS"], + dependencies: ["WalletConnectJWT"], path: "Sources/WalletConnectRelay", resources: [.copy("PackageConfig.json")]), .target( @@ -91,6 +96,9 @@ let package = Package( .target( name: "WalletConnectSigner", dependencies: ["WalletConnectNetworking"]), + .target( + name: "WalletConnectJWT", + dependencies: ["WalletConnectKMS"]), .target( name: "WalletConnectUtils", dependencies: ["JSONRPC"]), diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityKey.swift b/Sources/Chat/ProtocolServices/Identity/IdentityKey.swift new file mode 100644 index 000000000..b172afbdb --- /dev/null +++ b/Sources/Chat/ProtocolServices/Identity/IdentityKey.swift @@ -0,0 +1,3 @@ +import Foundation + +typealias IdentityKey = SigningPrivateKey diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift index 34daae0a3..68353adfe 100644 --- a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift +++ b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift @@ -22,42 +22,99 @@ actor IdentityRegisterService { self.messageFormatter = messageFormatter } - func register(account: Account, isPrivate: Bool, onSign: (String) -> CacaoSignature) async throws -> String { + func registerIdentity(account: Account, + isPrivate: Bool, + onSign: (String) -> CacaoSignature + ) async throws -> String { + if let identityKey = identityStorage.getIdentityKey(for: account) { return identityKey.publicKey.hexRepresentation } let identityKey = IdentityKey() - let identityPublicKey = identityKey.publicKey - let identityKeyDID = ED25519DIDKeyFactory().make( - pubKey: identityPublicKey.rawRepresentation, prefix: true - ) - let cacaoHeader = CacaoHeader(t: "eip4361") - let cacaoPayload = makeCacaoPayload(identityKeyDID: identityKeyDID, account: account) - let cacaoSignature = onSign(try messageFormatter.formatMessage(from: cacaoPayload)) - - let cacao = Cacao(h: cacaoHeader, p: cacaoPayload, s: cacaoSignature) + let cacao = try makeCacao(DIDKey: identityKey.DIDKey, account: account, onSign: onSign) try await identityNetworkService.registerIdentity(cacao: cacao) // TODO: Handle private mode try identityStorage.saveIdentityKey(identityKey, for: account) - return identityPublicKey.hexRepresentation + return identityKey.publicKey.hexRepresentation + } + + func registerInvite(account: Account, + isPrivate: Bool, + onSign: (String) -> CacaoSignature + ) async throws -> String { + + if let inviteKey = identityStorage.getInviteKey(for: account) { + return inviteKey.publicKey.hexRepresentation + } + + let inviteKey = IdentityKey() + try await identityNetworkService.registerInvite(idAuth: makeIDAuth( + account: account, + publicKeyString: inviteKey.publicKey.hexRepresentation + )) + + try identityStorage.saveIdentityKey(inviteKey, for: account) + return inviteKey.publicKey.hexRepresentation } } private extension IdentityRegisterService { - func makeCacaoPayload(identityKeyDID: String, account: Account) -> CacaoPayload { - return CacaoPayload( - iss: DIDPKH(account: account).iss, + enum Errors: Error { + case identityKeyNotFound + } + + func makeCacao( + DIDKey: String, + account: Account, + onSign: (String) -> CacaoSignature + ) throws -> Cacao { + let cacaoHeader = CacaoHeader(t: "eip4361") + let cacaoPayload = CacaoPayload( + iss: account.iss, domain: keyserverURL.host!, - aud: keyserverURL.absoluteString, - version: "1", - nonce: Data.randomBytes(count: 32).toHexString(), + aud: getAudience(), + version: getVersion(), + nonce: getNonce(), iat: iatProvader.iat, nbf: nil, exp: nil, statement: nil, requestId: nil, - resources: [identityKeyDID] + resources: [DIDKey] ) + let cacaoSignature = onSign(try messageFormatter.formatMessage(from: cacaoPayload)) + return Cacao(h: cacaoHeader, p: cacaoPayload, s: cacaoSignature) + } + + func makeIDAuth(account: Account, publicKeyString: String) throws -> String { + guard let inviteKey = identityStorage.getInviteKey(for: account) + else { throw Errors.identityKeyNotFound } + + return try JWTFactory().createAndSignJWT( + keyPair: inviteKey, + aud: getAudience(), + exp: getExpiry(), + pkh: account.iss + ) + } + + private func getNonce() -> String { + return Data.randomBytes(count: 32).toHexString() + } + + private func getVersion() -> String { + return "1" + } + + private func getExpiry() -> Int { + var components = DateComponents() + components.setValue(1, for: .hour) + let date = Calendar.current.date(byAdding: components, to: Date())! + return Int(date.timeIntervalSince1970) + } + + private func getAudience() -> String { + return keyserverURL.absoluteString } } diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityStorage.swift b/Sources/Chat/ProtocolServices/Identity/IdentityStorage.swift index db1d873f0..7f93bb075 100644 --- a/Sources/Chat/ProtocolServices/Identity/IdentityStorage.swift +++ b/Sources/Chat/ProtocolServices/Identity/IdentityStorage.swift @@ -1,8 +1,5 @@ import Foundation -typealias IdentityKey = SigningPrivateKey -typealias InviteKey = SigningPrivateKey - final class IdentityStorage { private let keychain: KeychainStorageProtocol @@ -15,7 +12,7 @@ final class IdentityStorage { try keychain.add(key, forKey: identityKeyIdentifier(for: account)) } - func saveInviteKey(_ key: InviteKey, for account: Account) throws { + func saveInviteKey(_ key: IdentityKey, for account: Account) throws { try keychain.add(key, forKey: inviteKeyIdentifier(for: account)) } @@ -23,7 +20,7 @@ final class IdentityStorage { return try? keychain.read(key: identityKeyIdentifier(for: account)) } - func getInviteKey(for account: Account) -> InviteKey? { + func getInviteKey(for account: Account) -> IdentityKey? { return try? keychain.read(key: inviteKeyIdentifier(for: account)) } } diff --git a/Sources/WalletConnectRelay/ClientAuth/JWT/JWT+Claims.swift b/Sources/WalletConnectJWT/JWT+Claims.swift similarity index 95% rename from Sources/WalletConnectRelay/ClientAuth/JWT/JWT+Claims.swift rename to Sources/WalletConnectJWT/JWT+Claims.swift index 14ea4cffd..125a2b50a 100644 --- a/Sources/WalletConnectRelay/ClientAuth/JWT/JWT+Claims.swift +++ b/Sources/WalletConnectJWT/JWT+Claims.swift @@ -7,6 +7,7 @@ extension JWT { let aud: String let iat: Int let exp: Int + let pkh: String? func encode() throws -> String { let jsonEncoder = JSONEncoder() diff --git a/Sources/WalletConnectRelay/ClientAuth/JWT/JWT+Header.swift b/Sources/WalletConnectJWT/JWT+Header.swift similarity index 100% rename from Sources/WalletConnectRelay/ClientAuth/JWT/JWT+Header.swift rename to Sources/WalletConnectJWT/JWT+Header.swift diff --git a/Sources/WalletConnectRelay/ClientAuth/JWT/JWT.swift b/Sources/WalletConnectJWT/JWT.swift similarity index 85% rename from Sources/WalletConnectRelay/ClientAuth/JWT/JWT.swift rename to Sources/WalletConnectJWT/JWT.swift index 17663319b..7633fb991 100644 --- a/Sources/WalletConnectRelay/ClientAuth/JWT/JWT.swift +++ b/Sources/WalletConnectJWT/JWT.swift @@ -9,12 +9,12 @@ struct JWT: Codable, Equatable { var claims: Claims var signature: String? - public init(header: Header = Header(), claims: Claims) { + init(header: Header = Header(), claims: Claims) { self.header = header self.claims = claims } - public mutating func sign(using jwtSigner: JWTSigning) throws { + mutating func sign(using jwtSigner: JWTSigning) throws { header.alg = jwtSigner.alg let headerString = try header.encode() let claimsString = try claims.encode() diff --git a/Sources/WalletConnectRelay/ClientAuth/JWT/JWTEncoder.swift b/Sources/WalletConnectJWT/JWTEncoder.swift similarity index 100% rename from Sources/WalletConnectRelay/ClientAuth/JWT/JWTEncoder.swift rename to Sources/WalletConnectJWT/JWTEncoder.swift diff --git a/Sources/WalletConnectJWT/JWTFactory.swift b/Sources/WalletConnectJWT/JWTFactory.swift new file mode 100644 index 000000000..17a04e124 --- /dev/null +++ b/Sources/WalletConnectJWT/JWTFactory.swift @@ -0,0 +1,28 @@ +import Foundation + +public struct JWTFactory { + + public init() { } + + public func createAndSignJWT( + keyPair: SigningPrivateKey, + aud: String, + exp: Int, + pkh: String? + ) throws -> String { + let now = Int(Date().timeIntervalSince1970) + let iss = keyPair.DIDKey + let sub = generateSubject() + let claims = JWT.Claims(iss: iss, sub: sub, aud: aud, iat: now, exp: exp, pkh: pkh) + var jwt = JWT(claims: claims) + try jwt.sign(using: EdDSASigner(keyPair)) + return try jwt.encoded() + } +} + +private extension JWTFactory { + + private func generateSubject() -> String { + return Data.randomBytes(count: 32).toHexString() + } +} diff --git a/Sources/WalletConnectJWT/JWTImports.swift b/Sources/WalletConnectJWT/JWTImports.swift new file mode 100644 index 000000000..24d4a8cab --- /dev/null +++ b/Sources/WalletConnectJWT/JWTImports.swift @@ -0,0 +1,3 @@ +#if !CocoaPods +@_exported import WalletConnectKMS +#endif diff --git a/Sources/WalletConnectRelay/ClientAuth/JWT/JWTSigning.swift b/Sources/WalletConnectJWT/JWTSigning.swift similarity index 100% rename from Sources/WalletConnectRelay/ClientAuth/JWT/JWTSigning.swift rename to Sources/WalletConnectJWT/JWTSigning.swift diff --git a/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/SigningKeyCryptoKit.swift b/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/SigningKeyCryptoKit.swift index f02cc72cb..527463fed 100644 --- a/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/SigningKeyCryptoKit.swift +++ b/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper/SigningKeyCryptoKit.swift @@ -79,4 +79,10 @@ public struct SigningPrivateKey: GenericPasswordConvertible, Equatable { public func signature(_ data: Data) throws -> Data { return try key.signature(for: data) } + + public var DIDKey: String { + return ED25519DIDKeyFactory().make( + pubKey: publicKey.rawRepresentation, prefix: true + ) + } } diff --git a/Sources/WalletConnectRelay/ClientAuth/SocketAuthenticator.swift b/Sources/WalletConnectRelay/ClientAuth/SocketAuthenticator.swift index 6858dcad5..1cfe42174 100644 --- a/Sources/WalletConnectRelay/ClientAuth/SocketAuthenticator.swift +++ b/Sources/WalletConnectRelay/ClientAuth/SocketAuthenticator.swift @@ -17,25 +17,19 @@ struct SocketAuthenticator: SocketAuthenticating { func createAuthToken() throws -> String { let clientIdKeyPair = try clientIdStorage.getOrCreateKeyPair() - let subject = generateSubject() - return try createAndSignJWT(subject: subject, keyPair: clientIdKeyPair) + return try createAndSignJWT(keyPair: clientIdKeyPair) } - private func createAndSignJWT(subject: String, keyPair: SigningPrivateKey) throws -> String { - let issuer = didKeyFactory.make(pubKey: keyPair.publicKey.rawRepresentation, prefix: true) - let now = Int(Date().timeIntervalSince1970) - let claims = JWT.Claims(iss: issuer, sub: subject, aud: getAudience(), iat: now, exp: getExpiry()) - var jwt = JWT(claims: claims) - try jwt.sign(using: EdDSASigner(keyPair)) - return try jwt.encoded() - } - - private func generateSubject() -> String { - return Data.randomBytes(count: 32).toHexString() + private func createAndSignJWT(keyPair: SigningPrivateKey) throws -> String { + return try JWTFactory().createAndSignJWT( + keyPair: keyPair, + aud: getAudience(), + exp: getExpiry(), + pkh: nil + ) } private func getExpiry() -> Int { - var components = DateComponents() components.setValue(1, for: .day) // safe to unwrap as the date must be calculated diff --git a/Sources/WalletConnectRelay/RelayImports.swift b/Sources/WalletConnectRelay/RelayImports.swift index 24d4a8cab..5c5e68a01 100644 --- a/Sources/WalletConnectRelay/RelayImports.swift +++ b/Sources/WalletConnectRelay/RelayImports.swift @@ -1,3 +1,3 @@ #if !CocoaPods -@_exported import WalletConnectKMS +@_exported import WalletConnectJWT #endif diff --git a/Sources/WalletConnectSigner/Cacao/Cacao.swift b/Sources/WalletConnectUtils/Cacao/Cacao.swift similarity index 100% rename from Sources/WalletConnectSigner/Cacao/Cacao.swift rename to Sources/WalletConnectUtils/Cacao/Cacao.swift diff --git a/Sources/WalletConnectSigner/Cacao/CacaoHeader.swift b/Sources/WalletConnectUtils/Cacao/CacaoHeader.swift similarity index 100% rename from Sources/WalletConnectSigner/Cacao/CacaoHeader.swift rename to Sources/WalletConnectUtils/Cacao/CacaoHeader.swift diff --git a/Sources/WalletConnectSigner/Cacao/CacaoPayload.swift b/Sources/WalletConnectUtils/Cacao/CacaoPayload.swift similarity index 100% rename from Sources/WalletConnectSigner/Cacao/CacaoPayload.swift rename to Sources/WalletConnectUtils/Cacao/CacaoPayload.swift diff --git a/Sources/WalletConnectSigner/Cacao/CacaoSignature.swift b/Sources/WalletConnectUtils/Cacao/CacaoSignature.swift similarity index 100% rename from Sources/WalletConnectSigner/Cacao/CacaoSignature.swift rename to Sources/WalletConnectUtils/Cacao/CacaoSignature.swift diff --git a/Sources/WalletConnectSigner/Cacao/IATProvider.swift b/Sources/WalletConnectUtils/Cacao/IATProvider.swift similarity index 100% rename from Sources/WalletConnectSigner/Cacao/IATProvider.swift rename to Sources/WalletConnectUtils/Cacao/IATProvider.swift diff --git a/Sources/WalletConnectRelay/ClientAuth/Base58.swift b/Sources/WalletConnectUtils/DID/Base58.swift similarity index 100% rename from Sources/WalletConnectRelay/ClientAuth/Base58.swift rename to Sources/WalletConnectUtils/DID/Base58.swift diff --git a/Sources/WalletConnectRelay/ClientAuth/DIDKeyFactory.swift b/Sources/WalletConnectUtils/DID/DIDKeyFactory.swift similarity index 100% rename from Sources/WalletConnectRelay/ClientAuth/DIDKeyFactory.swift rename to Sources/WalletConnectUtils/DID/DIDKeyFactory.swift diff --git a/Sources/WalletConnectSigner/DIDPKH/DIDPKH.swift b/Sources/WalletConnectUtils/DID/DIDPKH.swift similarity index 88% rename from Sources/WalletConnectSigner/DIDPKH/DIDPKH.swift rename to Sources/WalletConnectUtils/DID/DIDPKH.swift index a625b231a..065569cc2 100644 --- a/Sources/WalletConnectSigner/DIDPKH/DIDPKH.swift +++ b/Sources/WalletConnectUtils/DID/DIDPKH.swift @@ -31,3 +31,10 @@ public struct DIDPKH { self.account = account } } + +extension Account { + + public var iss: String { + return DIDPKH(account: self).iss + } +} diff --git a/Sources/WalletConnectSigner/SIWE/SIWECacaoFormatter.swift b/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift similarity index 100% rename from Sources/WalletConnectSigner/SIWE/SIWECacaoFormatter.swift rename to Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift diff --git a/Sources/WalletConnectSigner/SIWE/SIWEMessage.swift b/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift similarity index 100% rename from Sources/WalletConnectSigner/SIWE/SIWEMessage.swift rename to Sources/WalletConnectUtils/SIWE/SIWEMessage.swift From b34abce20464d0f5c7bf39105feddefcb403a8b1 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 6 Feb 2023 18:07:26 +0530 Subject: [PATCH 26/42] Resolve methods --- .../Identity/IdentityRegisterService.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift index 68353adfe..4d024d601 100644 --- a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift +++ b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift @@ -56,9 +56,19 @@ actor IdentityRegisterService { publicKeyString: inviteKey.publicKey.hexRepresentation )) + // TODO: Handle private mode + try identityStorage.saveIdentityKey(inviteKey, for: account) return inviteKey.publicKey.hexRepresentation } + + func resolveIdentity(publicKey: String) async throws -> Cacao { + return try await identityNetworkService.resolveIdentity(publicKey: publicKey) + } + + func resolveInvite(account: Account) async throws -> String { + return try await identityNetworkService.resolveInvite(account: account.absoluteString) + } } private extension IdentityRegisterService { From 6471c26d95343a6063ed8a092ec1d0c9c7a37684 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 6 Feb 2023 20:51:30 +0530 Subject: [PATCH 27/42] Registry integration tests --- .../IntegrationTests/Chat/RegistryTests.swift | 45 +++++++++++++++++++ ...yKeyService.swift => IdentityKeyAPI.swift} | 15 ++++++- .../Identity/IdentityNetworkService.swift | 7 ++- .../Identity/IdentityRegisterService.swift | 17 +++---- .../Signer/MessageSigner.swift | 12 +++++ 5 files changed, 82 insertions(+), 14 deletions(-) rename Sources/Chat/ProtocolServices/Identity/{IdentityKeyService.swift => IdentityKeyAPI.swift} (80%) diff --git a/Example/IntegrationTests/Chat/RegistryTests.swift b/Example/IntegrationTests/Chat/RegistryTests.swift index ea21c9375..2ce757b80 100644 --- a/Example/IntegrationTests/Chat/RegistryTests.swift +++ b/Example/IntegrationTests/Chat/RegistryTests.swift @@ -6,4 +6,49 @@ import WalletConnectUtils final class RegistryTests: XCTestCase { + let account = Account("eip155:1:0x15bca56b6e2728aec2532df9d436bd1600e86688")! + let privateKey = Data(hex: "305c6cde3846927892cd32762f6120539f3ec74c9e3a16b9b798b1e85351ae2a") + + var sut: IdentityRegisterService! + var storage: IdentityStorage! + var signer: CacaoMessageSigner! + + override func setUp() { + let keyserverURL = URL(string: "https://staging.keys.walletconnect.com")! + let httpService = HTTPNetworkClient(host: keyserverURL.host!) + let accountService = AccountService(currentAccount: account) + let identityNetworkService = IdentityNetworkService(accountService: accountService, httpService: httpService) + storage = IdentityStorage(keychain: KeychainStorageMock()) + sut = IdentityRegisterService( + keyserverURL: keyserverURL, + identityStorage: storage, + identityNetworkService: identityNetworkService, + iatProvader: DefaultIATProvider(), + messageFormatter: SIWECacaoFormatter() + ) + signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create(projectId: InputConfig.projectId) + } + + func testRegisterIdentity() async throws { + var message: String! + let publicKey = try await sut.registerIdentity(account: account, isPrivate: false) { msg in + message = msg + return try! signer.sign(message: msg, privateKey: privateKey, type: .eip191) + } + + let cacao = try await sut.resolveIdentity(publicKey: publicKey) + let recovered = storage.getIdentityKey(for: account)!.publicKey.hexRepresentation + + XCTAssertEqual(try SIWECacaoFormatter().formatMessage(from: cacao.p), message) + XCTAssertEqual(publicKey, recovered) + } + + func testRegisterInviteKey() async throws { + let inviteKey = try await sut.registerInvite(account: account, isPrivate: false, onSign: { msg in + return try! signer.sign(message: msg, privateKey: privateKey, type: .eip191) + }) + + let recovered = storage.getInviteKey(for: account)! + XCTAssertEqual(inviteKey, recovered.publicKey.hexRepresentation) + } } diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityKeyService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityKeyAPI.swift similarity index 80% rename from Sources/Chat/ProtocolServices/Identity/IdentityKeyService.swift rename to Sources/Chat/ProtocolServices/Identity/IdentityKeyAPI.swift index 131a143df..1346d40ac 100644 --- a/Sources/Chat/ProtocolServices/Identity/IdentityKeyService.swift +++ b/Sources/Chat/ProtocolServices/Identity/IdentityKeyAPI.swift @@ -32,9 +32,9 @@ enum IdentityKeyAPI: HTTPService { var body: Data? { switch self { case .registerIdentity(let cacao), .removeIdentity(let cacao): - return try? JSONEncoder().encode(cacao) + return try? JSONEncoder().encode(RegisterIdentityRequest(cacao: cacao)) case .registerInvite(let idAuth), .removeInvite(let idAuth): - return try? JSONEncoder().encode(["idAuth": idAuth]) + return try? JSONEncoder().encode(RegisterInviteRequest(idAuth: idAuth)) case .resolveIdentity, .resolveInvite: return nil } @@ -51,3 +51,14 @@ enum IdentityKeyAPI: HTTPService { } } } + +private extension IdentityKeyAPI { + + struct RegisterIdentityRequest: Codable { + let cacao: Cacao + } + + struct RegisterInviteRequest: Codable { + let idAuth: String + } +} diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityNetworkService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityNetworkService.swift index 51e77b1e2..8e1d08df2 100644 --- a/Sources/Chat/ProtocolServices/Identity/IdentityNetworkService.swift +++ b/Sources/Chat/ProtocolServices/Identity/IdentityNetworkService.swift @@ -20,7 +20,7 @@ actor IdentityNetworkService { func resolveIdentity(publicKey: String) async throws -> Cacao { let api = IdentityKeyAPI.resolveIdentity(publicKey: publicKey) let response = try await httpService.request(ResolveIdentityResponse.self, at: api) - return response.cacao + return response.value.cacao } func removeIdentity(cacao: Cacao) async throws { @@ -50,7 +50,10 @@ actor IdentityNetworkService { private extension IdentityNetworkService { struct ResolveIdentityResponse: Codable { - let cacao: Cacao + struct Value: Codable { + let cacao: Cacao + } + let value: Value } struct ResolveInviteResponse: Codable { diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift index 4d024d601..ab7ad3145 100644 --- a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift +++ b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift @@ -51,19 +51,19 @@ actor IdentityRegisterService { } let inviteKey = IdentityKey() - try await identityNetworkService.registerInvite(idAuth: makeIDAuth( - account: account, - publicKeyString: inviteKey.publicKey.hexRepresentation - )) + let idAuth = try makeIDAuth(account: account, inviteKey: inviteKey) + try await identityNetworkService.registerInvite(idAuth: idAuth) // TODO: Handle private mode - try identityStorage.saveIdentityKey(inviteKey, for: account) + try identityStorage.saveInviteKey(inviteKey, for: account) return inviteKey.publicKey.hexRepresentation } func resolveIdentity(publicKey: String) async throws -> Cacao { - return try await identityNetworkService.resolveIdentity(publicKey: publicKey) + let data = Data(hex: publicKey) + let did = ED25519DIDKeyFactory().make(pubKey: data, prefix: false) + return try await identityNetworkService.resolveIdentity(publicKey: did) } func resolveInvite(account: Account) async throws -> String { @@ -97,10 +97,7 @@ private extension IdentityRegisterService { return Cacao(h: cacaoHeader, p: cacaoPayload, s: cacaoSignature) } - func makeIDAuth(account: Account, publicKeyString: String) throws -> String { - guard let inviteKey = identityStorage.getInviteKey(for: account) - else { throw Errors.identityKeyNotFound } - + func makeIDAuth(account: Account, inviteKey: IdentityKey) throws -> String { return try JWTFactory().createAndSignJWT( keyPair: inviteKey, aud: getAudience(), diff --git a/Sources/WalletConnectSigner/Signer/MessageSigner.swift b/Sources/WalletConnectSigner/Signer/MessageSigner.swift index 5ecfdf8fa..b4eccf811 100644 --- a/Sources/WalletConnectSigner/Signer/MessageSigner.swift +++ b/Sources/WalletConnectSigner/Signer/MessageSigner.swift @@ -9,6 +9,11 @@ public protocol MessageSignatureVerifying { } public protocol MessageSigning { + func sign(message: String, + privateKey: Data, + type: CacaoSignatureType + ) throws -> CacaoSignature + func sign(payload: CacaoPayload, privateKey: Data, type: CacaoSignatureType @@ -41,6 +46,13 @@ struct MessageSigner: CacaoMessageSigner { ) throws -> CacaoSignature { let message = try messageFormatter.formatMessage(from: payload) + return try sign(message: message, privateKey: privateKey, type: type) + } + + func sign(message: String, + privateKey: Data, + type: CacaoSignatureType + ) throws -> CacaoSignature { guard let messageData = message.data(using: .utf8)else { throw Errors.utf8EncodingFailed From 81fa5e954d997d33edb978a78a11994ef5b70502 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 6 Feb 2023 21:19:02 +0530 Subject: [PATCH 28/42] Resolve tests --- Example/IntegrationTests/Chat/RegistryTests.swift | 15 ++++++++------- .../Identity/IdentityNetworkService.swift | 7 +++++-- .../Identity/IdentityRegisterService.swift | 10 +++++++--- Sources/WalletConnectJWT/JWTFactory.swift | 9 +-------- .../ClientAuth/SocketAuthenticator.swift | 5 +++++ 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/Example/IntegrationTests/Chat/RegistryTests.swift b/Example/IntegrationTests/Chat/RegistryTests.swift index 2ce757b80..e2f58588c 100644 --- a/Example/IntegrationTests/Chat/RegistryTests.swift +++ b/Example/IntegrationTests/Chat/RegistryTests.swift @@ -29,7 +29,7 @@ final class RegistryTests: XCTestCase { signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create(projectId: InputConfig.projectId) } - func testRegisterIdentity() async throws { + func testRegisterIdentityAndInviteKey() async throws { var message: String! let publicKey = try await sut.registerIdentity(account: account, isPrivate: false) { msg in message = msg @@ -37,18 +37,19 @@ final class RegistryTests: XCTestCase { } let cacao = try await sut.resolveIdentity(publicKey: publicKey) - let recovered = storage.getIdentityKey(for: account)!.publicKey.hexRepresentation - XCTAssertEqual(try SIWECacaoFormatter().formatMessage(from: cacao.p), message) + + let recovered = storage.getIdentityKey(for: account)!.publicKey.hexRepresentation XCTAssertEqual(publicKey, recovered) - } - func testRegisterInviteKey() async throws { let inviteKey = try await sut.registerInvite(account: account, isPrivate: false, onSign: { msg in return try! signer.sign(message: msg, privateKey: privateKey, type: .eip191) }) - let recovered = storage.getInviteKey(for: account)! - XCTAssertEqual(inviteKey, recovered.publicKey.hexRepresentation) + let recoveredKey = storage.getInviteKey(for: account)! + XCTAssertEqual(inviteKey, recoveredKey.publicKey.hexRepresentation) + + let resolvedKey = try await sut.resolveInvite(account: account) + XCTAssertEqual(inviteKey, resolvedKey) } } diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityNetworkService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityNetworkService.swift index 8e1d08df2..ca460fe7e 100644 --- a/Sources/Chat/ProtocolServices/Identity/IdentityNetworkService.swift +++ b/Sources/Chat/ProtocolServices/Identity/IdentityNetworkService.swift @@ -38,7 +38,7 @@ actor IdentityNetworkService { func resolveInvite(account: String) async throws -> String { let api = IdentityKeyAPI.resolveInvite(account: account) let response = try await httpService.request(ResolveInviteResponse.self, at: api) - return response.inviteKey + return response.value.inviteKey } func removeInvite(idAuth: String) async throws { @@ -57,6 +57,9 @@ private extension IdentityNetworkService { } struct ResolveInviteResponse: Codable { - let inviteKey: String + struct Value: Codable { + let inviteKey: String + } + let value: Value } } diff --git a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift index ab7ad3145..963290a9e 100644 --- a/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift +++ b/Sources/Chat/ProtocolServices/Identity/IdentityRegisterService.swift @@ -51,7 +51,8 @@ actor IdentityRegisterService { } let inviteKey = IdentityKey() - let idAuth = try makeIDAuth(account: account, inviteKey: inviteKey) + let invitePublicKey = inviteKey.publicKey.hexRepresentation + let idAuth = try makeIDAuth(account: account, invitePublicKey: invitePublicKey) try await identityNetworkService.registerInvite(idAuth: idAuth) // TODO: Handle private mode @@ -97,9 +98,12 @@ private extension IdentityRegisterService { return Cacao(h: cacaoHeader, p: cacaoPayload, s: cacaoSignature) } - func makeIDAuth(account: Account, inviteKey: IdentityKey) throws -> String { + func makeIDAuth(account: Account, invitePublicKey: String) throws -> String { + guard let identityKey = identityStorage.getIdentityKey(for: account) + else { throw Errors.identityKeyNotFound } return try JWTFactory().createAndSignJWT( - keyPair: inviteKey, + keyPair: identityKey, + sub: invitePublicKey, aud: getAudience(), exp: getExpiry(), pkh: account.iss diff --git a/Sources/WalletConnectJWT/JWTFactory.swift b/Sources/WalletConnectJWT/JWTFactory.swift index 17a04e124..3b459561a 100644 --- a/Sources/WalletConnectJWT/JWTFactory.swift +++ b/Sources/WalletConnectJWT/JWTFactory.swift @@ -6,23 +6,16 @@ public struct JWTFactory { public func createAndSignJWT( keyPair: SigningPrivateKey, + sub: String, aud: String, exp: Int, pkh: String? ) throws -> String { let now = Int(Date().timeIntervalSince1970) let iss = keyPair.DIDKey - let sub = generateSubject() let claims = JWT.Claims(iss: iss, sub: sub, aud: aud, iat: now, exp: exp, pkh: pkh) var jwt = JWT(claims: claims) try jwt.sign(using: EdDSASigner(keyPair)) return try jwt.encoded() } } - -private extension JWTFactory { - - private func generateSubject() -> String { - return Data.randomBytes(count: 32).toHexString() - } -} diff --git a/Sources/WalletConnectRelay/ClientAuth/SocketAuthenticator.swift b/Sources/WalletConnectRelay/ClientAuth/SocketAuthenticator.swift index 1cfe42174..1fbf12bac 100644 --- a/Sources/WalletConnectRelay/ClientAuth/SocketAuthenticator.swift +++ b/Sources/WalletConnectRelay/ClientAuth/SocketAuthenticator.swift @@ -23,6 +23,7 @@ struct SocketAuthenticator: SocketAuthenticating { private func createAndSignJWT(keyPair: SigningPrivateKey) throws -> String { return try JWTFactory().createAndSignJWT( keyPair: keyPair, + sub: getSubject(), aud: getAudience(), exp: getExpiry(), pkh: nil @@ -40,4 +41,8 @@ struct SocketAuthenticator: SocketAuthenticating { private func getAudience() -> String { return "wss://\(relayHost)" } + + private func getSubject() -> String { + return Data.randomBytes(count: 32).toHexString() + } } From 20d4a4ff229ece1cab3dd971c6d7ebce34731bef Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 6 Feb 2023 21:27:51 +0530 Subject: [PATCH 29/42] Unused libraries removed --- Package.swift | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Package.swift b/Package.swift index 9455df255..9a457fd6e 100644 --- a/Package.swift +++ b/Package.swift @@ -43,14 +43,6 @@ let package = Package( .library( name: "Web3Inbox", targets: ["Web3Inbox"]), - // TODO: Remove library - .library( - name: "WalletConnectJWT", - targets: ["WalletConnectJWT"]), - // TODO: Remove library - .library( - name: "WalletConnectSigner", - targets: ["WalletConnectSigner"]), ], dependencies: [], targets: [ From 5af776517fb6b196b0596a795f15499655b1b648 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 6 Feb 2023 21:51:21 +0530 Subject: [PATCH 30/42] WalletConnectSigner linking removed --- Example/ExampleApp.xcodeproj/project.pbxproj | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 0ca4e2635..2982ae6f2 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -209,7 +209,6 @@ A5E22D222840C8D300E36487 /* WalletEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D212840C8D300E36487 /* WalletEngine.swift */; }; A5E22D242840C8DB00E36487 /* SafariEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D232840C8DB00E36487 /* SafariEngine.swift */; }; A5E22D2C2840EAC300E36487 /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D2B2840EAC300E36487 /* XCUIElement.swift */; }; - A5F145D7298BCCDD0051B18A /* WalletConnectSigner in Frameworks */ = {isa = PBXBuildFile; productRef = A5F145D6298BCCDD0051B18A /* WalletConnectSigner */; }; C5133A78294125CC00A8314C /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = C5133A77294125CC00A8314C /* Web3 */; }; C53AA4362941251C008EA57C /* DefaultSignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59CF4F5292F83D50031A42F /* DefaultSignerFactory.swift */; }; C55D347F295DD7140004314A /* AuthRequestModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55D347A295DD7140004314A /* AuthRequestModule.swift */; }; @@ -676,7 +675,6 @@ A5C8BE85292FE20B006CC85C /* Web3 in Frameworks */, 84DDB4ED28ABB663003D66ED /* WalletConnectAuth in Frameworks */, C5DD5BE1294E09E3008FD3A4 /* Web3Wallet in Frameworks */, - A5F145D7298BCCDD0051B18A /* WalletConnectSigner in Frameworks */, A5E03E01286466EA00888481 /* WalletConnectChat in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1871,7 +1869,6 @@ 847CF3AE28E3141700F1D760 /* WalletConnectPush */, A5C8BE84292FE20B006CC85C /* Web3 */, C5DD5BE0294E09E3008FD3A4 /* Web3Wallet */, - A5F145D6298BCCDD0051B18A /* WalletConnectSigner */, ); productName = IntegrationTests; productReference = A5E03DED286464DB00888481 /* IntegrationTests.xctest */; @@ -3175,10 +3172,6 @@ isa = XCSwiftPackageProductDependency; productName = WalletConnectChat; }; - A5F145D6298BCCDD0051B18A /* WalletConnectSigner */ = { - isa = XCSwiftPackageProductDependency; - productName = WalletConnectSigner; - }; C5133A77294125CC00A8314C /* Web3 */ = { isa = XCSwiftPackageProductDependency; package = A5AE354528A1A2AC0059AE8A /* XCRemoteSwiftPackageReference "Web3" */; From e6c1defc094196d335730f0101b0753fc9267a40 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Tue, 7 Feb 2023 18:27:18 +0530 Subject: [PATCH 31/42] Unit tests build error --- Tests/Web3WalletTests/Mocks/AuthClientMock.swift | 2 +- Tests/Web3WalletTests/Web3WalletTests.swift | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Tests/Web3WalletTests/Mocks/AuthClientMock.swift b/Tests/Web3WalletTests/Mocks/AuthClientMock.swift index 3b1a3a68d..4f3e50c39 100644 --- a/Tests/Web3WalletTests/Mocks/AuthClientMock.swift +++ b/Tests/Web3WalletTests/Mocks/AuthClientMock.swift @@ -42,7 +42,7 @@ final class AuthClientMock: AuthClientProtocol { rejectCalled = true } - func getPendingRequests(account: WalletConnectUtils.Account) throws -> [AuthRequest] { + func getPendingRequests() throws -> [AuthRequest] { return [authRequest] } } diff --git a/Tests/Web3WalletTests/Web3WalletTests.swift b/Tests/Web3WalletTests/Web3WalletTests.swift index 7ce173cc5..8962e88a1 100644 --- a/Tests/Web3WalletTests/Web3WalletTests.swift +++ b/Tests/Web3WalletTests/Web3WalletTests.swift @@ -186,8 +186,7 @@ final class Web3WalletTests: XCTestCase { } func testAuthPendingRequestsCalledAndNotEmpty() async { - let account = Account("eip155:56:0xe5EeF1368781911d265fDB6946613dA61915a501")! - let pendingRequests = try! web3WalletClient.getPendingRequests(account: account) + let pendingRequests = try! web3WalletClient.getPendingRequests() XCTAssertEqual(1, pendingRequests.count) } } From 888c33174494c95277b73d32c067b3430f9faf55 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 8 Feb 2023 14:28:47 +0530 Subject: [PATCH 32/42] Unit tests fix --- Tests/RelayerTests/AuthTests/EdDSASignerTests.swift | 1 + Tests/RelayerTests/AuthTests/JWTTests.swift | 3 ++- Tests/RelayerTests/Mocks/EdDSASignerMock.swift | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Tests/RelayerTests/AuthTests/EdDSASignerTests.swift b/Tests/RelayerTests/AuthTests/EdDSASignerTests.swift index 2e5643785..913a2bed1 100644 --- a/Tests/RelayerTests/AuthTests/EdDSASignerTests.swift +++ b/Tests/RelayerTests/AuthTests/EdDSASignerTests.swift @@ -2,6 +2,7 @@ import Foundation import XCTest import WalletConnectKMS @testable import WalletConnectRelay +@testable import WalletConnectJWT final class EdDSASignerTests: XCTestCase { var sut: EdDSASigner! diff --git a/Tests/RelayerTests/AuthTests/JWTTests.swift b/Tests/RelayerTests/AuthTests/JWTTests.swift index 8f20cd961..d2eb4d8b6 100644 --- a/Tests/RelayerTests/AuthTests/JWTTests.swift +++ b/Tests/RelayerTests/AuthTests/JWTTests.swift @@ -1,6 +1,7 @@ import Foundation import XCTest @testable import WalletConnectRelay +@testable import WalletConnectJWT final class JWTTests: XCTestCase { let expectedJWT = "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2NTY5MTAwOTcsImV4cCI6MTY1Njk5NjQ5NywiaXNzIjoiZGlkOmtleTp6Nk1rb2RIWnduZVZSU2h0YUxmOEpLWWt4cERHcDF2R1pucEdtZEJwWDhNMmV4eEgiLCJzdWIiOiJjNDc5ZmU1ZGM0NjRlNzcxZTc4YjE5M2QyMzlhNjViNThkMjc4Y2FkMWMzNGJmYjBiNTcxNmU1YmI1MTQ5MjhlIiwiYXVkIjoid3NzOi8vcmVsYXkud2FsbGV0Y29ubmVjdC5jb20ifQ.0JkxOM-FV21U7Hk-xycargj_qNRaYV2H5HYtE4GzAeVQYiKWj7YySY5AdSqtCgGzX4Gt98XWXn2kSr9rE1qvCA" @@ -27,6 +28,6 @@ extension JWT.Claims { let aud = "wss://relay.walletconnect.com" let expDate = Calendar.current.date(byAdding: components, to: iatDate)! let exp = Int(expDate.timeIntervalSince1970) - return JWT.Claims(iss: iss, sub: sub, aud: aud, iat: iat, exp: exp) + return JWT.Claims(iss: iss, sub: sub, aud: aud, iat: iat, exp: exp, pkh: nil) } } diff --git a/Tests/RelayerTests/Mocks/EdDSASignerMock.swift b/Tests/RelayerTests/Mocks/EdDSASignerMock.swift index b7ca50718..dc52ed565 100644 --- a/Tests/RelayerTests/Mocks/EdDSASignerMock.swift +++ b/Tests/RelayerTests/Mocks/EdDSASignerMock.swift @@ -1,4 +1,5 @@ import Foundation +@testable import WalletConnectJWT @testable import WalletConnectRelay class EdDSASignerMock: JWTSigning { From 2e17fa49878d5230d06b126c5469d5c925074ee2 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 8 Feb 2023 15:15:19 +0530 Subject: [PATCH 33/42] MessageSignerMock fixed --- Tests/AuthTests/Stubs/MessageSignerMock.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tests/AuthTests/Stubs/MessageSignerMock.swift b/Tests/AuthTests/Stubs/MessageSignerMock.swift index 1d3cf358d..869febeeb 100644 --- a/Tests/AuthTests/Stubs/MessageSignerMock.swift +++ b/Tests/AuthTests/Stubs/MessageSignerMock.swift @@ -2,6 +2,9 @@ import Foundation import Auth struct MessageSignerMock: CacaoMessageSigner { + func sign(message: String, privateKey: Data, type: WalletConnectUtils.CacaoSignatureType) throws -> WalletConnectUtils.CacaoSignature { + return CacaoSignature(t: .eip191, s: "") + } func verify(signature: CacaoSignature, message: String, From 2ea965ea2137c41d360e0a0db801b51b2b873378 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 9 Feb 2023 04:06:14 +0530 Subject: [PATCH 34/42] Release script --- .env.Showcase | 3 +- .env.WalletApp | 3 +- .github/workflows/ci.yml | 4 +- .github/workflows/release.yml | 46 +++++++++++++++ .gitignore | 4 +- Example/ExampleApp.xcodeproj/project.pbxproj | 59 ++++++++++++++------ Makefile | 8 ++- fastlane/Appfile | 1 - fastlane/Fastfile | 28 ++++++++-- 9 files changed, 126 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.env.Showcase b/.env.Showcase index c08277921..9a34f57e3 100644 --- a/.env.Showcase +++ b/.env.Showcase @@ -1,3 +1,4 @@ SCHEME = "Showcase" APP_IDENTIFIER = "com.walletconnect.chat" -APPLE_ID = "1634760092" \ No newline at end of file +APPLE_ID = "1634760092" +PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.walletconnect.chat" \ No newline at end of file diff --git a/.env.WalletApp b/.env.WalletApp index 5ac0d15e7..d5954a7f6 100644 --- a/.env.WalletApp +++ b/.env.WalletApp @@ -1,3 +1,4 @@ SCHEME = "WalletApp" APP_IDENTIFIER = "com.walletconnect.walletapp" -APPLE_ID = "1667351690" \ No newline at end of file +APPLE_ID = "1667351690" +PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.walletconnect.walletapp" \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1846f591..ffeff03eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,8 +3,8 @@ name: ci on: push: branches: [ main, develop ] - pull_request: - branches: [ main, develop ] + # pull_request: + # branches: [ main, develop ] concurrency: # Support push/pr as event types with different behaviors each: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..f5414d798 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,46 @@ +name: release + +on: + schedule: + # Runs "Every Monday 10am CET" + - cron: '0 10 * * 1' + + workflow_dispatch: + +# TODO: REMOVE + pull_request: + branches: [ develop ] + +jobs: + build: + runs-on: macos-12 + + steps: + - uses: actions/checkout@v2 + + - name: Setup Xcode Version + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: 14.1 + + - uses: actions/cache@v2 + with: + path: | + .build + SourcePackagesCache + DerivedDataCache + key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }} + restore-keys: | + ${{ runner.os }}-spm- + + - name: Release + shell: bash + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + GH_TOKEN: ${{ secrets.GH_TOKEN }} + GH_USER: ${{ secrets.GH_USER }} + APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} + APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} + APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} + run: | + make release_all APPLE_ID=${{ secrets.APPLE_ID }} TOKEN=$(echo -n $GH_USER:$GH_TOKEN | base64) diff --git a/.gitignore b/.gitignore index 64e06f6b1..cdf6e24d3 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ fastlane/Preview.html fastlane/screenshots/**/*.png fastlane/test_output fastlane/README.md +.env # Configuration Configuration.xcconfig @@ -28,4 +29,5 @@ SourcePackagesCache DerivedDataCache # Artifacts -*.ipa \ No newline at end of file +*.ipa +*.zip \ No newline at end of file diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 2982ae6f2..4bef61689 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -2576,6 +2576,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.example.PushDecryptionService; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -2605,6 +2606,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.example.PushDecryptionService; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -2685,9 +2687,12 @@ buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = PNDecryptionService/PNDecryptionService.entitlements; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = W5R8AG9K22; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 7; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5R8AG9K22; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = PNDecryptionService/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = PNDecryptionService; @@ -2699,8 +2704,10 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp.PNDecryptionService; + PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.walletconnect.walletapp"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -2714,9 +2721,11 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = PNDecryptionService/PNDecryptionServiceRelease.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = W5R8AG9K22; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 7; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5R8AG9K22; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = PNDecryptionService/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = PNDecryptionService; @@ -2728,9 +2737,10 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp.PNDecryptionService; + PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.walletconnect.walletapp"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -2744,9 +2754,11 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 7; - DEVELOPMENT_TEAM = W5R8AG9K22; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5R8AG9K22; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Showcase/Other/Info.plist; INFOPLIST_KEY_NSCameraUsageDescription = "Allow the app to scan for QR codes"; @@ -2762,6 +2774,8 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.chat; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.walletconnect.chat"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2774,9 +2788,11 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 7; - DEVELOPMENT_TEAM = W5R8AG9K22; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5R8AG9K22; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Showcase/Other/Info.plist; INFOPLIST_KEY_NSCameraUsageDescription = "Allow the app to scan for QR codes"; @@ -2792,6 +2808,8 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.chat; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.walletconnect.chat"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2881,9 +2899,11 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = WalletApp/WalletApp.entitlements; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 7; - DEVELOPMENT_TEAM = W5R8AG9K22; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5R8AG9K22; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = WalletApp/Other/Info.plist; @@ -2900,6 +2920,8 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.walletconnect.walletapp"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2914,10 +2936,12 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = WalletApp/WalletAppRelease.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = "Apple Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 7; - DEVELOPMENT_TEAM = W5R8AG9K22; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5R8AG9K22; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = WalletApp/Other/Info.plist; @@ -2935,6 +2959,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.walletconnect.walletapp"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/Makefile b/Makefile index 218b88441..806b4f5bf 100755 --- a/Makefile +++ b/Makefile @@ -35,7 +35,11 @@ resolve_packages: fastlane resolve scheme:WalletApp release_wallet: - fastlane release_testflight username:$(APPLE_ID) --env WalletApp + fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) --env WalletApp release_showcase: - fastlane release_testflight username:$(APPLE_ID) --env Showcase \ No newline at end of file + fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) --env Showcase + +release_all: + fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) --env WalletApp + fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) --env Showcase diff --git a/fastlane/Appfile b/fastlane/Appfile index 9fae697da..91ad3f06d 100644 --- a/fastlane/Appfile +++ b/fastlane/Appfile @@ -1,3 +1,2 @@ itc_team_id("123564616") team_id("W5R8AG9K22") -git_url("https://github.com/WalletConnect/match-swift") diff --git a/fastlane/Fastfile b/fastlane/Fastfile index ba33be662..754a0fb64 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -51,12 +51,21 @@ platform :ios do end lane :release_testflight do |options| + setup_ci + api_key = app_store_connect_api_key( + key_id: ENV["APPLE_KEY_ID"], + issuer_id: ENV["APPLE_ISSUER_ID"], + key_content: ENV["APPLE_KEY_CONTENT"], + duration: 1200, + in_house: false, + ) match( readonly: false, type: "appstore", app_identifier: ENV["APP_IDENTIFIER"], git_url: "https://github.com/WalletConnect/match-swift.git", - username: options[:username], + git_basic_authorization: options[:token], + api_key: api_key ) number = latest_testflight_build_number( app_identifier: ENV["APP_IDENTIFIER"], @@ -66,17 +75,26 @@ platform :ios do build_number: number + 1, xcodeproj: "Example/ExampleApp.xcodeproj" ) - build_app( + gym( + configuration: "Release", project: "Example/ExampleApp.xcodeproj", - scheme: ENV["SCHEME"] + scheme: ENV["SCHEME"], + export_method: "app-store", + export_options: { + provisioningProfiles: { + ENV["APP_IDENTIFIER"] => ENV["PROVISIONING_PROFILE_SPECIFIER"] + } + } ) upload_to_testflight( - app_identifier: ENV["APP_IDENTIFIER"], - username: options[:username], apple_id: ENV["APPLE_ID"], + app_identifier: ENV["APP_IDENTIFIER"], skip_waiting_for_build_processing: true, + distribute_external: true, + notify_external_testers: false, ) clean_build_artifacts() end + end \ No newline at end of file From 7f9ba1189b6d992f02d3fb3cb504918804c67969 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 9 Feb 2023 04:19:29 +0530 Subject: [PATCH 35/42] Changelog --- fastlane/Fastfile | 1 + 1 file changed, 1 insertion(+) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 754a0fb64..69cc0127f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -91,6 +91,7 @@ platform :ios do app_identifier: ENV["APP_IDENTIFIER"], skip_waiting_for_build_processing: true, distribute_external: true, + changelog: "#{ENV["SCHEME"]} app weekly build 🚀", notify_external_testers: false, ) clean_build_artifacts() From 3b44682719ed868d908134c75bc8c29623dafbab Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 9 Feb 2023 04:53:44 +0530 Subject: [PATCH 36/42] Profiles for PNDecryptionService --- .env.Showcase | 4 ++-- .env.WalletApp | 4 ++-- Example/ExampleApp.xcodeproj/project.pbxproj | 8 ++++---- fastlane/Fastfile | 7 +------ 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/.env.Showcase b/.env.Showcase index 9a34f57e3..d15a1ba0e 100644 --- a/.env.Showcase +++ b/.env.Showcase @@ -1,4 +1,4 @@ SCHEME = "Showcase" APP_IDENTIFIER = "com.walletconnect.chat" -APPLE_ID = "1634760092" -PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.walletconnect.chat" \ No newline at end of file +MATCH_IDENTIFIERS = "com.walletconnect.chat" +APPLE_ID = "1634760092" \ No newline at end of file diff --git a/.env.WalletApp b/.env.WalletApp index d5954a7f6..18924e39f 100644 --- a/.env.WalletApp +++ b/.env.WalletApp @@ -1,4 +1,4 @@ SCHEME = "WalletApp" APP_IDENTIFIER = "com.walletconnect.walletapp" -APPLE_ID = "1667351690" -PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.walletconnect.walletapp" \ No newline at end of file +MATCH_IDENTIFIERS = "com.walletconnect.chat,com.walletconnect.walletapp.PNDecryptionService" +APPLE_ID = "1667351690" \ No newline at end of file diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 4bef61689..603c2e024 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -2704,10 +2704,10 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp; + PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp.PNDecryptionService; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.walletconnect.walletapp"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.walletconnect.walletapp.PNDecryptionService"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -2737,10 +2737,10 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp; + PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp.PNDecryptionService; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.walletconnect.walletapp"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.walletconnect.walletapp.PNDecryptionService"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 69cc0127f..aac915608 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -62,7 +62,7 @@ platform :ios do match( readonly: false, type: "appstore", - app_identifier: ENV["APP_IDENTIFIER"], + app_identifier: ENV["MATCH_IDENTIFIERS"], git_url: "https://github.com/WalletConnect/match-swift.git", git_basic_authorization: options[:token], api_key: api_key @@ -80,11 +80,6 @@ platform :ios do project: "Example/ExampleApp.xcodeproj", scheme: ENV["SCHEME"], export_method: "app-store", - export_options: { - provisioningProfiles: { - ENV["APP_IDENTIFIER"] => ENV["PROVISIONING_PROFILE_SPECIFIER"] - } - } ) upload_to_testflight( apple_id: ENV["APPLE_ID"], From 50370806b90f90398177029e7f74fdb87e50bc48 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 9 Feb 2023 05:03:27 +0530 Subject: [PATCH 37/42] fix typo --- .env.WalletApp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.WalletApp b/.env.WalletApp index 18924e39f..9396014a6 100644 --- a/.env.WalletApp +++ b/.env.WalletApp @@ -1,4 +1,4 @@ SCHEME = "WalletApp" APP_IDENTIFIER = "com.walletconnect.walletapp" -MATCH_IDENTIFIERS = "com.walletconnect.chat,com.walletconnect.walletapp.PNDecryptionService" +MATCH_IDENTIFIERS = "com.walletconnect.walletapp,com.walletconnect.walletapp.PNDecryptionService" APPLE_ID = "1667351690" \ No newline at end of file From d430580a9f593a849c2a0a0386ebbf41c0e1b32a Mon Sep 17 00:00:00 2001 From: llbartekll Date: Thu, 9 Feb 2023 07:27:31 +0000 Subject: [PATCH 38/42] 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 1663b3678..3227f6058 100644 --- a/Sources/WalletConnectRelay/PackageConfig.json +++ b/Sources/WalletConnectRelay/PackageConfig.json @@ -1 +1 @@ -{"version": "1.3.1"} +{"version": "1.3.2"} From 28e8b9e2b5c0cd992adae54f3ae776d5478c8ba6 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 9 Feb 2023 13:59:37 +0530 Subject: [PATCH 39/42] Finalize PR --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ffeff03eb..e1846f591 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,8 +3,8 @@ name: ci on: push: branches: [ main, develop ] - # pull_request: - # branches: [ main, develop ] + pull_request: + branches: [ main, develop ] concurrency: # Support push/pr as event types with different behaviors each: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f5414d798..5246d94d9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,10 +7,6 @@ on: workflow_dispatch: -# TODO: REMOVE - pull_request: - branches: [ develop ] - jobs: build: runs-on: macos-12 From 51113e235073581ab81885d1cac230225e08f277 Mon Sep 17 00:00:00 2001 From: Alexander Lisovik Date: Fri, 10 Feb 2023 18:31:55 +0100 Subject: [PATCH 40/42] Pass request.id to the RPCRequest --- Sources/WalletConnectSign/Engine/Common/SessionEngine.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift b/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift index 562726920..43d058db1 100644 --- a/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift +++ b/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift @@ -61,7 +61,7 @@ final class SessionEngine { let chainRequest = SessionType.RequestParams.Request(method: request.method, params: request.params, expiry: request.expiry) let sessionRequestParams = SessionType.RequestParams(request: chainRequest, chainId: request.chainId) let protocolMethod = SessionRequestProtocolMethod(ttl: request.calculateTtl()) - let rpcRequest = RPCRequest(method: protocolMethod.method, params: sessionRequestParams) + let rpcRequest = RPCRequest(method: protocolMethod.method, params: sessionRequestParams, rpcid: request.id) try await networkingInteractor.request(rpcRequest, topic: request.topic, protocolMethod: SessionRequestProtocolMethod()) } From 81c03c1c69f9bf9cc8ca1496e34bc0624e266cc3 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 13 Feb 2023 13:50:40 +0530 Subject: [PATCH 41/42] Cert fix + project_id --- .github/workflows/release.yml | 2 +- Makefile | 8 ++++---- fastlane/Fastfile | 4 +++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5246d94d9..c30113723 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,4 +39,4 @@ jobs: APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} run: | - make release_all APPLE_ID=${{ secrets.APPLE_ID }} TOKEN=$(echo -n $GH_USER:$GH_TOKEN | base64) + make release_all APPLE_ID=${{ secrets.APPLE_ID }} TOKEN=$(echo -n $GH_USER:$GH_TOKEN | base64) PROJECT_ID=${{ secrets.RELEASE_PROJECT_ID }} diff --git a/Makefile b/Makefile index 806b4f5bf..fa43c4abf 100755 --- a/Makefile +++ b/Makefile @@ -35,11 +35,11 @@ resolve_packages: fastlane resolve scheme:WalletApp release_wallet: - fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) --env WalletApp + fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) --env WalletApp release_showcase: - fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) --env 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) --env WalletApp - fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) --env Showcase + fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) --env WalletApp + fastlane release_testflight username:$(APPLE_ID) token:$(TOKEN) relay_host:$(RELAY_HOST) project_id:$(PROJECT_ID) --env Showcase diff --git a/fastlane/Fastfile b/fastlane/Fastfile index aac915608..b32acd249 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -65,7 +65,8 @@ platform :ios do app_identifier: ENV["MATCH_IDENTIFIERS"], git_url: "https://github.com/WalletConnect/match-swift.git", git_basic_authorization: options[:token], - api_key: api_key + api_key: api_key, + include_all_certificates: true ) number = latest_testflight_build_number( app_identifier: ENV["APP_IDENTIFIER"], @@ -80,6 +81,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]}'" ) upload_to_testflight( apple_id: ENV["APPLE_ID"], From 6d53da22c6adefac987e5f552a03ba0c43dd339a Mon Sep 17 00:00:00 2001 From: Alexander Lisovik Date: Tue, 14 Feb 2023 20:29:48 +0100 Subject: [PATCH 42/42] Web3Wallet expose disconnect pairing --- Sources/WalletConnectPairing/PairingClientProtocol.swift | 1 + Sources/Web3Wallet/Web3WalletClient.swift | 4 ++++ Tests/Web3WalletTests/Mocks/PairingClientMock.swift | 5 +++++ Tests/Web3WalletTests/Web3WalletTests.swift | 5 +++++ 4 files changed, 15 insertions(+) diff --git a/Sources/WalletConnectPairing/PairingClientProtocol.swift b/Sources/WalletConnectPairing/PairingClientProtocol.swift index 680cb3090..3c4435cc6 100644 --- a/Sources/WalletConnectPairing/PairingClientProtocol.swift +++ b/Sources/WalletConnectPairing/PairingClientProtocol.swift @@ -1,3 +1,4 @@ public protocol PairingClientProtocol { func pair(uri: WalletConnectURI) async throws + func disconnect(topic: String) async throws } diff --git a/Sources/Web3Wallet/Web3WalletClient.swift b/Sources/Web3Wallet/Web3WalletClient.swift index d9397de4e..cde24b697 100644 --- a/Sources/Web3Wallet/Web3WalletClient.swift +++ b/Sources/Web3Wallet/Web3WalletClient.swift @@ -125,6 +125,10 @@ public class Web3WalletClient { public func pair(uri: WalletConnectURI) async throws { try await pairingClient.pair(uri: uri) } + + public func disconnectPairing(topic: String) async throws { + try await pairingClient.disconnect(topic: topic) + } /// For a wallet and a dApp to terminate a session /// diff --git a/Tests/Web3WalletTests/Mocks/PairingClientMock.swift b/Tests/Web3WalletTests/Mocks/PairingClientMock.swift index 6c03d2226..55aed003e 100644 --- a/Tests/Web3WalletTests/Mocks/PairingClientMock.swift +++ b/Tests/Web3WalletTests/Mocks/PairingClientMock.swift @@ -5,8 +5,13 @@ import Combine final class PairingClientMock: PairingClientProtocol { var pairCalled = false + var disconnectPairingCalled = false func pair(uri: WalletConnectUtils.WalletConnectURI) async throws { pairCalled = true } + + func disconnect(topic: String) async throws { + disconnectPairingCalled = true + } } diff --git a/Tests/Web3WalletTests/Web3WalletTests.swift b/Tests/Web3WalletTests/Web3WalletTests.swift index 8962e88a1..76a088e63 100644 --- a/Tests/Web3WalletTests/Web3WalletTests.swift +++ b/Tests/Web3WalletTests/Web3WalletTests.swift @@ -127,6 +127,11 @@ final class Web3WalletTests: XCTestCase { XCTAssertTrue(pairingClient.pairCalled) } + func testDisconnectPairingCalled() async { + try! await web3WalletClient.disconnectPairing(topic: "topic") + XCTAssertTrue(pairingClient.disconnectPairingCalled) + } + func testDisconnectCalled() async { try! await web3WalletClient.disconnect(topic: "") XCTAssertTrue(signClient.disconnectCalled)