diff --git a/AlphaWallet.xcodeproj/project.pbxproj b/AlphaWallet.xcodeproj/project.pbxproj index 15e6325a9..3f6a20d7b 100644 --- a/AlphaWallet.xcodeproj/project.pbxproj +++ b/AlphaWallet.xcodeproj/project.pbxproj @@ -569,7 +569,6 @@ 874ED68A27D9E4B4001AB374 /* AmountTextFieldPair.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874ED68927D9E4B4001AB374 /* AmountTextFieldPair.swift */; }; 874ED68C27D9E4D1001AB374 /* AmountTextFieldViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874ED68B27D9E4D1001AB374 /* AmountTextFieldViewModel.swift */; }; 874ED68E27DA1BA7001AB374 /* SwapOptionsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874ED68D27DA1BA7001AB374 /* SwapOptionsCoordinator.swift */; }; - 874ED69027DB48FE001AB374 /* DappRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874ED68F27DB48FE001AB374 /* DappRequestHandler.swift */; }; 874ED69527DF34C0001AB374 /* SwapOptionsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874ED69427DF34C0001AB374 /* SwapOptionsHeaderView.swift */; }; 874ED69727DF3685001AB374 /* SlippageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874ED69627DF3685001AB374 /* SlippageView.swift */; }; 874ED69D27DF36D2001AB374 /* SlippageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874ED69C27DF36D2001AB374 /* SlippageViewModel.swift */; }; @@ -1446,7 +1445,6 @@ 874ED68927D9E4B4001AB374 /* AmountTextFieldPair.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AmountTextFieldPair.swift; sourceTree = ""; }; 874ED68B27D9E4D1001AB374 /* AmountTextFieldViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AmountTextFieldViewModel.swift; sourceTree = ""; }; 874ED68D27DA1BA7001AB374 /* SwapOptionsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwapOptionsCoordinator.swift; sourceTree = ""; }; - 874ED68F27DB48FE001AB374 /* DappRequestHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DappRequestHandler.swift; sourceTree = ""; }; 874ED69427DF34C0001AB374 /* SwapOptionsHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwapOptionsHeaderView.swift; sourceTree = ""; }; 874ED69627DF3685001AB374 /* SlippageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlippageView.swift; sourceTree = ""; }; 874ED69C27DF36D2001AB374 /* SlippageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlippageViewModel.swift; sourceTree = ""; }; @@ -4099,7 +4097,6 @@ 87B1B5F228C8715F0072A5E2 /* Analytics */, 5E7C7FC75FF544B1DF0B0D8B /* PushNotificationsService.swift */, 875CA90828BF2B720020FA48 /* LocalNotificationService.swift */, - 874ED68F27DB48FE001AB374 /* DappRequestHandler.swift */, 87FBF2B428056B6F00616B7D /* FirebaseReportService.swift */, 87D175EC24AF1565002130D2 /* KeyboardChecker.swift */, ); @@ -5432,7 +5429,6 @@ 5E7C745ECFCAE8B1A52B7FAC /* EnabledServersViewModel.swift in Sources */, 5E7C76C8A983A91A82F646E5 /* TokenInstanceWebView.swift in Sources */, 87F15AF927F1EB9900EB9787 /* SwapStepViewModel.swift in Sources */, - 874ED69027DB48FE001AB374 /* DappRequestHandler.swift in Sources */, 5E7C742DDE5C63804A2C420D /* Collection+UIView.swift in Sources */, 87D163A7242CD9A2002662D2 /* AddHideTokenSectionHeaderView.swift in Sources */, 5E7C7ACB2F44B820940EACEB /* TokenInstanceActionViewController.swift in Sources */, diff --git a/AlphaWallet/ActiveWalletCoordinator.swift b/AlphaWallet/ActiveWalletCoordinator.swift index aaafd59f5..903bcd6b4 100644 --- a/AlphaWallet/ActiveWalletCoordinator.swift +++ b/AlphaWallet/ActiveWalletCoordinator.swift @@ -15,7 +15,7 @@ protocol ActiveWalletCoordinatorDelegate: AnyObject { } // swiftlint:disable type_body_length -class ActiveWalletCoordinator: NSObject, Coordinator, DappRequestHandlerDelegate { +class ActiveWalletCoordinator: NSObject, Coordinator { private let wallet: Wallet private let config: Config private let assetDefinitionStore: AssetDefinitionStore @@ -123,13 +123,6 @@ class ActiveWalletCoordinator: NSObject, Coordinator, DappRequestHandlerDelegate } } - private lazy var dappRequestHandler: DappRequestHandler = { - let handler = DappRequestHandler(walletConnectProvider: walletConnectCoordinator.walletConnectProvider, dappBrowserCoordinator: dappBrowserCoordinator!) - handler.delegate = self - - return handler - }() - private lazy var transactionNotificationService: NotificationSourceService = { let service = TransactionNotificationSourceService(transactionDataStore: transactionsDataStore, config: config) service.delegate = promptBackup @@ -619,20 +612,37 @@ extension ActiveWalletCoordinator: WalletConnectCoordinatorDelegate { buyCrypto(wallet: wallet, token: token, viewController: viewController, source: source) } - func requestSwitchChain(server: RPCServer, currentUrl: URL?, callbackID: SwitchCustomChainCallbackId, targetChain: WalletSwitchEthereumChainObject) { + func requestSwitchChain(server: RPCServer, + currentUrl: URL?, + targetChain: WalletSwitchEthereumChainObject) -> AnyPublisher { + let coordinator = DappRequestSwitchExistingChainCoordinator( config: config, server: server, - callbackId: callbackID, targetChain: targetChain, restartQueue: restartQueue, analytics: analytics, currentUrl: currentUrl, inViewController: presentationViewController) - coordinator.delegate = dappRequestHandler - dappRequestHandler.addCoordinator(coordinator) - coordinator.start() + addCoordinator(coordinator) + + return coordinator.start() + .handleEvents(receiveOutput: { [weak self] operation in + //NOTE: we need this small delay to make sure source subscriber received event, e.g web browser or wallet connect, and then perform switching actions, because for processRestartQueueAndRestartUI recreates active wallet coordinator, will be removed when silent updated will be applied + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + switch operation { + case .restartToEnableAndSwitchBrowserToServer: + self?.processRestartQueueAndRestartUI(reason: .serverChange) + case .switchBrowserToExistingServer, .notifySuccessful: + break + } + } + }, receiveCompletion: { [weak self] _ in + self?.removeCoordinator(coordinator) + }, receiveCancel: { [weak self] in + self?.removeCoordinator(coordinator) + }).eraseToAnyPublisher() } func requestAddCustomChain(server: RPCServer, @@ -652,14 +662,12 @@ extension ActiveWalletCoordinator: WalletConnectCoordinatorDelegate { return coordinator.start() .handleEvents(receiveOutput: { [weak self] operation in - //NOTE: we need this small delay to make sure source subscriber received event, e.g web browser or wallet connect, and then perform switching actions, because for processRestartQueueAndRestartUI recreates active wallet coordinator, will be removes when silent updated will be applied + //NOTE: we need this small delay to make sure source subscriber received event, e.g web browser or wallet connect, and then perform switching actions, because for processRestartQueueAndRestartUI recreates active wallet coordinator, will be removed when silent updated will be applied DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { switch operation { case .notifySuccessful: break - case .restartToEnableAndSwitchBrowserToServer: - self?.processRestartQueueAndRestartUI(reason: .serverChange) - case .restartToAddEnableAndSwitchBrowserToServer: + case .restartToEnableAndSwitchBrowserToServer, .restartToAddEnableAndSwitchBrowserToServer: self?.processRestartQueueAndRestartUI(reason: .serverChange) case .switchBrowserToExistingServer(let server, url: let url): self?.dappBrowserCoordinator?.switch(toServer: server, url: url) diff --git a/AlphaWallet/Browser/Coordinators/DappBrowserCoordinator.swift b/AlphaWallet/Browser/Coordinators/DappBrowserCoordinator.swift index f11ad6a71..40c7c1f28 100644 --- a/AlphaWallet/Browser/Coordinators/DappBrowserCoordinator.swift +++ b/AlphaWallet/Browser/Coordinators/DappBrowserCoordinator.swift @@ -404,8 +404,30 @@ final class DappBrowserCoordinator: NSObject, Coordinator { }).store(in: &cancellable) } - private func switchChain(callbackID: Int, targetChain: WalletSwitchEthereumChainObject, inViewController viewController: UIViewController) { - delegate?.requestSwitchChain(server: server, currentUrl: currentUrl, callbackID: .dapp(requestId: callbackID), targetChain: targetChain) + private func switchChain(callbackID: Int, targetChain: WalletSwitchEthereumChainObject) { + guard let delegate = delegate else { + notifyFinish(callbackID: callbackID, value: .failure(.cancelled)) + return + } + + delegate.requestSwitchChain(server: server, currentUrl: currentUrl, targetChain: targetChain) + .sink(receiveCompletion: { [weak self] result in + if case .failure(let e) = result { + let error = e.embedded as? DAppError ?? .nodeError("Unknown Error") + + self?.notifyFinish(callbackID: callbackID, value: .failure(error)) + } + }, receiveValue: { [weak self] operation in + switch operation { + case .notifySuccessful: + let callback = DappCallback(id: callbackID, value: .walletSwitchEthereumChain) + self?.notifyFinish(callbackID: callbackID, value: .success(callback)) + case .switchBrowserToExistingServer(let server, let url): + self?.switch(toServer: server, url: url) + case .restartToEnableAndSwitchBrowserToServer: + break + } + }).store(in: &cancellable) } } // swiftlint:enable type_body_length @@ -518,7 +540,7 @@ extension DappBrowserCoordinator: BrowserViewControllerDelegate { case .walletAddEthereumChain(let customChain): requestAddCustomChain(callbackID, customChain: customChain) case .walletSwitchEthereumChain(let targetChain): - switchChain(callbackID: callbackID, targetChain: targetChain, inViewController: viewController) + switchChain(callbackID: callbackID, targetChain: targetChain) case .unknown, .sendRawTransaction: break } diff --git a/AlphaWallet/Browser/Coordinators/DappRequestSwitchCustomChainCoordinator.swift b/AlphaWallet/Browser/Coordinators/DappRequestSwitchCustomChainCoordinator.swift index bc344c7b7..11638e8ef 100644 --- a/AlphaWallet/Browser/Coordinators/DappRequestSwitchCustomChainCoordinator.swift +++ b/AlphaWallet/Browser/Coordinators/DappRequestSwitchCustomChainCoordinator.swift @@ -46,10 +46,6 @@ class DappRequestSwitchCustomChainCoordinator: NSObject, Coordinator { self.viewController = viewController } - deinit { - print("xxx.\(self).deinit") - } - func start() -> AnyPublisher { guard let customChainId = Int(chainId0xString: customChain.chainId) else { return .fail(PromiseError(error: DAppError.nodeError(R.string.localizable.addCustomChainErrorInvalidChainId(customChain.chainId)))) diff --git a/AlphaWallet/Browser/Coordinators/DappRequestSwitchExistingChainCoordinator.swift b/AlphaWallet/Browser/Coordinators/DappRequestSwitchExistingChainCoordinator.swift index b65f0891c..2473eb2ed 100644 --- a/AlphaWallet/Browser/Coordinators/DappRequestSwitchExistingChainCoordinator.swift +++ b/AlphaWallet/Browser/Coordinators/DappRequestSwitchExistingChainCoordinator.swift @@ -3,32 +3,30 @@ import UIKit import PromiseKit import AlphaWalletFoundation +import AlphaWalletCore +import Combine -protocol DappRequestSwitchExistingChainCoordinatorDelegate: AnyObject { - func notifySuccessful(withCallbackId callbackId: SwitchCustomChainCallbackId, inCoordinator coordinator: DappRequestSwitchExistingChainCoordinator) - func restartToEnableAndSwitchBrowserToServer(inCoordinator coordinator: DappRequestSwitchExistingChainCoordinator) - func switchBrowserToExistingServer(_ server: RPCServer, callbackId: SwitchCustomChainCallbackId, url: URL?, inCoordinator coordinator: DappRequestSwitchExistingChainCoordinator) - func userCancelled(withCallbackId callbackId: SwitchCustomChainCallbackId, inCoordinator coordinator: DappRequestSwitchExistingChainCoordinator) - func failed(withErrorMessage errorMessage: String, withCallbackId callbackId: SwitchCustomChainCallbackId, inCoordinator coordinator: DappRequestSwitchExistingChainCoordinator) +enum SwitchExistingChainOperation { + case notifySuccessful + case restartToEnableAndSwitchBrowserToServer + case switchBrowserToExistingServer(_ server: RPCServer, url: URL?) } class DappRequestSwitchExistingChainCoordinator: NSObject, Coordinator { private let config: Config - let server: RPCServer - let callbackId: SwitchCustomChainCallbackId + private let server: RPCServer private let targetChain: WalletSwitchEthereumChainObject private let restartQueue: RestartTaskQueue private let analytics: AnalyticsLogger private let currentUrl: URL? private let viewController: UIViewController + private let subject = PassthroughSubject() var coordinators: [Coordinator] = [] - weak var delegate: DappRequestSwitchExistingChainCoordinatorDelegate? - init(config: Config, server: RPCServer, callbackId: SwitchCustomChainCallbackId, targetChain: WalletSwitchEthereumChainObject, restartQueue: RestartTaskQueue, analytics: AnalyticsLogger, currentUrl: URL?, inViewController viewController: UIViewController) { + init(config: Config, server: RPCServer, targetChain: WalletSwitchEthereumChainObject, restartQueue: RestartTaskQueue, analytics: AnalyticsLogger, currentUrl: URL?, inViewController viewController: UIViewController) { self.config = config self.server = server - self.callbackId = callbackId self.targetChain = targetChain self.restartQueue = restartQueue self.analytics = analytics @@ -36,27 +34,29 @@ class DappRequestSwitchExistingChainCoordinator: NSObject, Coordinator { self.viewController = viewController } - func start() { + func start() -> AnyPublisher { guard let targetChainId = Int(chainId0xString: targetChain.chainId) else { - delegate?.failed(withErrorMessage: R.string.localizable.switchChainErrorInvalidChainId(targetChain.chainId), withCallbackId: callbackId, inCoordinator: self) - return + return .fail(PromiseError(error: DAppError.nodeError(R.string.localizable.switchChainErrorInvalidChainId(targetChain.chainId)))) } if let existingServer = ServersCoordinator.serversOrdered.first(where: { $0.chainID == targetChainId }) { if config.enabledServers.contains(where: { $0.chainID == targetChainId }) { if server.chainID == targetChainId { - notifySwitchChainSucceededBecauseAlreadyActive(withCallbackId: callbackId) + //This is really only (and should only be) fired when the chain is already enabled and activated in browser. i.e. we are not supposed to have restarted the app UI or browser. It's a no-op. If DApps detect that the browser is already connected to the right chain, they might not even trigger this + return .just(.notifySuccessful) } else { - promptAndSwitchToExistingServerInBrowser(existingServer: existingServer, viewController: viewController, callbackID: callbackId) + promptAndSwitchToExistingServerInBrowser(existingServer: existingServer, viewController: viewController) } } else { - promptAndActivateExistingServer(existingServer: existingServer, inViewController: viewController, callbackID: callbackId) + promptAndActivateExistingServer(existingServer: existingServer, inViewController: viewController) } } else { - delegate?.failed(withErrorMessage: R.string.localizable.switchChainErrorNotSupportedChainId(targetChain.chainId), withCallbackId: callbackId, inCoordinator: self) + return .fail(PromiseError(error: DAppError.nodeError(R.string.localizable.switchChainErrorNotSupportedChainId(targetChain.chainId)))) } + + return subject.eraseToAnyPublisher() } - private func promptAndActivateExistingServer(existingServer: RPCServer, inViewController viewController: UIViewController, callbackID: SwitchCustomChainCallbackId) { + private func promptAndActivateExistingServer(existingServer: RPCServer, inViewController viewController: UIViewController) { func runEnableChain() { let enableChain = EnableChain(existingServer, restartQueue: restartQueue, url: currentUrl) enableChain.delegate = self @@ -64,38 +64,35 @@ class DappRequestSwitchExistingChainCoordinator: NSObject, Coordinator { } let configuration: SwitchChainRequestConfiguration = .promptAndActivateExistingServer(existingServer: existingServer) - SwitchChainRequestViewController.promise(viewController, configuration: configuration).done { result in + SwitchChainRequestViewController.promise(viewController, configuration: configuration).done { [subject] result in // NOTE: here we pretty sure that there is only one action switch result { case .action: runEnableChain() case .canceled: - self.delegate?.userCancelled(withCallbackId: callbackID, inCoordinator: self) + subject.send(completion: .failure(PromiseError(error: DAppError.cancelled))) } }.cauterize() } - private func promptAndSwitchToExistingServerInBrowser(existingServer: RPCServer, viewController: UIViewController, callbackID: SwitchCustomChainCallbackId) { + private func promptAndSwitchToExistingServerInBrowser(existingServer: RPCServer, viewController: UIViewController) { let configuration: SwitchChainRequestConfiguration = .promptAndSwitchToExistingServerInBrowser(existingServer: existingServer) - SwitchChainRequestViewController.promise(viewController, configuration: configuration).done { result in + SwitchChainRequestViewController.promise(viewController, configuration: configuration).done { [subject] result in // NOTE: here we pretty sure that there is only one action switch result { case .action: - self.delegate?.switchBrowserToExistingServer(existingServer, callbackId: callbackID, url: self.currentUrl, inCoordinator: self) + subject.send(.switchBrowserToExistingServer(existingServer, url: self.currentUrl)) + subject.send(completion: .finished) case .canceled: - self.delegate?.userCancelled(withCallbackId: callbackID, inCoordinator: self) + subject.send(completion: .failure(PromiseError(error: DAppError.cancelled))) } }.cauterize() } - - //This is really only (and should only be) fired when the chain is already enabled and activated in browser. i.e. we are not supposed to have restarted the app UI or browser. It's a no-op. If DApps detect that the browser is already connected to the right chain, they might not even trigger this - private func notifySwitchChainSucceededBecauseAlreadyActive(withCallbackId callbackId: SwitchCustomChainCallbackId) { - delegate?.notifySuccessful(withCallbackId: callbackId, inCoordinator: self) - } } extension DappRequestSwitchExistingChainCoordinator: EnableChainDelegate { //Don't need to notify browser/dapp since we are restarting UI func notifyEnableChainQueuedSuccessfully(in enableChain: EnableChain) { - delegate?.restartToEnableAndSwitchBrowserToServer(inCoordinator: self) + subject.send(.restartToEnableAndSwitchBrowserToServer) + subject.send(completion: .finished) } } diff --git a/AlphaWallet/Common/Services/DappRequestHandler.swift b/AlphaWallet/Common/Services/DappRequestHandler.swift deleted file mode 100644 index 73ecfaa8a..000000000 --- a/AlphaWallet/Common/Services/DappRequestHandler.swift +++ /dev/null @@ -1,93 +0,0 @@ -// -// DappRequestHandler.swift -// AlphaWallet -// -// Created by Vladyslav Shepitko on 11.03.2022. -// - -import Foundation -import AlphaWalletFoundation - -protocol DappRequestHandlerDelegate: AnyObject { - func processRestartQueueAndRestartUI(reason: RestartReason) -} - -extension ActiveWalletCoordinator { - /// Wraps DappRequestSwitchCustomChainCoordinatorDelegate and DappRequestSwitchExistingChainCoordinatorDelegate to reduce in coordinator size - class DappRequestHandler: Coordinator { - private let walletConnectProvider: WalletConnectProvider - private var dappBrowserCoordinator: DappBrowserCoordinator - - weak var delegate: DappRequestHandlerDelegate? - var coordinators: [Coordinator] = [] - - init(walletConnectProvider: WalletConnectProvider, dappBrowserCoordinator: DappBrowserCoordinator) { - self.walletConnectProvider = walletConnectProvider - self.dappBrowserCoordinator = dappBrowserCoordinator - } - - private func processRestartQueueAndRestartUI(reason: RestartReason) { - delegate?.processRestartQueueAndRestartUI(reason: reason) - } - } -} - -extension ActiveWalletCoordinator.DappRequestHandler: DappRequestSwitchExistingChainCoordinatorDelegate { - - func notifySuccessful(withCallbackId callbackId: SwitchCustomChainCallbackId, inCoordinator coordinator: DappRequestSwitchExistingChainCoordinator) { - switch callbackId { - case .dapp(let callbackId): - let callback = DappCallback(id: callbackId, value: .walletSwitchEthereumChain) - dappBrowserCoordinator.notifyFinish(callbackID: callbackId, value: .success(callback)) - case .walletConnect(let request): - try? walletConnectProvider.respond(.value(nil), request: request) - try? walletConnectProvider.notifyUpdateServers(request: request, server: coordinator.server) - } - - removeCoordinator(coordinator) - } - - func switchBrowserToExistingServer(_ server: RPCServer, callbackId: SwitchCustomChainCallbackId, url: URL?, inCoordinator coordinator: DappRequestSwitchExistingChainCoordinator) { - dappBrowserCoordinator.switch(toServer: server, url: url) - switch callbackId { - case .dapp: - break - case .walletConnect(let request): - try? walletConnectProvider.respond(.value(nil), request: request) - try? walletConnectProvider.notifyUpdateServers(request: request, server: server) - } - removeCoordinator(coordinator) - } - - func restartToEnableAndSwitchBrowserToServer(inCoordinator coordinator: DappRequestSwitchExistingChainCoordinator) { - processRestartQueueAndRestartUI(reason: .serverChange) - switch coordinator.callbackId { - case .dapp: - break - case .walletConnect(let request): - try? walletConnectProvider.respond(.value(nil), request: request) - try? walletConnectProvider.notifyUpdateServers(request: request, server: coordinator.server) - } - removeCoordinator(coordinator) - } - func userCancelled(withCallbackId callbackId: SwitchCustomChainCallbackId, inCoordinator coordinator: DappRequestSwitchExistingChainCoordinator) { - switch callbackId { - case .dapp(let callbackId): - dappBrowserCoordinator.notifyFinish(callbackID: callbackId, value: .failure(DAppError.cancelled)) - case .walletConnect(let request): - try? walletConnectProvider.respond(.init(error: .requestRejected), request: request) - } - removeCoordinator(coordinator) - } - - func failed(withErrorMessage errorMessage: String, withCallbackId callbackId: SwitchCustomChainCallbackId, inCoordinator coordinator: DappRequestSwitchExistingChainCoordinator) { - switch callbackId { - case .dapp(let callbackId): - let error = DAppError.nodeError(errorMessage) - dappBrowserCoordinator.notifyFinish(callbackID: callbackId, value: .failure(error)) - case .walletConnect(let request): - try? walletConnectProvider.respond(.init(error: .requestRejected), request: request) - } - removeCoordinator(coordinator) - } -} diff --git a/AlphaWallet/WalletConnect/Coordinator/WalletConnectCoordinator.swift b/AlphaWallet/WalletConnect/Coordinator/WalletConnectCoordinator.swift index 357fe4afa..bcaea8909 100644 --- a/AlphaWallet/WalletConnect/Coordinator/WalletConnectCoordinator.swift +++ b/AlphaWallet/WalletConnect/Coordinator/WalletConnectCoordinator.swift @@ -20,7 +20,9 @@ protocol RequestAddCustomChainProvider: NSObjectProtocol { } protocol RequestSwitchChainProvider: NSObjectProtocol { - func requestSwitchChain(server: RPCServer, currentUrl: URL?, callbackID: SwitchCustomChainCallbackId, targetChain: WalletSwitchEthereumChainObject) + func requestSwitchChain(server: RPCServer, + currentUrl: URL?, + targetChain: WalletSwitchEthereumChainObject) -> AnyPublisher } protocol WalletConnectCoordinatorDelegate: CanOpenURL, SendTransactionAndFiatOnRampDelegate, RequestAddCustomChainProvider, RequestSwitchChainProvider { @@ -277,12 +279,11 @@ extension WalletConnectCoordinator: WalletConnectProviderDelegate { return delegate.requestAddCustomChain(server: server, customChain: customChain) } - func requestSwitchChain(server: RPCServer, currentUrl: URL?, callbackID: SwitchCustomChainCallbackId, targetChain: WalletSwitchEthereumChainObject) -> AnyPublisher { + func requestSwitchChain(server: RPCServer, currentUrl: URL?, targetChain: WalletSwitchEthereumChainObject) -> AnyPublisher { infoLog("[WalletConnect] switchChain: \(targetChain)") + guard let delegate = delegate else { return .empty() } - delegate?.requestSwitchChain(server: server, currentUrl: nil, callbackID: callbackID, targetChain: targetChain) - - return .fail(PromiseError(error: WalletConnectError.delayedOperation)) + return delegate.requestSwitchChain(server: server, currentUrl: nil, targetChain: targetChain) } private func resetSessionsToRemoveLoadingIfNeeded() { diff --git a/AlphaWallet/WalletConnect/WalletConnectProvider.swift b/AlphaWallet/WalletConnect/WalletConnectProvider.swift index 6b05d8c48..6edbc756c 100644 --- a/AlphaWallet/WalletConnect/WalletConnectProvider.swift +++ b/AlphaWallet/WalletConnect/WalletConnectProvider.swift @@ -43,8 +43,7 @@ protocol WalletConnectProviderDelegate: AnyObject { func requestSwitchChain(server: RPCServer, currentUrl: URL?, - callbackID: SwitchCustomChainCallbackId, - targetChain: WalletSwitchEthereumChainObject) -> AnyPublisher + targetChain: WalletSwitchEthereumChainObject) -> AnyPublisher func provider(_ provider: WalletConnectProvider, didFail error: WalletConnectError) func provider(_ provider: WalletConnectProvider, tookTooLongToConnectToUrl url: AlphaWallet.WalletConnect.ConnectionUrl) @@ -269,9 +268,20 @@ extension WalletConnectProvider: WalletConnectServerDelegate { return .fail(.internal(.unsupportedChain(chainId: targetChain.chainId))) } - let callbackID: SwitchCustomChainCallbackId = .walletConnect(request: request) - - return dappRequestProvider.requestSwitchChain(server: server, currentUrl: nil, callbackID: callbackID, targetChain: targetChain) + return dappRequestProvider.requestSwitchChain(server: server, currentUrl: nil, targetChain: targetChain) + .map { [weak self] operation -> AlphaWallet.WalletConnect.Response in + switch operation { + case .notifySuccessful: + try? self?.notifyUpdateServers(request: request, server: server) + return .init(data: nil) + case .restartToEnableAndSwitchBrowserToServer: + try? self?.notifyUpdateServers(request: request, server: server) + return .init(data: nil) + case .switchBrowserToExistingServer: + try? self?.notifyUpdateServers(request: request, server: server) + return .init(data: nil) + } + } .mapError { WalletConnectError(error: $0) } .eraseToAnyPublisher() }