An advanced Ethereum/EVM mobile wallet
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
alpha-wallet-ios/Trust/InCoordinator.swift

280 lines
10 KiB

// Copyright SIX DAY LLC. All rights reserved.
import Foundation
import TrustKeystore
import UIKit
import RealmSwift
protocol InCoordinatorDelegate: class {
func didCancel(in coordinator: InCoordinator)
func didUpdateAccounts(in coordinator: InCoordinator)
}
enum InCoordinatorError: LocalizedError {
case onlyWatchAccount
var errorDescription: String? {
return NSLocalizedString(
"InCoordinatorError.onlyWatchAccount",
value: "This wallet could be only used for watching. Import Private Key/Keystore to sign transactions",
comment: ""
)
}
}
class InCoordinator: Coordinator {
let navigationController: UINavigationController
var coordinators: [Coordinator] = []
let initialWallet: Wallet
var keystore: Keystore
var config: Config
let appTracker: AppTracker
weak var delegate: InCoordinatorDelegate?
var transactionCoordinator: TransactionCoordinator? {
return self.coordinators.flatMap { $0 as? TransactionCoordinator }.first
}
lazy var helpUsCoordinator: HelpUsCoordinator = {
return HelpUsCoordinator(
navigationController: navigationController,
appTracker: appTracker
)
}()
init(
navigationController: UINavigationController = NavigationController(),
wallet: Wallet,
keystore: Keystore,
config: Config = Config(),
appTracker: AppTracker = AppTracker()
) {
self.navigationController = navigationController
self.initialWallet = wallet
self.keystore = keystore
self.config = config
self.appTracker = appTracker
}
func start() {
showTabBar(for: initialWallet)
checkDevice()
helpUsCoordinator.start()
addCoordinator(helpUsCoordinator)
}
func showTabBar(for account: Wallet) {
let migration = MigrationInitializer(account: account, chainID: config.chainID)
migration.perform()
let web3 = self.web3(for: config.server)
let realm = self.realm(for: migration.config)
let tokensStorage = TokensDataStore(realm: realm, account: account, config: config, web3: web3)
let balance = BalanceCoordinator(account: account, storage: tokensStorage)
let session = WalletSession(
account: account,
config: config,
web3: web3,
balanceCoordinator: balance
)
let transactionsStorage = TransactionsStorage(
realm: realm
)
let inCoordinatorViewModel = InCoordinatorViewModel(config: config)
let transactionCoordinator = TransactionCoordinator(
session: session,
storage: transactionsStorage,
keystore: keystore,
tokensStorage: tokensStorage
)
transactionCoordinator.rootViewController.tabBarItem = UITabBarItem(title: NSLocalizedString("transactions.tabbar.item.title", value: "Transactions", comment: ""), image: R.image.feed(), selectedImage: nil)
transactionCoordinator.delegate = self
transactionCoordinator.start()
addCoordinator(transactionCoordinator)
let tabBarController = TabBarController()
tabBarController.viewControllers = [
transactionCoordinator.navigationController,
]
tabBarController.tabBar.isTranslucent = false
tabBarController.didShake = { [weak self] in
if inCoordinatorViewModel.canActivateDebugMode {
self?.activateDebug()
}
}
if inCoordinatorViewModel.browserAvailable {
let coordinator = BrowserCoordinator(session: session, keystore: keystore)
coordinator.delegate = self
coordinator.start()
coordinator.rootViewController.tabBarItem = UITabBarItem(
title: NSLocalizedString("browser.tabbar.item.title", value: "Browser", comment: ""),
image: R.image.coins(),
selectedImage: nil
)
addCoordinator(coordinator)
tabBarController.viewControllers?.insert(coordinator.navigationController, at: 0)
}
if inCoordinatorViewModel.tokensAvailable {
let tokenCoordinator = TokensCoordinator(
session: session,
keystore: keystore,
tokensStorage: tokensStorage
)
tokenCoordinator.rootViewController.tabBarItem = UITabBarItem(title: NSLocalizedString("tokens.tabbar.item.title", value: "Tokens", comment: ""), image: R.image.coins(), selectedImage: nil)
tokenCoordinator.delegate = self
tokenCoordinator.start()
addCoordinator(tokenCoordinator)
tabBarController.viewControllers?.append(tokenCoordinator.navigationController)
}
if inCoordinatorViewModel.exchangeAvailable {
let exchangeCoordinator = ExchangeCoordinator(session: session, keystore: keystore)
exchangeCoordinator.rootViewController.tabBarItem = UITabBarItem(title: NSLocalizedString("exchange.tabbar.item.title", value: "Exchange", comment: ""), image: R.image.exchange(), selectedImage: nil)
exchangeCoordinator.start()
addCoordinator(exchangeCoordinator)
tabBarController.viewControllers?.append(exchangeCoordinator.navigationController)
}
let settingsCoordinator = SettingsCoordinator(
keystore: keystore,
session: session,
storage: transactionsStorage
)
settingsCoordinator.rootViewController.tabBarItem = UITabBarItem(
title: NSLocalizedString("settings.navigation.title", value: "Settings", comment: ""),
image: R.image.settings_icon(),
selectedImage: nil
)
settingsCoordinator.delegate = self
settingsCoordinator.start()
addCoordinator(settingsCoordinator)
tabBarController.viewControllers?.append(settingsCoordinator.navigationController)
navigationController.setViewControllers(
[tabBarController],
animated: false
)
navigationController.setNavigationBarHidden(true, animated: false)
addCoordinator(transactionCoordinator)
// let coor = SignMessageCoordinator(navigationController: navigationController, keystore: keystore, account: Account(address: account.address))
// coor.start(with: "Hello")
keystore.recentlyUsedWallet = account
}
@objc func activateDebug() {
config.isDebugEnabled = !config.isDebugEnabled
guard let transactionCoordinator = transactionCoordinator else { return }
restart(for: transactionCoordinator.session.account, in: transactionCoordinator)
}
func restart(for account: Wallet, in coordinator: TransactionCoordinator) {
coordinator.navigationController.dismiss(animated: true, completion: nil)
coordinator.stop()
removeAllCoordinators()
showTabBar(for: account)
}
func checkDevice() {
let deviceChecker = CheckDeviceCoordinator(
navigationController: navigationController,
jailbreakChecker: DeviceChecker()
)
deviceChecker.start()
addCoordinator(deviceChecker)
}
func showPaymentFlow(for type: PaymentFlow) {
guard let transactionCoordinator = transactionCoordinator else { return }
let session = transactionCoordinator.session
let tokenStorage = transactionCoordinator.tokensStorage
switch session.account.type {
case .real(let account):
let coordinator = PaymentCoordinator(
flow: type,
session: session,
keystore: keystore,
storage: tokenStorage,
account: account
)
coordinator.delegate = self
navigationController.present(coordinator.navigationController, animated: true, completion: nil)
coordinator.start()
addCoordinator(coordinator)
case .watch: break
}
}
private func handlePendingTransaction(transaction: SentTransaction) {
transactionCoordinator?.dataCoordinator.add(transaction: transaction)
}
private func realm(for config: Realm.Configuration) -> Realm {
return try! Realm(configuration: config)
}
private func web3(for server: RPCServer) -> Web3Swift {
return Web3Swift(url: config.rpcURL)
}
}
extension InCoordinator: TransactionCoordinatorDelegate {
func didPress(for type: PaymentFlow, in coordinator: TransactionCoordinator) {
showPaymentFlow(for: type)
}
func didCancel(in coordinator: TransactionCoordinator) {
delegate?.didCancel(in: self)
coordinator.navigationController.dismiss(animated: true, completion: nil)
coordinator.stop()
removeAllCoordinators()
}
}
extension InCoordinator: SettingsCoordinatorDelegate {
func didCancel(in coordinator: SettingsCoordinator) {
removeCoordinator(coordinator)
coordinator.navigationController.dismiss(animated: true, completion: nil)
delegate?.didCancel(in: self)
}
func didRestart(with account: Wallet, in coordinator: SettingsCoordinator) {
guard let transactionCoordinator = transactionCoordinator else { return }
restart(for: account, in: transactionCoordinator)
}
func didUpdateAccounts(in coordinator: SettingsCoordinator) {
delegate?.didUpdateAccounts(in: self)
}
}
extension InCoordinator: TokensCoordinatorDelegate {
func didPress(for type: PaymentFlow, in coordinator: TokensCoordinator) {
showPaymentFlow(for: type)
}
}
extension InCoordinator: PaymentCoordinatorDelegate {
func didCreatePendingTransaction(transaction: SentTransaction, in coordinator: PaymentCoordinator) {
handlePendingTransaction(transaction: transaction)
}
func didCancel(in coordinator: PaymentCoordinator) {
coordinator.navigationController.dismiss(animated: true, completion: nil)
removeCoordinator(coordinator)
}
}
extension InCoordinator: BrowserCoordinatorDelegate {
func didSentTransaction(transaction: SentTransaction, in coordinator: BrowserCoordinator) {
handlePendingTransaction(transaction: transaction)
}
}