From 062753a682256f0f7e29f2f0e84c9c50dd8dc87c Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 24 Nov 2023 09:33:46 +0100 Subject: [PATCH 01/15] savepoint --- Sources/WalletConnectPush/PushClient.swift | 2 +- Sources/WalletConnectPush/PushClientProtocol.swift | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectPush/PushClient.swift b/Sources/WalletConnectPush/PushClient.swift index 30f87f9f3..c385726da 100644 --- a/Sources/WalletConnectPush/PushClient.swift +++ b/Sources/WalletConnectPush/PushClient.swift @@ -14,7 +14,7 @@ public class PushClient: PushClientProtocol { self.logger = logger } - public func register(deviceToken: Data) async throws { + public func register(deviceToken: Data, enableEncrypted: Bool = false) async throws { try await registerService.register(deviceToken: deviceToken) } diff --git a/Sources/WalletConnectPush/PushClientProtocol.swift b/Sources/WalletConnectPush/PushClientProtocol.swift index 35eb8f3fa..d07b0ada0 100644 --- a/Sources/WalletConnectPush/PushClientProtocol.swift +++ b/Sources/WalletConnectPush/PushClientProtocol.swift @@ -1,8 +1,14 @@ import Foundation public protocol PushClientProtocol { - func register(deviceToken: Data) async throws + func register(deviceToken: Data, enableEncrypted: Bool) async throws #if DEBUG func register(deviceToken: String) async throws #endif } + +extension PushClientProtocol { + func register(deviceToken: Data, enableEncrypted: Bool = false) async throws { + try await register(deviceToken: deviceToken, enableEncrypted: enableEncrypted) + } +} From 2ddd01db6f7d12044c4a8566a7378dded9d00075 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 24 Nov 2023 09:34:16 +0100 Subject: [PATCH 02/15] update --- Sources/WalletConnectPush/PushClientProtocol.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectPush/PushClientProtocol.swift b/Sources/WalletConnectPush/PushClientProtocol.swift index d07b0ada0..93c9a5fe6 100644 --- a/Sources/WalletConnectPush/PushClientProtocol.swift +++ b/Sources/WalletConnectPush/PushClientProtocol.swift @@ -7,7 +7,7 @@ public protocol PushClientProtocol { #endif } -extension PushClientProtocol { +public extension PushClientProtocol { func register(deviceToken: Data, enableEncrypted: Bool = false) async throws { try await register(deviceToken: deviceToken, enableEncrypted: enableEncrypted) } From a1e6e5971da4a0ad47d1055334b66da622ec3a0b Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 24 Nov 2023 14:25:57 +0100 Subject: [PATCH 03/15] update push client's register method, wip NotificationService --- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../NotificationService.swift | 61 ++++++++++++------- Sources/WalletConnectPush/PushClient.swift | 4 +- .../Register/PushRegisterService.swift | 12 ++-- .../Register/PushService.swift | 28 ++++++--- Sources/Web3Wallet/Web3WalletClient.swift | 4 +- 6 files changed, 69 insertions(+), 44 deletions(-) diff --git a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 229e0f8ef..dceba93f5 100644 --- a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -168,8 +168,8 @@ "repositoryURL": "https://github.com/WalletConnect/web3modal-swift", "state": { "branch": null, - "revision": "e68c1b1560264965ca13608db44294d301c6404f", - "version": "1.0.9" + "revision": "831410cfd6e68afa7212a5547483fb2d180f0fa7", + "version": "1.0.10" } } ] diff --git a/Example/PNDecryptionService/NotificationService.swift b/Example/PNDecryptionService/NotificationService.swift index 708444594..eac699664 100644 --- a/Example/PNDecryptionService/NotificationService.swift +++ b/Example/PNDecryptionService/NotificationService.swift @@ -7,6 +7,8 @@ class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNNotificationContent? + private let notifyTags: [UInt] = [1] + private let w3wTags: [UInt] = [1] override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler @@ -16,41 +18,52 @@ class NotificationService: UNNotificationServiceExtension { if let content = bestAttemptContent, let topic = content.userInfo["topic"] as? String, - let ciphertext = content.userInfo["blob"] as? String { - - log("topic and blob found") + let ciphertext = content.userInfo["message"] as? String, + let tag = content.userInfo["tag"] as? UInt { + + if notifyTags.contains(tag) { + Task { + let mutableContent = await handleNotifyMessage(content: content, topic: topic, tag: tag, ciphertext: ciphertext) + contentHandler(mutableContent) + } + } else if w3wTags.contains(tag) { + // Handle other tags + } else { + // Handle default case + } + } + } - do { - let service = NotifyDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") - let (pushMessage, account) = try service.decryptMessage(topic: topic, ciphertext: ciphertext) - log("message decrypted", account: account, topic: topic, message: pushMessage) + private func handleNotifyMessage(content: UNNotificationContent, topic: String, tag: UInt, ciphertext: String) async -> UNMutableNotificationContent { + do { + let service = NotifyDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") + let (pushMessage, account) = try service.decryptMessage(topic: topic, ciphertext: ciphertext) - let updatedContent = handle(content: content, pushMessage: pushMessage, topic: topic) + log("message decrypted", account: account, topic: topic, message: pushMessage) - let mutableContent = updatedContent.mutableCopy() as! UNMutableNotificationContent - mutableContent.title = pushMessage.title - mutableContent.subtitle = pushMessage.url - mutableContent.body = pushMessage.body + let updatedContent = handle(content: content, pushMessage: pushMessage, topic: topic) - log("message handled", account: account, topic: topic, message: pushMessage) + let mutableContent = updatedContent.mutableCopy() as! UNMutableNotificationContent + mutableContent.title = pushMessage.title + mutableContent.subtitle = pushMessage.url + mutableContent.body = pushMessage.body - contentHandler(mutableContent) + log("message handled", account: account, topic: topic, message: pushMessage) - log("content handled", account: account, topic: topic, message: pushMessage) - } - catch { - log("error: \(error.localizedDescription)") + return mutableContent + } catch { + log("error: \(error.localizedDescription)") - let mutableContent = content.mutableCopy() as! UNMutableNotificationContent - mutableContent.title = "Error" - mutableContent.body = error.localizedDescription + let mutableContent = content.mutableCopy() as! UNMutableNotificationContent + mutableContent.title = "Error" + mutableContent.body = error.localizedDescription - contentHandler(mutableContent) - } + return mutableContent } } + override func serviceExtensionTimeWillExpire() { // Called just before the extension will be terminated by the system. // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. @@ -58,6 +71,8 @@ class NotificationService: UNNotificationServiceExtension { contentHandler(bestAttemptContent) } } + + } private extension NotificationService { diff --git a/Sources/WalletConnectPush/PushClient.swift b/Sources/WalletConnectPush/PushClient.swift index c385726da..2c378b3e6 100644 --- a/Sources/WalletConnectPush/PushClient.swift +++ b/Sources/WalletConnectPush/PushClient.swift @@ -15,12 +15,12 @@ public class PushClient: PushClientProtocol { } public func register(deviceToken: Data, enableEncrypted: Bool = false) async throws { - try await registerService.register(deviceToken: deviceToken) + try await registerService.register(deviceToken: deviceToken, alwaysRaw: enableEncrypted) } #if DEBUG public func register(deviceToken: String) async throws { - try await registerService.register(deviceToken: deviceToken) + try await registerService.register(deviceToken: deviceToken, alwaysRaw: true) } #endif } diff --git a/Sources/WalletConnectPush/Register/PushRegisterService.swift b/Sources/WalletConnectPush/Register/PushRegisterService.swift index 3c06ce281..193c173c7 100644 --- a/Sources/WalletConnectPush/Register/PushRegisterService.swift +++ b/Sources/WalletConnectPush/Register/PushRegisterService.swift @@ -29,7 +29,7 @@ actor PushRegisterService { self.environment = environment } - func register(deviceToken: Data) async throws { + func register(deviceToken: Data, alwaysRaw: Bool) async throws { let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) } let token = tokenParts.joined() let pushAuthToken = try pushAuthenticator.createAuthToken() @@ -40,7 +40,7 @@ actor PushRegisterService { do { let response = try await httpClient.request( PushResponse.self, - at: PushAPI.register(clientId: clientIdMutlibase, token: token, projectId: projectId, environment: environment, auth: pushAuthToken) + at: PushAPI.register(clientId: clientIdMutlibase, token: token, projectId: projectId, environment: environment, auth: pushAuthToken, alwaysRaw: alwaysRaw) ) guard response.status == .success else { throw Errors.registrationFailed @@ -51,7 +51,7 @@ actor PushRegisterService { logger.debug("Trying fallback") fallback = true await echoHostFallback() - try await register(deviceToken: deviceToken) + try await register(deviceToken: deviceToken, alwaysRaw: alwaysRaw) } logger.debug("Push Server registration error: \(error.localizedDescription)") throw error @@ -63,7 +63,7 @@ actor PushRegisterService { } #if DEBUG - public func register(deviceToken: String) async throws { + public func register(deviceToken: String, alwaysRaw: Bool) async throws { let pushAuthToken = try pushAuthenticator.createAuthToken() let clientId = try clientIdStorage.getClientId() let clientIdMutlibase = try DIDKey(did: clientId).multibase(variant: .ED25519) @@ -71,7 +71,7 @@ actor PushRegisterService { do { let response = try await httpClient.request( PushResponse.self, - at: PushAPI.register(clientId: clientIdMutlibase, token: deviceToken, projectId: projectId, environment: environment, auth: pushAuthToken) + at: PushAPI.register(clientId: clientIdMutlibase, token: deviceToken, projectId: projectId, environment: environment, auth: pushAuthToken, alwaysRaw: alwaysRaw) ) guard response.status == .success else { throw Errors.registrationFailed @@ -81,7 +81,7 @@ actor PushRegisterService { if (error as? HTTPError) == .couldNotConnect && !fallback { fallback = true await echoHostFallback() - try await register(deviceToken: deviceToken) + try await register(deviceToken: deviceToken, alwaysRaw: alwaysRaw) } throw error } diff --git a/Sources/WalletConnectPush/Register/PushService.swift b/Sources/WalletConnectPush/Register/PushService.swift index d6ddbc6f3..43062e6c4 100644 --- a/Sources/WalletConnectPush/Register/PushService.swift +++ b/Sources/WalletConnectPush/Register/PushService.swift @@ -1,12 +1,12 @@ import Foundation enum PushAPI: HTTPService { - case register(clientId: String, token: String, projectId: String, environment: APNSEnvironment, auth: String) + case register(clientId: String, token: String, projectId: String, environment: APNSEnvironment, auth: String, alwaysRaw: Bool) case unregister(clientId: String, projectId: String, auth: 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)" @@ -24,12 +24,9 @@ enum PushAPI: HTTPService { var body: Data? { switch self { - case .register(let clientId, let token, _, let environment, _): - return try? JSONEncoder().encode([ - "client_id": clientId, - "type": environment.rawValue, - "token": token - ]) + case .register(let clientId, let token, _, let environment, _, let alwaysRaw): + let request = RegisterRequest(clientId: clientId, type: environment.rawValue, token: token, alwaysRaw: alwaysRaw) + return try? JSONEncoder().encode(request) case .unregister: return nil } @@ -45,7 +42,7 @@ enum PushAPI: HTTPService { var additionalHeaderFields: [String : String]? { switch self { - case .register(_, _, _, _, let auth): + case .register(_, _, _, _, let auth, _): return ["Authorization": auth] case .unregister(_, _, let auth): return ["Authorization": auth] @@ -54,3 +51,16 @@ enum PushAPI: HTTPService { } +struct RegisterRequest: Codable { + let clientId: String + let type: String + let token: String + let alwaysRaw: Bool + + enum CodingKeys: String, CodingKey { + case clientId = "client_id" + case type + case token + case alwaysRaw = "always_raw" + } +} diff --git a/Sources/Web3Wallet/Web3WalletClient.swift b/Sources/Web3Wallet/Web3WalletClient.swift index a90093a10..1602e2138 100644 --- a/Sources/Web3Wallet/Web3WalletClient.swift +++ b/Sources/Web3Wallet/Web3WalletClient.swift @@ -212,8 +212,8 @@ public class Web3WalletClient { try authClient.getPendingRequests() } - public func registerPushClient(deviceToken: Data) async throws { - try await pushClient.register(deviceToken: deviceToken) + public func registerPushClient(deviceToken: Data, enableEncrypted: Bool = false) async throws { + try await pushClient.register(deviceToken: deviceToken, enableEncrypted: enableEncrypted) } /// Delete all stored data such as: pairings, sessions, keys From 5553219a350d3d5dc53d1e3ec68cc83e769f0ac3 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 27 Nov 2023 10:07:39 +0100 Subject: [PATCH 04/15] add sign decryption service --- .../NotificationService.swift | 25 +++++++++++++---- .../SignDecryptionService.swift | 28 +++++++++++++++++++ .../Web3WalletDecryptionService.swift | 18 ++++++++++++ 3 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 Sources/WalletConnectSign/SignDecryptionService.swift create mode 100644 Sources/Web3Wallet/Web3WalletDecryptionService.swift diff --git a/Example/PNDecryptionService/NotificationService.swift b/Example/PNDecryptionService/NotificationService.swift index eac699664..290e8f934 100644 --- a/Example/PNDecryptionService/NotificationService.swift +++ b/Example/PNDecryptionService/NotificationService.swift @@ -1,4 +1,5 @@ import UserNotifications +import Web3Wallet import WalletConnectNotify import Intents import Mixpanel @@ -7,8 +8,8 @@ class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNNotificationContent? - private let notifyTags: [UInt] = [1] - private let w3wTags: [UInt] = [1] + private let notifyTags: [UInt] = [4002] + private let w3wTags: [UInt] = [1100, 1108, 3000] override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler @@ -23,19 +24,33 @@ class NotificationService: UNNotificationServiceExtension { if notifyTags.contains(tag) { Task { - let mutableContent = await handleNotifyMessage(content: content, topic: topic, tag: tag, ciphertext: ciphertext) + let mutableContent = await handleNotifyNotification(content: content, topic: topic, ciphertext: ciphertext) contentHandler(mutableContent) } } else if w3wTags.contains(tag) { - // Handle other tags + Task { + let mutableContent = await handleWeb3WalletNotification(content: content, topic: topic, tag: tag, ciphertext: ciphertext) + } } else { // Handle default case } } } + private func handleWeb3WalletNotification(content: UNNotificationContent, topic: String, tag: UInt, ciphertext: String) async -> UNMutableNotificationContent { + + + let web3WalletDecryptionService = Web3WalletDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") + + let rpcRequest = web3WalletDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) + + let metadata = web3WalletDecryptionService.getMetadata(topic: topic) + + + } + - private func handleNotifyMessage(content: UNNotificationContent, topic: String, tag: UInt, ciphertext: String) async -> UNMutableNotificationContent { + private func handleNotifyNotification(content: UNNotificationContent, topic: String, ciphertext: String) async -> UNMutableNotificationContent { do { let service = NotifyDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") let (pushMessage, account) = try service.decryptMessage(topic: topic, ciphertext: ciphertext) diff --git a/Sources/WalletConnectSign/SignDecryptionService.swift b/Sources/WalletConnectSign/SignDecryptionService.swift new file mode 100644 index 000000000..5b80c49e6 --- /dev/null +++ b/Sources/WalletConnectSign/SignDecryptionService.swift @@ -0,0 +1,28 @@ +import Foundation + +public class SignDecryptionService { + enum Errors: Error { + case couldNotInitialiseDefaults + } + private let serializer: Serializing + private let sessionStorage: WCSessionStorage + + public init(groupIdentifier: String) throws { + let keychainStorage = GroupKeychainStorage(serviceIdentifier: groupIdentifier) + let kms = KeyManagementService(keychain: keychainStorage) + self.serializer = Serializer(kms: kms, logger: ConsoleLogger(prefix: "🔐", loggingLevel: .off)) + guard let defaults = UserDefaults(suiteName: groupIdentifier) else { + throw Errors.couldNotInitialiseDefaults + } + sessionStorage = SessionStorage(storage: SequenceStore(store: .init(defaults: defaults, identifier: SignStorageIdentifiers.sessions.rawValue))) + } + + public func decryptMessage(topic: String, ciphertext: String) throws -> RPCRequest { + let (rpcRequest, _, _): (RPCRequest, String?, Data) = try serializer.deserialize(topic: topic, encodedEnvelope: ciphertext) + return rpcRequest + } + + public func getMetadata(topic: String) -> AppMetadata? { + sessionStorage.getSession(forTopic: topic)?.peerParticipant.metadata + } +} diff --git a/Sources/Web3Wallet/Web3WalletDecryptionService.swift b/Sources/Web3Wallet/Web3WalletDecryptionService.swift new file mode 100644 index 000000000..3defff2d6 --- /dev/null +++ b/Sources/Web3Wallet/Web3WalletDecryptionService.swift @@ -0,0 +1,18 @@ +import Foundation + +public class Web3WalletDecryptionService { + + private let signDecryptionService: SignDecryptionService + + public init(groupIdentifier: String) throws { + self.signDecryptionService = try SignDecryptionService(groupIdentifier: groupIdentifier) + } + + public func decryptMessage(topic: String, ciphertext: String) throws -> RPCRequest { + return try signDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) + } + + public func getMetadata(topic: String) -> AppMetadata? { + signDecryptionService.getMetadata(topic: topic) + } +} From 7d0b797cd260f4dc8b734d811fc163bf2e7c7be5 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 27 Nov 2023 10:14:25 +0100 Subject: [PATCH 05/15] savepoint --- .../PNDecryptionService/NotificationService.swift | 15 +++++---------- .../Web3Wallet/Web3WalletDecryptionService.swift | 2 +- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Example/PNDecryptionService/NotificationService.swift b/Example/PNDecryptionService/NotificationService.swift index 290e8f934..49661f83c 100644 --- a/Example/PNDecryptionService/NotificationService.swift +++ b/Example/PNDecryptionService/NotificationService.swift @@ -23,21 +23,17 @@ class NotificationService: UNNotificationServiceExtension { let tag = content.userInfo["tag"] as? UInt { if notifyTags.contains(tag) { - Task { - let mutableContent = await handleNotifyNotification(content: content, topic: topic, ciphertext: ciphertext) - contentHandler(mutableContent) - } + let mutableContent = handleNotifyNotification(content: content, topic: topic, ciphertext: ciphertext) + contentHandler(mutableContent) } else if w3wTags.contains(tag) { - Task { - let mutableContent = await handleWeb3WalletNotification(content: content, topic: topic, tag: tag, ciphertext: ciphertext) - } + let mutableContent = handleWeb3WalletNotification(content: content, topic: topic, tag: tag, ciphertext: ciphertext) } else { // Handle default case } } } - private func handleWeb3WalletNotification(content: UNNotificationContent, topic: String, tag: UInt, ciphertext: String) async -> UNMutableNotificationContent { + private func handleWeb3WalletNotification(content: UNNotificationContent, topic: String, tag: UInt, ciphertext: String) -> UNMutableNotificationContent { let web3WalletDecryptionService = Web3WalletDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") @@ -46,11 +42,10 @@ class NotificationService: UNNotificationServiceExtension { let metadata = web3WalletDecryptionService.getMetadata(topic: topic) - } - private func handleNotifyNotification(content: UNNotificationContent, topic: String, ciphertext: String) async -> UNMutableNotificationContent { + private func handleNotifyNotification(content: UNNotificationContent, topic: String, ciphertext: String) -> UNMutableNotificationContent { do { let service = NotifyDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") let (pushMessage, account) = try service.decryptMessage(topic: topic, ciphertext: ciphertext) diff --git a/Sources/Web3Wallet/Web3WalletDecryptionService.swift b/Sources/Web3Wallet/Web3WalletDecryptionService.swift index 3defff2d6..2a3dd91fd 100644 --- a/Sources/Web3Wallet/Web3WalletDecryptionService.swift +++ b/Sources/Web3Wallet/Web3WalletDecryptionService.swift @@ -1,6 +1,6 @@ import Foundation -public class Web3WalletDecryptionService { +public final class Web3WalletDecryptionService { private let signDecryptionService: SignDecryptionService From 8d7a6aadcd9ebfeb415f385bb97053da7112bee4 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 27 Nov 2023 14:19:35 +0100 Subject: [PATCH 06/15] savepoint --- Example/ExampleApp.xcodeproj/project.pbxproj | 7 ++++++ .../xcshareddata/xcschemes/WalletApp.xcscheme | 14 ++++++++++++ .../NotificationService.swift | 22 ++++++++++++++++--- .../ApplicationLayer/AppDelegate.swift | 2 +- .../Client/Wallet/NotifyClient.swift | 4 ++-- .../WalletConnectPush/PushClientFactory.swift | 4 ++-- 6 files changed, 45 insertions(+), 8 deletions(-) diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 4f5a2101c..ea9581c83 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 84474A0129B9EB74005F520B /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = 84474A0029B9EB74005F520B /* Starscream */; }; 84474A0229B9ECA2005F520B /* DefaultSocketFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AEF2877F73000094373 /* DefaultSocketFactory.swift */; }; 8448F1D427E4726F0000B866 /* WalletConnect in Frameworks */ = {isa = PBXBuildFile; productRef = 8448F1D327E4726F0000B866 /* WalletConnect */; }; + 844AD55F2B1497270062E123 /* Web3Wallet in Frameworks */ = {isa = PBXBuildFile; productRef = 844AD55E2B1497270062E123 /* Web3Wallet */; }; 845B8D8C2934B36C0084A966 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845B8D8B2934B36C0084A966 /* Account.swift */; }; 847BD1D62989492500076C90 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D12989492500076C90 /* MainViewController.swift */; }; 847BD1D82989492500076C90 /* MainModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D32989492500076C90 /* MainModule.swift */; }; @@ -732,6 +733,7 @@ buildActionMask = 2147483647; files = ( A5A650CA2B062A1400F9AD4B /* Mixpanel in Frameworks */, + 844AD55F2B1497270062E123 /* Web3Wallet in Frameworks */, A5B6C0F72A6EAB3200927332 /* WalletConnectNotify in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2032,6 +2034,7 @@ packageProductDependencies = ( A5B6C0F62A6EAB3200927332 /* WalletConnectNotify */, A5A650C92B062A1400F9AD4B /* Mixpanel */, + 844AD55E2B1497270062E123 /* Web3Wallet */, ); productName = PNDecryptionService; productReference = 84E6B84729787A8000428BAF /* PNDecryptionService.appex */; @@ -3412,6 +3415,10 @@ isa = XCSwiftPackageProductDependency; productName = WalletConnect; }; + 844AD55E2B1497270062E123 /* Web3Wallet */ = { + isa = XCSwiftPackageProductDependency; + productName = Web3Wallet; + }; 8487A9432A836C2A0003D5AF /* Sentry */ = { isa = XCSwiftPackageProductDependency; package = 8487A9422A836C2A0003D5AF /* XCRemoteSwiftPackageReference "sentry-cocoa" */; diff --git a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletApp.xcscheme b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletApp.xcscheme index 036e15875..6d01f5811 100644 --- a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletApp.xcscheme +++ b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/WalletApp.xcscheme @@ -20,6 +20,20 @@ ReferencedContainer = "container:ExampleApp.xcodeproj"> + + + + UNMutableNotificationContent { + do { + let web3WalletDecryptionService = try Web3WalletDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") + +// let rpcRequest = try web3WalletDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) + + let metadata = web3WalletDecryptionService.getMetadata(topic: topic) + + let mutableContent = content.mutableCopy() as! UNMutableNotificationContent - let web3WalletDecryptionService = Web3WalletDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") + mutableContent.title = "rpcRequest.method" - let rpcRequest = web3WalletDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) + mutableContent.subtitle = metadata?.url ?? "" - let metadata = web3WalletDecryptionService.getMetadata(topic: topic) + return mutableContent + } catch { + let mutableContent = content.mutableCopy() as! UNMutableNotificationContent + mutableContent.title = "Error" + mutableContent.body = error.localizedDescription + return mutableContent + } } diff --git a/Example/WalletApp/ApplicationLayer/AppDelegate.swift b/Example/WalletApp/ApplicationLayer/AppDelegate.swift index 1bef78e52..f2f961b36 100644 --- a/Example/WalletApp/ApplicationLayer/AppDelegate.swift +++ b/Example/WalletApp/ApplicationLayer/AppDelegate.swift @@ -29,7 +29,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { UserDefaults.standard.set(deviceTokenString.joined(), forKey: "deviceToken") Task(priority: .high) { - try await Notify.instance.register(deviceToken: deviceToken) + try await Notify.instance.register(deviceToken: deviceToken, enableEncrypted: true) } } diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 41db7b97e..6a3ea77e5 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -117,8 +117,8 @@ public class NotifyClient { try? notifyStorage.deleteMessage(id: id) } - public func register(deviceToken: Data) async throws { - try await pushClient.register(deviceToken: deviceToken) + public func register(deviceToken: Data, enableEncrypted: Bool = false) async throws { + try await pushClient.register(deviceToken: deviceToken, enableEncrypted: enableEncrypted) } public func isIdentityRegistered(account: Account) -> Bool { diff --git a/Sources/WalletConnectPush/PushClientFactory.swift b/Sources/WalletConnectPush/PushClientFactory.swift index 60a3a9ad6..50a8a7809 100644 --- a/Sources/WalletConnectPush/PushClientFactory.swift +++ b/Sources/WalletConnectPush/PushClientFactory.swift @@ -27,8 +27,8 @@ public struct PushClientFactory { environment: APNSEnvironment ) -> PushClient { let sessionConfiguration = URLSessionConfiguration.default - sessionConfiguration.timeoutIntervalForRequest = 5.0 - sessionConfiguration.timeoutIntervalForResource = 5.0 + sessionConfiguration.timeoutIntervalForRequest = 10.0 + sessionConfiguration.timeoutIntervalForResource = 10.0 let session = URLSession(configuration: sessionConfiguration) let logger = ConsoleLogger(prefix: "👂🏻", loggingLevel: .off) From 79ec49ecd44b4345bc250b8242c926ff7bd3d6fd Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 28 Nov 2023 08:03:41 +0100 Subject: [PATCH 07/15] update decryption services --- .../NotificationService.swift | 27 +++++++------ Sources/Auth/AuthDecryptionService.swift | 40 +++++++++++++++++++ .../Wallet/NotifyDecryptionService.swift | 5 +++ .../PairStorageIdentifiers.swift | 2 +- .../Web3WalletDecryptionService.swift | 30 ++++++++++++-- 5 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 Sources/Auth/AuthDecryptionService.swift diff --git a/Example/PNDecryptionService/NotificationService.swift b/Example/PNDecryptionService/NotificationService.swift index 10b89a134..c97a95df2 100644 --- a/Example/PNDecryptionService/NotificationService.swift +++ b/Example/PNDecryptionService/NotificationService.swift @@ -8,34 +8,32 @@ class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNNotificationContent? - private let notifyTags: [UInt] = [4002] - private let w3wTags: [UInt] = [1100, 1108, 3000] override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler self.bestAttemptContent = request.content log("didReceive(_:) fired") - if let content = bestAttemptContent, let topic = content.userInfo["topic"] as? String, let ciphertext = content.userInfo["message"] as? String, let tag = content.userInfo["tag"] as? UInt { - if notifyTags.contains(tag) { - let mutableContent = handleNotifyNotification(content: content, topic: topic, ciphertext: ciphertext) + if let w3wRequestMethod = Web3WalletDecryptionService.getRequestMethod(tag: tag) { + let mutableContent = handleWeb3WalletNotification(content: content, topic: topic, requestMethod: w3wRequestMethod, ciphertext: ciphertext) contentHandler(mutableContent) - } else if w3wTags.contains(tag) { - let mutableContent = handleWeb3WalletNotification(content: content, topic: topic, tag: tag, ciphertext: ciphertext) + } else if NotifyDecryptionService.canHandle(tag: tag) { + let mutableContent = handleNotifyNotification(content: content, topic: topic, ciphertext: ciphertext) contentHandler(mutableContent) } else { - // Handle default case + let mutableContent = content.mutableCopy() as! UNMutableNotificationContent + mutableContent.title = "Error: unknown message tag" } } } - private func handleWeb3WalletNotification(content: UNNotificationContent, topic: String, tag: UInt, ciphertext: String) -> UNMutableNotificationContent { + private func handleWeb3WalletNotification(content: UNNotificationContent, topic: String, requestMethod: Web3WalletDecryptionService.RequestMethod, ciphertext: String) -> UNMutableNotificationContent { do { let web3WalletDecryptionService = try Web3WalletDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") @@ -46,9 +44,14 @@ class NotificationService: UNNotificationServiceExtension { let mutableContent = content.mutableCopy() as! UNMutableNotificationContent - mutableContent.title = "rpcRequest.method" - - mutableContent.subtitle = metadata?.url ?? "" + switch requestMethod { + case .sessionProposal: + mutableContent.title = "session proposal" + case .sessionRequest: + mutableContent.title = "session request" + case .authRequest: + mutableContent.title = "auth request" + } return mutableContent } catch { diff --git a/Sources/Auth/AuthDecryptionService.swift b/Sources/Auth/AuthDecryptionService.swift new file mode 100644 index 000000000..8ba0c8e2e --- /dev/null +++ b/Sources/Auth/AuthDecryptionService.swift @@ -0,0 +1,40 @@ +import Foundation + +public class AuthDecryptionService { + enum Errors: Error { + case couldNotInitialiseDefaults + } + private let serializer: Serializing + private let pairingStorage: PairingStorage + + public init(groupIdentifier: String) throws { + let keychainStorage = GroupKeychainStorage(serviceIdentifier: groupIdentifier) + let kms = KeyManagementService(keychain: keychainStorage) + self.serializer = Serializer(kms: kms, logger: ConsoleLogger(prefix: "🔐", loggingLevel: .off)) + guard let defaults = UserDefaults(suiteName: groupIdentifier) else { + throw Errors.couldNotInitialiseDefaults + } + pairingStorage = PairingStorage(storage: SequenceStore(store: .init(defaults: defaults, identifier: PairStorageIdentifiers.pairings.rawValue))) + } + + public func decryptMessage(topic: String, ciphertext: String) throws -> RPCRequest { + let (rpcRequest, _, _): (RPCRequest, String?, Data) = try serializer.deserialize(topic: topic, encodedEnvelope: ciphertext) + setPairingMetadata(rpcRequest: rpcRequest, topic: topic) + return rpcRequest + } + + public func getMetadata(topic: String) -> AppMetadata? { + pairingStorage.getPairing(forTopic: topic)?.peerMetadata + } + + private func setPairingMetadata(rpcRequest: RPCRequest, topic: String) { + guard var pairing = pairingStorage.getPairing(forTopic: topic), + pairing.peerMetadata == nil, + let peerMetadata = try? rpcRequest.params?.get(AuthRequestParams.self).requester.metadata + else { return } + + pairing.updatePeerMetadata(peerMetadata) + pairingStorage.setPairing(pairing) + } +} + diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyDecryptionService.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyDecryptionService.swift index 296e515e9..272a37cea 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyDecryptionService.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyDecryptionService.swift @@ -5,6 +5,7 @@ public class NotifyDecryptionService { case malformedNotifyMessage } private let serializer: Serializing + private static let notifyTags: [UInt] = [4002] init(serializer: Serializing) { self.serializer = serializer @@ -16,6 +17,10 @@ public class NotifyDecryptionService { self.serializer = Serializer(kms: kms, logger: ConsoleLogger(prefix: "🔐", loggingLevel: .off)) } + public static func canHandle(tag: UInt) -> Bool { + return notifyTags.contains(tag) + } + public func decryptMessage(topic: String, ciphertext: String) throws -> (NotifyMessage, Account) { let (rpcRequest, _, _): (RPCRequest, String?, Data) = try serializer.deserialize(topic: topic, encodedEnvelope: ciphertext) guard let params = rpcRequest.params else { throw Errors.malformedNotifyMessage } diff --git a/Sources/WalletConnectPairing/PairStorageIdentifiers.swift b/Sources/WalletConnectPairing/PairStorageIdentifiers.swift index f287e1aad..0728ec2c5 100644 --- a/Sources/WalletConnectPairing/PairStorageIdentifiers.swift +++ b/Sources/WalletConnectPairing/PairStorageIdentifiers.swift @@ -1,5 +1,5 @@ import Foundation -enum PairStorageIdentifiers: String { +public enum PairStorageIdentifiers: String { case pairings = "com.walletconnect.sdk.pairingSequences" } diff --git a/Sources/Web3Wallet/Web3WalletDecryptionService.swift b/Sources/Web3Wallet/Web3WalletDecryptionService.swift index 2a3dd91fd..724b3f8a8 100644 --- a/Sources/Web3Wallet/Web3WalletDecryptionService.swift +++ b/Sources/Web3Wallet/Web3WalletDecryptionService.swift @@ -1,18 +1,42 @@ import Foundation public final class Web3WalletDecryptionService { + enum Errors: Error { + case unknownTag + } + public enum RequestMethod: UInt { + case sessionRequest = 1108 + case sessionProposal = 1100 + case authRequest = 3000 + } private let signDecryptionService: SignDecryptionService + private let authDecryptionService: AuthDecryptionService public init(groupIdentifier: String) throws { + self.authDecryptionService = try AuthDecryptionService(groupIdentifier: groupIdentifier) self.signDecryptionService = try SignDecryptionService(groupIdentifier: groupIdentifier) } - public func decryptMessage(topic: String, ciphertext: String) throws -> RPCRequest { - return try signDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) + public static func getRequestMethod(tag: UInt) -> RequestMethod? { + return RequestMethod(rawValue: tag) + } + + public func decryptMessage(topic: String, ciphertext: String, tag: UInt) throws -> RPCRequest { + guard let requestMethod = Self.getRequestMethod(tag: tag) else { throw Errors.unknownTag } + switch requestMethod { + case .sessionProposal, .sessionRequest: + return try signDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) + case .authRequest: + return try authDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) + } } public func getMetadata(topic: String) -> AppMetadata? { - signDecryptionService.getMetadata(topic: topic) + if let metadata = signDecryptionService.getMetadata(topic: topic) { + return metadata + } else { + return authDecryptionService.getMetadata(topic: topic) + } } } From 546aacaf9f684a7b1076d19e89c59796bf79836a Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 29 Nov 2023 08:13:37 +0100 Subject: [PATCH 08/15] remove unused scheme --- .../xcshareddata/swiftpm/Package.resolved | 4 +- ....xcscheme => PNDecryptionService.xcscheme} | 64 ++++++------------- .../NotificationService.swift | 12 ++-- 3 files changed, 28 insertions(+), 52 deletions(-) rename Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/{PushDecryptionService.xcscheme => PNDecryptionService.xcscheme} (57%) diff --git a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index dceba93f5..229e0f8ef 100644 --- a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -168,8 +168,8 @@ "repositoryURL": "https://github.com/WalletConnect/web3modal-swift", "state": { "branch": null, - "revision": "831410cfd6e68afa7212a5547483fb2d180f0fa7", - "version": "1.0.10" + "revision": "e68c1b1560264965ca13608db44294d301c6404f", + "version": "1.0.9" } } ] diff --git a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/PushDecryptionService.xcscheme b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/PNDecryptionService.xcscheme similarity index 57% rename from Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/PushDecryptionService.xcscheme rename to Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/PNDecryptionService.xcscheme index 07e071581..026a57bb3 100644 --- a/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/PushDecryptionService.xcscheme +++ b/Example/ExampleApp.xcodeproj/xcshareddata/xcschemes/PNDecryptionService.xcscheme @@ -1,8 +1,8 @@ + version = "2.0"> @@ -15,9 +15,9 @@ buildForAnalyzing = "YES"> @@ -29,9 +29,9 @@ buildForAnalyzing = "YES"> @@ -41,31 +41,21 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES"> - - - - - - + shouldUseLaunchSchemeArgsEnv = "YES" + shouldAutocreateTestPlan = "YES"> + allowLocationSimulation = "YES" + launchAutomaticallySubstyle = "2"> - - - - - - - - diff --git a/Example/PNDecryptionService/NotificationService.swift b/Example/PNDecryptionService/NotificationService.swift index c97a95df2..250d19ca7 100644 --- a/Example/PNDecryptionService/NotificationService.swift +++ b/Example/PNDecryptionService/NotificationService.swift @@ -40,17 +40,21 @@ class NotificationService: UNNotificationServiceExtension { // let rpcRequest = try web3WalletDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) - let metadata = web3WalletDecryptionService.getMetadata(topic: topic) let mutableContent = content.mutableCopy() as! UNMutableNotificationContent + guard let metadata = web3WalletDecryptionService.getMetadata(topic: topic) else { + mutableContent.title = "Error: Cannot get peer's metadata" + return mutableContent + } + switch requestMethod { case .sessionProposal: - mutableContent.title = "session proposal" + mutableContent.title = "session proposal: \(metadata.name)" case .sessionRequest: - mutableContent.title = "session request" + mutableContent.title = "session request: \(metadata.name)" case .authRequest: - mutableContent.title = "auth request" + mutableContent.title = "auth request: \(metadata.name)" } return mutableContent From d48d87a34c5343261f46ccd9c3dfd15d9ee3548e Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 29 Nov 2023 14:01:26 +0100 Subject: [PATCH 09/15] savepoint --- Example/PNDecryptionService/NotificationService.swift | 2 +- Sources/Web3Wallet/Web3WalletDecryptionService.swift | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Example/PNDecryptionService/NotificationService.swift b/Example/PNDecryptionService/NotificationService.swift index 250d19ca7..e51414f4b 100644 --- a/Example/PNDecryptionService/NotificationService.swift +++ b/Example/PNDecryptionService/NotificationService.swift @@ -38,7 +38,7 @@ class NotificationService: UNNotificationServiceExtension { do { let web3WalletDecryptionService = try Web3WalletDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") -// let rpcRequest = try web3WalletDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) + let rpcRequest = try web3WalletDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext, requestMethod: requestMethod) let mutableContent = content.mutableCopy() as! UNMutableNotificationContent diff --git a/Sources/Web3Wallet/Web3WalletDecryptionService.swift b/Sources/Web3Wallet/Web3WalletDecryptionService.swift index 724b3f8a8..e9321e7fb 100644 --- a/Sources/Web3Wallet/Web3WalletDecryptionService.swift +++ b/Sources/Web3Wallet/Web3WalletDecryptionService.swift @@ -1,9 +1,6 @@ import Foundation public final class Web3WalletDecryptionService { - enum Errors: Error { - case unknownTag - } public enum RequestMethod: UInt { case sessionRequest = 1108 case sessionProposal = 1100 @@ -22,8 +19,7 @@ public final class Web3WalletDecryptionService { return RequestMethod(rawValue: tag) } - public func decryptMessage(topic: String, ciphertext: String, tag: UInt) throws -> RPCRequest { - guard let requestMethod = Self.getRequestMethod(tag: tag) else { throw Errors.unknownTag } + public func decryptMessage(topic: String, ciphertext: String, requestMethod: RequestMethod) throws -> RPCRequest { switch requestMethod { case .sessionProposal, .sessionRequest: return try signDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) From 5b05a65628fe3d2de7bf6a125bdf0e1dc209533e Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Dec 2023 07:36:10 +0100 Subject: [PATCH 10/15] fix build --- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- .../Wallet/Notifications/NotificationsView.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 229e0f8ef..465b92c16 100644 --- a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -168,8 +168,8 @@ "repositoryURL": "https://github.com/WalletConnect/web3modal-swift", "state": { "branch": null, - "revision": "e68c1b1560264965ca13608db44294d301c6404f", - "version": "1.0.9" + "revision": "3295d69d1b12df29a5040578d107f56986b1b399", + "version": "1.0.13" } } ] diff --git a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift index 2daa40746..a3146cbd8 100644 --- a/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift +++ b/Example/WalletApp/PresentationLayer/Wallet/Notifications/NotificationsView.swift @@ -191,7 +191,7 @@ struct NotificationsView: View { AsyncButton("Subscribed") { try await presenter.unsubscribe(subscription: subscription) } - .buttonStyle(W3MButtonStyle(size: .m, variant: .accent, rightIcon: .Checkmark)) + .buttonStyle(W3MButtonStyle(size: .m, variant: .accent, rightIcon: Image.Medium.checkmark)) .disabled(true) } else { AsyncButton("Subscribe") { From 63b204dbc05b9b6089cff8e241cc7b2854e58bdc Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Dec 2023 09:03:03 +0100 Subject: [PATCH 11/15] refactor to handle request types --- .../NotificationService.swift | 22 ++++---- Sources/Auth/AuthDecryptionService.swift | 9 +++- .../SignDecryptionService.swift | 18 ++++++- .../Web3WalletDecryptionService.swift | 54 +++++++++++++++---- 4 files changed, 79 insertions(+), 24 deletions(-) diff --git a/Example/PNDecryptionService/NotificationService.swift b/Example/PNDecryptionService/NotificationService.swift index e51414f4b..095403342 100644 --- a/Example/PNDecryptionService/NotificationService.swift +++ b/Example/PNDecryptionService/NotificationService.swift @@ -20,8 +20,8 @@ class NotificationService: UNNotificationServiceExtension { let ciphertext = content.userInfo["message"] as? String, let tag = content.userInfo["tag"] as? UInt { - if let w3wRequestMethod = Web3WalletDecryptionService.getRequestMethod(tag: tag) { - let mutableContent = handleWeb3WalletNotification(content: content, topic: topic, requestMethod: w3wRequestMethod, ciphertext: ciphertext) + if Web3WalletDecryptionService.canHandle(tag: tag) { + let mutableContent = handleWeb3WalletNotification(content: content, topic: topic, tag: tag, ciphertext: ciphertext) contentHandler(mutableContent) } else if NotifyDecryptionService.canHandle(tag: tag) { let mutableContent = handleNotifyNotification(content: content, topic: topic, ciphertext: ciphertext) @@ -33,13 +33,12 @@ class NotificationService: UNNotificationServiceExtension { } } - private func handleWeb3WalletNotification(content: UNNotificationContent, topic: String, requestMethod: Web3WalletDecryptionService.RequestMethod, ciphertext: String) -> UNMutableNotificationContent { + private func handleWeb3WalletNotification(content: UNNotificationContent, topic: String, tag: UInt, ciphertext: String) -> UNMutableNotificationContent { do { let web3WalletDecryptionService = try Web3WalletDecryptionService(groupIdentifier: "group.com.walletconnect.sdk") - let rpcRequest = try web3WalletDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext, requestMethod: requestMethod) - + let decryptedPayload = try web3WalletDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext, tag: tag) let mutableContent = content.mutableCopy() as! UNMutableNotificationContent @@ -48,13 +47,18 @@ class NotificationService: UNNotificationServiceExtension { return mutableContent } - switch requestMethod { + switch decryptedPayload.requestMethod { case .sessionProposal: - mutableContent.title = "session proposal: \(metadata.name)" + mutableContent.title = "New session proposal!" + mutableContent.body = "A new session proposal arrived from \(metadata.name), please check your wallet" case .sessionRequest: - mutableContent.title = "session request: \(metadata.name)" + if let payload = decryptedPayload as? RequestPayload { + mutableContent.title = "New session request!" + mutableContent.body = "A new session request \(payload.requestMethod) arrived from \(metadata.name), please check your wallet" + } case .authRequest: - mutableContent.title = "auth request: \(metadata.name)" + mutableContent.title = "New authentication request!" + mutableContent.body = "A new authentication request arrived from \(metadata.name), please check your wallet" } return mutableContent diff --git a/Sources/Auth/AuthDecryptionService.swift b/Sources/Auth/AuthDecryptionService.swift index 8ba0c8e2e..5674d52b9 100644 --- a/Sources/Auth/AuthDecryptionService.swift +++ b/Sources/Auth/AuthDecryptionService.swift @@ -3,6 +3,7 @@ import Foundation public class AuthDecryptionService { enum Errors: Error { case couldNotInitialiseDefaults + case couldNotDecodeTypeFromCiphertext } private let serializer: Serializing private let pairingStorage: PairingStorage @@ -17,10 +18,14 @@ public class AuthDecryptionService { pairingStorage = PairingStorage(storage: SequenceStore(store: .init(defaults: defaults, identifier: PairStorageIdentifiers.pairings.rawValue))) } - public func decryptMessage(topic: String, ciphertext: String) throws -> RPCRequest { + public func decryptAuthRequest(topic: String, ciphertext: String) throws -> AuthRequest { let (rpcRequest, _, _): (RPCRequest, String?, Data) = try serializer.deserialize(topic: topic, encodedEnvelope: ciphertext) setPairingMetadata(rpcRequest: rpcRequest, topic: topic) - return rpcRequest + if let request = try rpcRequest.params?.get(AuthRequest.self) { + return request + } else { + throw Errors.couldNotDecodeTypeFromCiphertext + } } public func getMetadata(topic: String) -> AppMetadata? { diff --git a/Sources/WalletConnectSign/SignDecryptionService.swift b/Sources/WalletConnectSign/SignDecryptionService.swift index 5b80c49e6..182384698 100644 --- a/Sources/WalletConnectSign/SignDecryptionService.swift +++ b/Sources/WalletConnectSign/SignDecryptionService.swift @@ -3,6 +3,7 @@ import Foundation public class SignDecryptionService { enum Errors: Error { case couldNotInitialiseDefaults + case couldNotDecodeTypeFromCiphertext } private let serializer: Serializing private let sessionStorage: WCSessionStorage @@ -17,9 +18,22 @@ public class SignDecryptionService { sessionStorage = SessionStorage(storage: SequenceStore(store: .init(defaults: defaults, identifier: SignStorageIdentifiers.sessions.rawValue))) } - public func decryptMessage(topic: String, ciphertext: String) throws -> RPCRequest { + public func decryptProposal(topic: String, ciphertext: String) throws -> Session.Proposal { let (rpcRequest, _, _): (RPCRequest, String?, Data) = try serializer.deserialize(topic: topic, encodedEnvelope: ciphertext) - return rpcRequest + if let proposal = try rpcRequest.params?.get(Session.Proposal.self) { + return proposal + } else { + throw Errors.couldNotDecodeTypeFromCiphertext + } + } + + public func decryptRequest(topic: String, ciphertext: String) throws -> Request { + let (rpcRequest, _, _): (RPCRequest, String?, Data) = try serializer.deserialize(topic: topic, encodedEnvelope: ciphertext) + if let request = try rpcRequest.params?.get(Request.self) { + return request + } else { + throw Errors.couldNotDecodeTypeFromCiphertext + } } public func getMetadata(topic: String) -> AppMetadata? { diff --git a/Sources/Web3Wallet/Web3WalletDecryptionService.swift b/Sources/Web3Wallet/Web3WalletDecryptionService.swift index e9321e7fb..2171eeb39 100644 --- a/Sources/Web3Wallet/Web3WalletDecryptionService.swift +++ b/Sources/Web3Wallet/Web3WalletDecryptionService.swift @@ -1,6 +1,10 @@ import Foundation +import WalletConnectSign public final class Web3WalletDecryptionService { + enum Errors: Error { + case unknownTag + } public enum RequestMethod: UInt { case sessionRequest = 1108 case sessionProposal = 1100 @@ -9,23 +13,15 @@ public final class Web3WalletDecryptionService { private let signDecryptionService: SignDecryptionService private let authDecryptionService: AuthDecryptionService + private static let w3wTags: [UInt] = [1108, 1100, 3000] public init(groupIdentifier: String) throws { self.authDecryptionService = try AuthDecryptionService(groupIdentifier: groupIdentifier) self.signDecryptionService = try SignDecryptionService(groupIdentifier: groupIdentifier) } - public static func getRequestMethod(tag: UInt) -> RequestMethod? { - return RequestMethod(rawValue: tag) - } - - public func decryptMessage(topic: String, ciphertext: String, requestMethod: RequestMethod) throws -> RPCRequest { - switch requestMethod { - case .sessionProposal, .sessionRequest: - return try signDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) - case .authRequest: - return try authDecryptionService.decryptMessage(topic: topic, ciphertext: ciphertext) - } + public static func canHandle(tag: UInt) -> Bool { + return w3wTags.contains(tag) } public func getMetadata(topic: String) -> AppMetadata? { @@ -35,4 +31,40 @@ public final class Web3WalletDecryptionService { return authDecryptionService.getMetadata(topic: topic) } } + + public func decryptMessage(topic: String, ciphertext: String, tag: UInt) throws -> DecryptedPayloadProtocol { + guard let requestMethod = RequestMethod(rawValue: tag) else { throw Errors.unknownTag } + switch requestMethod { + case .sessionProposal: + let proposal = try signDecryptionService.decryptProposal(topic: topic, ciphertext: ciphertext) + return ProposalPayload(proposal: proposal) + case .sessionRequest: + let request = try signDecryptionService.decryptRequest(topic: topic, ciphertext: ciphertext) + return RequestPayload(request: request) + case .authRequest: + let request = try authDecryptionService.decryptAuthRequest(topic: topic, ciphertext: ciphertext) + return AuthRequestPayload(authRequest: request) + } + } + + +} + +public protocol DecryptedPayloadProtocol { + var requestMethod: Web3WalletDecryptionService.RequestMethod { get } +} + +public struct RequestPayload: DecryptedPayloadProtocol { + public var requestMethod: Web3WalletDecryptionService.RequestMethod { .sessionRequest } + var request: Request +} + +public struct ProposalPayload: DecryptedPayloadProtocol { + public var requestMethod: Web3WalletDecryptionService.RequestMethod { .sessionProposal } + var proposal: Session.Proposal +} + +public struct AuthRequestPayload: DecryptedPayloadProtocol { + public var requestMethod: Web3WalletDecryptionService.RequestMethod { .authRequest } + var authRequest: AuthRequest } From e44cef0951cb41f0790cb98ea598382baa5b79b3 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Dec 2023 09:26:43 +0100 Subject: [PATCH 12/15] fix session request notification --- .../PNDecryptionService/NotificationService.swift | 2 +- .../WalletConnectSign/SignDecryptionService.swift | 12 +++++++++++- Sources/Web3Wallet/Web3WalletDecryptionService.swift | 6 +++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Example/PNDecryptionService/NotificationService.swift b/Example/PNDecryptionService/NotificationService.swift index 095403342..474de9fd2 100644 --- a/Example/PNDecryptionService/NotificationService.swift +++ b/Example/PNDecryptionService/NotificationService.swift @@ -54,7 +54,7 @@ class NotificationService: UNNotificationServiceExtension { case .sessionRequest: if let payload = decryptedPayload as? RequestPayload { mutableContent.title = "New session request!" - mutableContent.body = "A new session request \(payload.requestMethod) arrived from \(metadata.name), please check your wallet" + mutableContent.body = "A new session request \(payload.request.method) arrived from \(metadata.name), please check your wallet" } case .authRequest: mutableContent.title = "New authentication request!" diff --git a/Sources/WalletConnectSign/SignDecryptionService.swift b/Sources/WalletConnectSign/SignDecryptionService.swift index 182384698..8549cd428 100644 --- a/Sources/WalletConnectSign/SignDecryptionService.swift +++ b/Sources/WalletConnectSign/SignDecryptionService.swift @@ -29,7 +29,17 @@ public class SignDecryptionService { public func decryptRequest(topic: String, ciphertext: String) throws -> Request { let (rpcRequest, _, _): (RPCRequest, String?, Data) = try serializer.deserialize(topic: topic, encodedEnvelope: ciphertext) - if let request = try rpcRequest.params?.get(Request.self) { + if let request = try rpcRequest.params?.get(SessionType.RequestParams.self), + let rpcId = rpcRequest.id{ + let request = Request( + id: rpcId, + topic: topic, + method: request.request.method, + params: request.request.params, + chainId: request.chainId, + expiry: request.request.expiry + ) + return request } else { throw Errors.couldNotDecodeTypeFromCiphertext diff --git a/Sources/Web3Wallet/Web3WalletDecryptionService.swift b/Sources/Web3Wallet/Web3WalletDecryptionService.swift index 2171eeb39..e4786129f 100644 --- a/Sources/Web3Wallet/Web3WalletDecryptionService.swift +++ b/Sources/Web3Wallet/Web3WalletDecryptionService.swift @@ -56,15 +56,15 @@ public protocol DecryptedPayloadProtocol { public struct RequestPayload: DecryptedPayloadProtocol { public var requestMethod: Web3WalletDecryptionService.RequestMethod { .sessionRequest } - var request: Request + public var request: Request } public struct ProposalPayload: DecryptedPayloadProtocol { public var requestMethod: Web3WalletDecryptionService.RequestMethod { .sessionProposal } - var proposal: Session.Proposal + public var proposal: Session.Proposal } public struct AuthRequestPayload: DecryptedPayloadProtocol { public var requestMethod: Web3WalletDecryptionService.RequestMethod { .authRequest } - var authRequest: AuthRequest + public var authRequest: AuthRequest } From 8083877d5e7f3e303fd04d3cc7d5b3f6669e3146 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Dec 2023 09:30:40 +0100 Subject: [PATCH 13/15] fix session proposal --- Sources/WalletConnectSign/SignDecryptionService.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectSign/SignDecryptionService.swift b/Sources/WalletConnectSign/SignDecryptionService.swift index 8549cd428..8b0e82125 100644 --- a/Sources/WalletConnectSign/SignDecryptionService.swift +++ b/Sources/WalletConnectSign/SignDecryptionService.swift @@ -20,8 +20,8 @@ public class SignDecryptionService { public func decryptProposal(topic: String, ciphertext: String) throws -> Session.Proposal { let (rpcRequest, _, _): (RPCRequest, String?, Data) = try serializer.deserialize(topic: topic, encodedEnvelope: ciphertext) - if let proposal = try rpcRequest.params?.get(Session.Proposal.self) { - return proposal + if let proposal = try rpcRequest.params?.get(SessionType.ProposeParams.self) { + return proposal.publicRepresentation(pairingTopic: topic) } else { throw Errors.couldNotDecodeTypeFromCiphertext } From 52fa7b8faa49c8fc21ff975a3a9b9304456a4e17 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Dec 2023 09:49:19 +0100 Subject: [PATCH 14/15] fix auth request --- Sources/Auth/AuthDecryptionService.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Sources/Auth/AuthDecryptionService.swift b/Sources/Auth/AuthDecryptionService.swift index 5674d52b9..9c2c55d61 100644 --- a/Sources/Auth/AuthDecryptionService.swift +++ b/Sources/Auth/AuthDecryptionService.swift @@ -21,8 +21,10 @@ public class AuthDecryptionService { public func decryptAuthRequest(topic: String, ciphertext: String) throws -> AuthRequest { let (rpcRequest, _, _): (RPCRequest, String?, Data) = try serializer.deserialize(topic: topic, encodedEnvelope: ciphertext) setPairingMetadata(rpcRequest: rpcRequest, topic: topic) - if let request = try rpcRequest.params?.get(AuthRequest.self) { - return request + if let params = try rpcRequest.params?.get(AuthRequestParams.self), + let id = rpcRequest.id { + let authRequest = AuthRequest(id: id, topic: topic, payload: params.payloadParams, requester: params.requester.metadata) + return authRequest } else { throw Errors.couldNotDecodeTypeFromCiphertext } From 78be65a138a88c39480bb02e9b3db1b89f1b10e4 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 1 Dec 2023 11:55:11 +0100 Subject: [PATCH 15/15] fix build --- Example/DApp/SceneDelegate.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Example/DApp/SceneDelegate.swift b/Example/DApp/SceneDelegate.swift index c08b15a8b..b9b49d56c 100644 --- a/Example/DApp/SceneDelegate.swift +++ b/Example/DApp/SceneDelegate.swift @@ -28,7 +28,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { Web3Modal.configure( projectId: InputConfig.projectId, - chainId: Blockchain("eip155:1")!, metadata: metadata )