From eaa46a2900c0a4cbb7011a9621496dfa0b2fd6b6 Mon Sep 17 00:00:00 2001 From: Pat Nakajima Date: Mon, 25 Sep 2023 09:07:09 -0700 Subject: [PATCH 1/4] Support WalletConnectV2 in the example app --- .../XMTPiOSExample.xcodeproj/project.pbxproj | 66 +++++++ .../xcshareddata/swiftpm/Package.resolved | 45 +++++ .../XMTPiOSExample/ContentView.swift | 67 ++----- .../XMTPiOSExample/Extensions/Data.swift | 42 ++++ .../XMTPiOSExample/Views/LoginView.swift | 187 ++++++++++++++++++ 5 files changed, 356 insertions(+), 51 deletions(-) create mode 100644 XMTPiOSExample/XMTPiOSExample/Extensions/Data.swift create mode 100644 XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift diff --git a/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.pbxproj b/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.pbxproj index 07367f28..cbc73c4b 100644 --- a/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.pbxproj +++ b/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.pbxproj @@ -33,6 +33,12 @@ A6AE5191297B625F006FDD0F /* XMTP in Frameworks */ = {isa = PBXBuildFile; productRef = A6AE5190297B625F006FDD0F /* XMTP */; }; A6AE5192297B6270006FDD0F /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = A65F0703297B5D4E00C3C76E /* Persistence.swift */; }; A6AE5194297B62C8006FDD0F /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = A6AE5193297B62C8006FDD0F /* KeychainAccess */; }; + A6C0F37B2AC1E321008C6AA7 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A6C0F37A2AC1E321008C6AA7 /* Starscream */; }; + A6C0F37E2AC1E34F008C6AA7 /* WalletConnect in Frameworks */ = {isa = PBXBuildFile; productRef = A6C0F37D2AC1E34F008C6AA7 /* WalletConnect */; }; + A6C0F3802AC1E34F008C6AA7 /* WalletConnectModal in Frameworks */ = {isa = PBXBuildFile; productRef = A6C0F37F2AC1E34F008C6AA7 /* WalletConnectModal */; }; + A6C0F3822AC1E34F008C6AA7 /* Web3Wallet in Frameworks */ = {isa = PBXBuildFile; productRef = A6C0F3812AC1E34F008C6AA7 /* Web3Wallet */; }; + A6C0F3842AC1E4B5008C6AA7 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6C0F3832AC1E4B5008C6AA7 /* LoginView.swift */; }; + A6C0F3862AC1E549008C6AA7 /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6C0F3852AC1E549008C6AA7 /* Data.swift */; }; A6D192D0293A7B97006B49F2 /* ConversationListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D192CF293A7B97006B49F2 /* ConversationListView.swift */; }; /* End PBXBuildFile section */ @@ -84,6 +90,8 @@ A6AE5180297B61AE006FDD0F /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; }; A6AE518B297B61C8006FDD0F /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = ""; }; A6AE518C297B6210006FDD0F /* NotificationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; + A6C0F3832AC1E4B5008C6AA7 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; + A6C0F3852AC1E549008C6AA7 /* Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = ""; }; A6D192CF293A7B97006B49F2 /* ConversationListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationListView.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -93,8 +101,12 @@ buildActionMask = 2147483647; files = ( A65F0707297B5E7600C3C76E /* WalletConnectSwift in Frameworks */, + A6C0F3802AC1E34F008C6AA7 /* WalletConnectModal in Frameworks */, 6AEE396E29F330CD0027B657 /* secp256k1 in Frameworks */, + A6C0F37E2AC1E34F008C6AA7 /* WalletConnect in Frameworks */, + A6C0F3822AC1E34F008C6AA7 /* Web3Wallet in Frameworks */, A69F33C6292DC992005A5556 /* XMTP in Frameworks */, + A6C0F37B2AC1E321008C6AA7 /* Starscream in Frameworks */, A65F070A297B5E8600C3C76E /* KeychainAccess in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -134,6 +146,7 @@ A6281991292DC825004B9117 /* XMTPiOSExample */ = { isa = PBXGroup; children = ( + A6C0F3872AC1E54F008C6AA7 /* Extensions */, A65F0703297B5D4E00C3C76E /* Persistence.swift */, A687810529679B5B00042FAB /* Account */, A69F33C8292DD54C005A5556 /* Views */, @@ -184,6 +197,7 @@ A683860B293EA862006336FF /* MessageListView.swift */, A6557A302941166E00CC4C7B /* MessageCellView.swift */, A6557A3229411F4F00CC4C7B /* NewConversationView.swift */, + A6C0F3832AC1E4B5008C6AA7 /* LoginView.swift */, ); path = Views; sourceTree = ""; @@ -197,6 +211,14 @@ path = NotificationService; sourceTree = ""; }; + A6C0F3872AC1E54F008C6AA7 /* Extensions */ = { + isa = PBXGroup; + children = ( + A6C0F3852AC1E549008C6AA7 /* Data.swift */, + ); + path = Extensions; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -220,6 +242,10 @@ A65F0706297B5E7600C3C76E /* WalletConnectSwift */, A65F0709297B5E8600C3C76E /* KeychainAccess */, 6AEE396D29F330CD0027B657 /* secp256k1 */, + A6C0F37A2AC1E321008C6AA7 /* Starscream */, + A6C0F37D2AC1E34F008C6AA7 /* WalletConnect */, + A6C0F37F2AC1E34F008C6AA7 /* WalletConnectModal */, + A6C0F3812AC1E34F008C6AA7 /* Web3Wallet */, ); productName = XMTPiOSExample; productReference = A628198F292DC825004B9117 /* XMTPiOSExample.app */; @@ -277,6 +303,8 @@ A65F0705297B5E7500C3C76E /* XCRemoteSwiftPackageReference "WalletConnectSwift" */, A65F0708297B5E8600C3C76E /* XCRemoteSwiftPackageReference "KeychainAccess" */, 6AEE396C29F330CD0027B657 /* XCRemoteSwiftPackageReference "secp256k1.swift" */, + A6C0F3792AC1E321008C6AA7 /* XCRemoteSwiftPackageReference "Starscream" */, + A6C0F37C2AC1E34F008C6AA7 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */, ); productRefGroup = A6281990292DC825004B9117 /* Products */; projectDirPath = ""; @@ -313,6 +341,7 @@ buildActionMask = 2147483647; files = ( A6557A3329411F4F00CC4C7B /* NewConversationView.swift in Sources */, + A6C0F3862AC1E549008C6AA7 /* Data.swift in Sources */, A65F0704297B5D4E00C3C76E /* Persistence.swift in Sources */, A687810729679BC700042FAB /* Account.swift in Sources */, A6557A312941166E00CC4C7B /* MessageCellView.swift in Sources */, @@ -322,6 +351,7 @@ A687810C29679BFC00042FAB /* WalletConnection.swift in Sources */, A69F33CA292DD557005A5556 /* LoggedInView.swift in Sources */, A69F33CC292DD568005A5556 /* QRCodeSheetView.swift in Sources */, + A6C0F3842AC1E4B5008C6AA7 /* LoginView.swift in Sources */, A6281993292DC825004B9117 /* XMTPiOSExampleApp.swift in Sources */, A67CCEC129355B4B00131F5C /* AccountManager.swift in Sources */, A687810E29679C0D00042FAB /* WalletConnectionMethod.swift in Sources */, @@ -655,6 +685,22 @@ kind = branch; }; }; + A6C0F3792AC1E321008C6AA7 /* XCRemoteSwiftPackageReference "Starscream" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/daltoniam/Starscream"; + requirement = { + kind = exactVersion; + version = 3.1.2; + }; + }; + A6C0F37C2AC1E34F008C6AA7 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/WalletConnect/WalletConnectSwiftV2"; + requirement = { + branch = main; + kind = branch; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -686,6 +732,26 @@ package = A65F0708297B5E8600C3C76E /* XCRemoteSwiftPackageReference "KeychainAccess" */; productName = KeychainAccess; }; + A6C0F37A2AC1E321008C6AA7 /* Starscream */ = { + isa = XCSwiftPackageProductDependency; + package = A6C0F3792AC1E321008C6AA7 /* XCRemoteSwiftPackageReference "Starscream" */; + productName = Starscream; + }; + A6C0F37D2AC1E34F008C6AA7 /* WalletConnect */ = { + isa = XCSwiftPackageProductDependency; + package = A6C0F37C2AC1E34F008C6AA7 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; + productName = WalletConnect; + }; + A6C0F37F2AC1E34F008C6AA7 /* WalletConnectModal */ = { + isa = XCSwiftPackageProductDependency; + package = A6C0F37C2AC1E34F008C6AA7 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; + productName = WalletConnectModal; + }; + A6C0F3812AC1E34F008C6AA7 /* Web3Wallet */ = { + isa = XCSwiftPackageProductDependency; + package = A6C0F37C2AC1E34F008C6AA7 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; + productName = Web3Wallet; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = A6281987292DC825004B9117 /* Project object */; diff --git a/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6187659e..79f88f7f 100644 --- a/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -54,6 +54,15 @@ "revision" : "ecb18d8ce4d88277cc4fb103973352d91e18c535" } }, + { + "identity" : "qrcode", + "kind" : "remoteSourceControl", + "location" : "https://github.com/WalletConnect/QRCode", + "state" : { + "revision" : "263f280d2c8144adfb0b6676109846cfc8dd552b", + "version" : "14.3.1" + } + }, { "identity" : "secp256k1.swift", "kind" : "remoteSourceControl", @@ -63,6 +72,15 @@ "version" : "0.10.0" } }, + { + "identity" : "starscream", + "kind" : "remoteSourceControl", + "location" : "https://github.com/daltoniam/Starscream", + "state" : { + "revision" : "a063fda2b8145a231953c20e7a646be254365396", + "version" : "3.1.2" + } + }, { "identity" : "swift-atomics", "kind" : "remoteSourceControl", @@ -144,6 +162,24 @@ "version" : "1.20.3" } }, + { + "identity" : "swift-qrcode-generator", + "kind" : "remoteSourceControl", + "location" : "https://github.com/dagronf/swift-qrcode-generator", + "state" : { + "revision" : "5ca09b6a2ad190f94aa3d6ddef45b187f8c0343b", + "version" : "1.0.3" + } + }, + { + "identity" : "swiftimagereadwrite", + "kind" : "remoteSourceControl", + "location" : "https://github.com/dagronf/SwiftImageReadWrite", + "state" : { + "revision" : "5596407d1cf61b953b8e658fa8636a471df3c509", + "version" : "1.1.6" + } + }, { "identity" : "walletconnectswift", "kind" : "remoteSourceControl", @@ -153,6 +189,15 @@ "revision" : "9e4dfba34fb35336fd5da551285d7986ff536cb8" } }, + { + "identity" : "walletconnectswiftv2", + "kind" : "remoteSourceControl", + "location" : "https://github.com/WalletConnect/WalletConnectSwiftV2", + "state" : { + "branch" : "main", + "revision" : "13446a81e678e8eddc6ab506e85c522df0163f1f" + } + }, { "identity" : "web3.swift", "kind" : "remoteSourceControl", diff --git a/XMTPiOSExample/XMTPiOSExample/ContentView.swift b/XMTPiOSExample/XMTPiOSExample/ContentView.swift index 37818cdc..8899659d 100644 --- a/XMTPiOSExample/XMTPiOSExample/ContentView.swift +++ b/XMTPiOSExample/XMTPiOSExample/ContentView.swift @@ -19,6 +19,7 @@ struct ContentView: View { @State private var isShowingQRCode = false @State private var qrCodeImage: UIImage? + @State private var isConnectingWallet = false @State private var client: Client? @@ -26,8 +27,21 @@ struct ContentView: View { VStack { switch status { case .unknown: - Button("Connect Wallet", action: connectWallet) - Button("Generate Wallet", action: generateWallet) + Button("Connect Wallet") { isConnectingWallet = true } + .sheet(isPresented: $isConnectingWallet) { + LoginView(onTryDemo: {}, onConnecting: {}, onConnected: { client in + do { + let keysData = try client.privateKeyBundle.serializedData() + Persistence().saveKeys(keysData) + self.status = .connected(client) + } catch { + print("Error setting up client: \(error)") + } + + print("Got a client: \(client)") + }) + } + Button("Generate Wallet") { generateWallet() } case .connecting: ProgressView("Connecting…") case let .connected(client): @@ -52,55 +66,6 @@ struct ContentView: View { } } - func connectWallet() { - status = .connecting - - do { - switch try accountManager.account.preferredConnectionMethod() { - case let .qrCode(image): - qrCodeImage = image - - DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { - self.isShowingQRCode = true - } - case let .redirect(url): - UIApplication.shared.open(url) - case let .manual(url): - print("Open \(url) in mobile safari") - } - - Task { - do { - try await accountManager.account.connect() - - for _ in 0 ... 30 { - if accountManager.account.isConnected { - let client = try await Client.create(account: accountManager.account) - - let keysData = try client.privateKeyBundle.serializedData() - Persistence().saveKeys(keysData) - - self.status = .connected(client) - self.isShowingQRCode = false - return - } - - try await Task.sleep(for: .seconds(1)) - } - - self.status = .error("Timed out waiting to connect (30 seconds)") - } catch { - await MainActor.run { - self.status = .error("Error connecting: \(error)") - self.isShowingQRCode = false - } - } - } - } catch { - status = .error("No acceptable connection methods found \(error)") - } - } - func generateWallet() { Task { do { diff --git a/XMTPiOSExample/XMTPiOSExample/Extensions/Data.swift b/XMTPiOSExample/XMTPiOSExample/Extensions/Data.swift new file mode 100644 index 00000000..376cad8e --- /dev/null +++ b/XMTPiOSExample/XMTPiOSExample/Extensions/Data.swift @@ -0,0 +1,42 @@ +// +// Data.swift +// XMTPChat +// +// Created by Pat Nakajima on 9/20/23. +// + +import Foundation + +extension Data { + static func value(of nibble: UInt8) -> UInt8? { + guard let letter = String(bytes: [nibble], encoding: .ascii) else { return nil } + return UInt8(letter, radix: 16) + } + + public init(hexString hex: String) { + var data = Data() + let string = hex.hasPrefix("0x") ? String(hex.dropFirst(2)) : hex + + // Convert the string to bytes for better performance + guard + let stringData = string.data(using: .ascii, allowLossyConversion: true) + else { + self = data + return + } + + let stringBytes = Array(stringData) + for idx in stride(from: 0, to: stringBytes.count, by: 2) { + guard let high = Data.value(of: stringBytes[idx]) else { + data.removeAll() + break + } + if idx < stringBytes.count - 1, let low = Data.value(of: stringBytes[idx + 1]) { + data.append((high << 4) | low) + } else { + data.append(high) + } + } + self = data + } +} diff --git a/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift b/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift new file mode 100644 index 00000000..629db440 --- /dev/null +++ b/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift @@ -0,0 +1,187 @@ +// +// LoginView.swift +// XMTPChat +// +// Created by Pat Nakajima on 6/7/23. +// + +import SwiftUI +import WebKit +import XMTP +import WalletConnectRelay +import Combine +import SwiftUI +import WalletConnectModal +import Starscream + +extension WebSocket: WebSocketConnecting { } +extension Blockchain: @unchecked Sendable { } + +struct SocketFactory: WebSocketFactory { + func create(with url: URL) -> WalletConnectRelay.WebSocketConnecting { + WebSocket(url: url) + } +} + +struct ModalWrapper: UIViewControllerRepresentable { + func makeUIViewController(context: Context) -> UIViewController { + let controller = UIViewController() + Task { + try? await Task.sleep(for: .seconds(0.4)) + await MainActor.run { + WalletConnectModal.present(from: controller) + } + } + return controller + } + + func updateUIViewController(_ uiViewController: UIViewController, context: Context) { + } +} + +class Signer: SigningKey { + var account: WalletConnectUtils.Account + var session: WalletConnectSign.Session + + var address: String { + account.address + } + + init(session: WalletConnectSign.Session, account: WalletConnectUtils.Account) { + self.session = session + self.account = account + self.cancellable = Sign.instance.sessionResponsePublisher.sink { response in + print("RESPONSE: \(response)") + + guard case let .response(codable) = response.result else { + print("NO RESPONSE") + return + } + + let signatureData = Data(hexString: codable.value as! String) + print("SIGNATURE DATA: \(signatureData)") + print("GOT A RESPONSE: \(response) signature: \(signatureData)") + + let signature = Signature(bytes: signatureData[0..<64], recovery: Int(signatureData[64])) + self.continuation?.resume(returning: signature) + self.continuation = nil + } + } + + var cancellable: AnyCancellable? + var continuation: CheckedContinuation? + + func sign(_ data: Data) async throws -> XMTP.Signature { + let address = account.address + let topic = session.topic + let blockchain = account.blockchain + + return await withCheckedContinuation { continuation in + self.continuation = continuation + + Task { + let method = "personal_sign" + let walletAddress = address + let requestParams = AnyCodable([ + String(data: data, encoding: .utf8), + walletAddress + ]) + + let request = Request( + topic: topic, + method: method, + params: requestParams, + chainId: blockchain + ) + + try await Sign.instance.request(params: request) + } + } + } + + func sign(message: String) async throws -> XMTP.Signature { + try await sign(Data(message.utf8)) + } +} + +struct LoginView: View { + var onTryDemo: () -> Void + var onConnecting: () -> Void + var onConnected: (Client) -> Void + var publishers: [AnyCancellable] = [] + + @State private var isShowingWebview = true + + init( + onTryDemo: @escaping () -> Void, + onConnecting: @escaping () -> Void, + onConnected: @escaping (Client) -> Void + ) { + self.onTryDemo = onTryDemo + self.onConnected = onConnected + self.onConnecting = onConnecting + + Networking.configure( + projectId: "YOUR PROJECT ID", + socketFactory: SocketFactory() + ) + + WalletConnectModal.configure( + projectId: "YOUR PROJECT ID", + metadata: .init( + name: "XMTP Chat", + description: "It's a chat app.", + url: "https://localhost:4567", + icons: [] + ) + ) + + let requiredNamespaces: [String: ProposalNamespace] = [:] + let optionalNamespaces: [String: ProposalNamespace] = [ + "eip155": ProposalNamespace( + chains: [ + Blockchain("eip155:80001")!, //Polygon Testnet + Blockchain("eip155:421613")! //Arbitrum Testnet + ], + methods: [ + "personal_sign" + ], events: [] + ) + ] + + WalletConnectModal.set(sessionParams: .init( + requiredNamespaces: requiredNamespaces, + optionalNamespaces: optionalNamespaces, + sessionProperties: nil + )) + + Sign.instance.sessionSettlePublisher + .receive(on: DispatchQueue.main) + .sink { session in + guard let account = session.accounts.first else { return } + + Task(priority: .high) { + let signer = Signer(session: session, account: account) + let client = try await Client.create( + account: signer, + options: .init(api: .init(env: .production, isSecure: true)) + ) + + await MainActor.run { + onConnected(client) + } + } + + print("GOT AN ACCOUNT \(account)") + } + .store(in: &publishers) + } + + var body: some View { + ModalWrapper() + } +} + +#Preview { + LoginView(onTryDemo: {}, onConnecting: {}, onConnected: { _ in }) +} From b9f1dd7fe76b431edfeeb028de6031723e4ddeea Mon Sep 17 00:00:00 2001 From: Pat Nakajima Date: Mon, 25 Sep 2023 09:14:56 -0700 Subject: [PATCH 2/4] Simplify, add some comments --- .../XMTPiOSExample/ContentView.swift | 2 +- .../XMTPiOSExample/Views/LoginView.swift | 18 +++++------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/XMTPiOSExample/XMTPiOSExample/ContentView.swift b/XMTPiOSExample/XMTPiOSExample/ContentView.swift index 8899659d..1b80321a 100644 --- a/XMTPiOSExample/XMTPiOSExample/ContentView.swift +++ b/XMTPiOSExample/XMTPiOSExample/ContentView.swift @@ -29,7 +29,7 @@ struct ContentView: View { case .unknown: Button("Connect Wallet") { isConnectingWallet = true } .sheet(isPresented: $isConnectingWallet) { - LoginView(onTryDemo: {}, onConnecting: {}, onConnected: { client in + LoginView(onConnected: { client in do { let keysData = try client.privateKeyBundle.serializedData() Persistence().saveKeys(keysData) diff --git a/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift b/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift index 629db440..7c0b3f30 100644 --- a/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift +++ b/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift @@ -23,6 +23,8 @@ struct SocketFactory: WebSocketFactory { } } +// WalletConnectV2's ModalSheet doesn't have any public initializers so we need +// to wrap their UIKit API struct ModalWrapper: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> UIViewController { let controller = UIViewController() @@ -39,6 +41,7 @@ struct ModalWrapper: UIViewControllerRepresentable { } } +// Conformance to XMTP iOS's SigningKey protocol class Signer: SigningKey { var account: WalletConnectUtils.Account var session: WalletConnectSign.Session @@ -51,18 +54,13 @@ class Signer: SigningKey { self.session = session self.account = account self.cancellable = Sign.instance.sessionResponsePublisher.sink { response in - print("RESPONSE: \(response)") - guard case let .response(codable) = response.result else { - print("NO RESPONSE") return } let signatureData = Data(hexString: codable.value as! String) - print("SIGNATURE DATA: \(signatureData)") - print("GOT A RESPONSE: \(response) signature: \(signatureData)") - let signature = Signature(bytes: signatureData[0..<64], recovery: Int(signatureData[64])) + self.continuation?.resume(returning: signature) self.continuation = nil } @@ -105,21 +103,15 @@ class Signer: SigningKey { } struct LoginView: View { - var onTryDemo: () -> Void - var onConnecting: () -> Void var onConnected: (Client) -> Void var publishers: [AnyCancellable] = [] @State private var isShowingWebview = true init( - onTryDemo: @escaping () -> Void, - onConnecting: @escaping () -> Void, onConnected: @escaping (Client) -> Void ) { - self.onTryDemo = onTryDemo self.onConnected = onConnected - self.onConnecting = onConnecting Networking.configure( projectId: "YOUR PROJECT ID", @@ -183,5 +175,5 @@ struct LoginView: View { } #Preview { - LoginView(onTryDemo: {}, onConnecting: {}, onConnected: { _ in }) + LoginView(onConnected: { _ in }) } From 132f46d5e901ca6d56bbe828ad4401d6277645ee Mon Sep 17 00:00:00 2001 From: Pat Nakajima Date: Mon, 4 Dec 2023 16:33:38 -0800 Subject: [PATCH 3/4] fix lint --- XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift b/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift index 7c0b3f30..0f506d99 100644 --- a/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift +++ b/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift @@ -132,8 +132,10 @@ struct LoginView: View { let optionalNamespaces: [String: ProposalNamespace] = [ "eip155": ProposalNamespace( chains: [ + // swiftlint:disable force_unwrapping Blockchain("eip155:80001")!, //Polygon Testnet Blockchain("eip155:421613")! //Arbitrum Testnet + // swiftlint:enable force_unwrapping ], methods: [ "personal_sign" From bbcde7e83d957e3766d3d59b6c8dc22188ec2cbb Mon Sep 17 00:00:00 2001 From: Pat Nakajima Date: Mon, 4 Dec 2023 16:35:36 -0800 Subject: [PATCH 4/4] fix more lint --- XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift b/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift index 0f506d99..3cf8523c 100644 --- a/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift +++ b/XMTPiOSExample/XMTPiOSExample/Views/LoginView.swift @@ -29,7 +29,9 @@ struct ModalWrapper: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> UIViewController { let controller = UIViewController() Task { + // swiftlint:disable no_optional_try try? await Task.sleep(for: .seconds(0.4)) + // swiftlint:enable no_optional_try await MainActor.run { WalletConnectModal.present(from: controller) } @@ -58,7 +60,9 @@ class Signer: SigningKey { return } + // swiftlint:disable force_cast let signatureData = Data(hexString: codable.value as! String) + // swiftlint:enable force_cast let signature = Signature(bytes: signatureData[0..<64], recovery: Int(signatureData[64])) self.continuation?.resume(returning: signature)