From 1e93d8ffe1f3c8d2b3e965ee9b3527fc4a91fab9 Mon Sep 17 00:00:00 2001 From: Ivan Grachev Date: Sat, 12 Feb 2022 21:30:05 +0300 Subject: [PATCH] Refactor processing Safari requests on macOS --- Tokenary macOS/Agent.swift | 140 +++-------------------------- Tokenary macOS/WalletConnect.swift | 8 +- 2 files changed, 20 insertions(+), 128 deletions(-) diff --git a/Tokenary macOS/Agent.swift b/Tokenary macOS/Agent.swift index 266f1a88..002cdc37 100644 --- a/Tokenary macOS/Agent.swift +++ b/Tokenary macOS/Agent.swift @@ -89,32 +89,28 @@ class Agent: NSObject { } } - func showApprove(transaction: Transaction, chain: EthereumChain, peerMeta: PeerMeta?, browser: Browser?, completion: @escaping (Transaction?) -> Void) { + func showApprove(transaction: Transaction, chain: EthereumChain, peerMeta: PeerMeta?, completion: @escaping (Transaction?) -> Void) { let windowController = Window.showNew() let approveViewController = ApproveTransactionViewController.with(transaction: transaction, chain: chain, peerMeta: peerMeta) { [weak self] transaction in if transaction != nil { self?.askAuthentication(on: windowController.window, onStart: false, reason: .sendTransaction) { success in completion(success ? transaction : nil) - Window.closeAllAndActivateBrowser(force: browser) } } else { - Window.closeAllAndActivateBrowser(force: browser) completion(nil) } } windowController.contentViewController = approveViewController } - func showApprove(subject: ApprovalSubject, meta: String, peerMeta: PeerMeta?, browser: Browser?, completion: @escaping (Bool) -> Void) { + func showApprove(subject: ApprovalSubject, meta: String, peerMeta: PeerMeta?, completion: @escaping (Bool) -> Void) { let windowController = Window.showNew() let approveViewController = ApproveViewController.with(subject: subject, meta: meta, peerMeta: peerMeta) { [weak self] result in if result { self?.askAuthentication(on: windowController.window, onStart: false, reason: subject.asAuthenticationReason) { success in completion(success) - Window.closeAllAndActivateBrowser(force: browser) } } else { - Window.closeAllAndActivateBrowser(force: browser) completion(result) } } @@ -301,130 +297,22 @@ class Agent: NSObject { } private func processSafariRequest(_ safariRequest: SafariRequest) { - // TODO: process all chains' requests - guard ExtensionBridge.hasRequest(id: safariRequest.id), case let .ethereum(request) = safariRequest.body else { - respond(to: safariRequest, error: Strings.somethingWentWrong) - return + let action = DappRequestProcessor.processSafariRequest(safariRequest) { + Window.closeAllAndActivateBrowser(force: .safari) } - - let peerMeta = PeerMeta(title: safariRequest.host, iconURLString: safariRequest.favicon) - switch request.method { - case .signPersonalMessage: - guard let data = request.message else { - respond(to: safariRequest, error: Strings.somethingWentWrong) - return - } - let text = String(data: data, encoding: .utf8) ?? data.hexString - showApprove(subject: .signPersonalMessage, meta: text, peerMeta: peerMeta, browser: .safari) { [weak self] approved in - if approved { - self?.signPersonalMessage(address: request.address, data: data, request: safariRequest) - } else { - self?.respond(to: safariRequest, error: Strings.failedToSign) - } - } - case .requestAccounts, .switchAccount: + + switch action { + case .none: + break + case .selectAccount(let action): let windowController = Window.showNew() let accountsList = instantiate(AccountsListViewController.self) - - accountsList.onSelectedWallet = { [weak self] chain, wallet in - if let chain = chain, let wallet = wallet, let ethereumAddress = wallet.ethereumAddress { - let responseBody = ResponseToExtension.Ethereum(results: [ethereumAddress], chainId: chain.hexStringId, rpcURL: chain.nodeURLString) - self?.respond(to: safariRequest, body: .ethereum(responseBody)) - } else { - self?.respond(to: safariRequest, error: Strings.canceled) - } - Window.closeAllAndActivateBrowser(force: .safari) - } + accountsList.onSelectedWallet = action.completion windowController.contentViewController = accountsList - case .signMessage: - guard let data = request.message else { - respond(to: safariRequest, error: Strings.somethingWentWrong) - return - } - showApprove(subject: .signMessage, meta: data.hexString, peerMeta: peerMeta, browser: .safari) { [weak self] approved in - if approved { - self?.signMessage(address: request.address, data: data, request: safariRequest) - } else { - self?.respond(to: safariRequest, error: Strings.failedToSign) - } - } - case .signTypedMessage: - guard let raw = request.raw else { - respond(to: safariRequest, error: Strings.somethingWentWrong) - return - } - showApprove(subject: .signTypedData, meta: raw, peerMeta: peerMeta, browser: .safari) { [weak self] approved in - if approved { - self?.signTypedData(address: request.address, raw: raw, request: safariRequest) - } else { - self?.respond(to: safariRequest, error: Strings.failedToSign) - } - } - case .signTransaction: - guard let transaction = request.transaction, let chain = request.chain else { - respond(to: safariRequest, error: Strings.somethingWentWrong) - return - } - showApprove(transaction: transaction, chain: chain, peerMeta: peerMeta, browser: .safari) { [weak self] transaction in - if let transaction = transaction { - self?.sendTransaction(transaction, address: request.address, chain: chain, request: safariRequest) - } else { - self?.respond(to: safariRequest, error: Strings.canceled) - } - } - case .ecRecover: - if let (signature, message) = request.signatureAndMessage, - let recovered = ethereum.recover(signature: signature, message: message) { - respond(to: safariRequest, body: .ethereum(.init(result: recovered))) - } else { - respond(to: safariRequest, error: Strings.failedToVerify) - } - Window.closeAllAndActivateBrowser(force: .safari) - case .switchEthereumChain, .addEthereumChain, .watchAsset: - Window.closeAllAndActivateBrowser(force: .safari) - } - } - - private func respond(to safariRequest: SafariRequest, body: ResponseToExtension.Body) { - let response = ResponseToExtension(for: safariRequest, body: body) - ExtensionBridge.respond(response: response) - } - - private func respond(to safariRequest: SafariRequest, error: String) { - let response = ResponseToExtension(for: safariRequest, error: error) - ExtensionBridge.respond(response: response) - } - - private func sendTransaction(_ transaction: Transaction, address: String, chain: EthereumChain, request: SafariRequest) { - if let wallet = walletsManager.getWallet(address: address), - let transactionHash = try? ethereum.send(transaction: transaction, wallet: wallet, chain: chain) { - respond(to: request, body: .ethereum(.init(result: transactionHash))) - } else { - respond(to: request, error: Strings.failedToSign) - } - } - - private func signTypedData(address: String, raw: String, request: SafariRequest) { - if let wallet = walletsManager.getWallet(address: address), let signed = try? ethereum.sign(typedData: raw, wallet: wallet) { - respond(to: request, body: .ethereum(.init(result: signed))) - } else { - respond(to: request, error: Strings.failedToSign) - } - } - - private func signMessage(address: String, data: Data, request: SafariRequest) { - if let wallet = walletsManager.getWallet(address: address), let signed = try? ethereum.sign(data: data, wallet: wallet) { - respond(to: request, body: .ethereum(.init(result: signed))) - } else { - respond(to: request, error: Strings.failedToSign) - } - } - - private func signPersonalMessage(address: String, data: Data, request: SafariRequest) { - if let wallet = walletsManager.getWallet(address: address), let signed = try? ethereum.signPersonalMessage(data: data, wallet: wallet) { - respond(to: request, body: .ethereum(.init(result: signed))) - } else { - respond(to: request, error: Strings.failedToSign) + case .approveMessage(let action): + showApprove(subject: action.subject, meta: action.meta, peerMeta: action.peerMeta, completion: action.completion) + case .approveTransaction(let action): + showApprove(transaction: action.transaction, chain: action.chain, peerMeta: action.peerMeta, completion: action.completion) } } diff --git a/Tokenary macOS/WalletConnect.swift b/Tokenary macOS/WalletConnect.swift index 1a981ac3..d389703c 100644 --- a/Tokenary macOS/WalletConnect.swift +++ b/Tokenary macOS/WalletConnect.swift @@ -133,10 +133,12 @@ class WalletConnect { let peer = PeerMeta(wcPeerMeta: getPeerOfInteractor(interactor)) let transaction = Transaction(from: wct.from, to: to, nonce: wct.nonce, gasPrice: wct.gasPrice, gas: wct.gas, value: wct.value, data: wct.data) - agent.showApprove(transaction: transaction, chain: chain, peerMeta: peer, browser: nil) { [weak self, weak interactor] transaction in + agent.showApprove(transaction: transaction, chain: chain, peerMeta: peer) { [weak self, weak interactor] transaction in if let transaction = transaction { self?.sendTransaction(transaction, walletId: walletId, chainId: chainId, requestId: id, interactor: interactor) + Window.closeAllAndActivateBrowser(force: nil) } else { + Window.closeAllAndActivateBrowser(force: nil) self?.rejectRequest(id: id, interactor: interactor, message: Strings.canceled) } } @@ -160,10 +162,12 @@ class WalletConnect { } let peer = PeerMeta(wcPeerMeta: getPeerOfInteractor(interactor)) - agent.showApprove(subject: approvalSubject, meta: message ?? "", peerMeta: peer, browser: nil) { [weak self, weak interactor] approved in + agent.showApprove(subject: approvalSubject, meta: message ?? "", peerMeta: peer) { [weak self, weak interactor] approved in if approved { self?.sign(id: id, payload: payload, walletId: walletId, interactor: interactor) + Window.closeAllAndActivateBrowser(force: nil) } else { + Window.closeAllAndActivateBrowser(force: nil) self?.rejectRequest(id: id, interactor: interactor, message: Strings.canceled) } }