// // AccountControllerOnboardingChangeKey.swift // PayCash // // Created by Alexandr Serpokrylow on 16.02.2022. // Copyright © 2022 AM. All rights reserved. // import UIKit import EosioSwift class AccountControllerChangeKey: UIViewController { @IBOutlet weak var accountsLabel: UILabel! @IBOutlet weak var canChangeLabel: UILabel! @IBOutlet weak var tableView: UITableView! @IBOutlet weak var confirmButton: CommonButtonAction! private let service = Account.Service.ChangeKey() private var accounts = [Account.Model.ChangeKey]() var privateKey = "" var account: Account.Model? override func viewDidLoad() { super.viewDidLoad() title = L10n.Account.Onboarding.Changing.Private.key if navigationController != nil { navigationItem.leftBarButtonItem = .back({ self.dismiss(animated: true) }) navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) navigationController?.navigationBar.shadowImage = UIImage() navigationController?.navigationBar.isTranslucent = true } configureView() } private func configureView() { guard let account = account else { return } Loader.show() service.fetch(privateKey: privateKey, keyType: account.keyType, { _ in Loader.hide() self.accounts = self.service.accounts self.configureAccountView() self.tableView.reloadData() }) configureChangeLabel(account: account) tableView.delegate = self tableView.dataSource = self tableView.register(cell: ChangeKeyCell.self) } private func configureAccountView() { let attributedString = NSMutableAttributedString(string: "") for (index, account) in accounts.enumerated() { let divider = index != accounts.count - 1 ? "\n" : "" let string: NSMutableAttributedString = NSMutableAttributedString(string: "\(account.username)@\(account.permission.permName)\(divider)") string.setColor(color: Asset.coal.color, forText: account.username) string.setColor(color: Asset.pebble.color, forText: "@\(account.permission.permName)") string.setFont(font: UIFont.font(style: .medium, size: 14), forText: account.username) string.setFont(font: UIFont.font(style: .regular, size: 14), forText: "@\(account.permission.permName)") attributedString.append(string) } let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 8 attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, attributedString.length)) accountsLabel.attributedText = attributedString } private func configureChangeLabel(account: Account.Model) { let avaialableKeys = account.keyType == Account.KeyType.owner ? "\(Account.KeyType.owner.rawValue), \(Account.KeyType.active.rawValue)" : Account.KeyType.active.rawValue let attributedString = NSMutableAttributedString(string: "\(L10n.Account.Onboarding.Can.change)\(avaialableKeys)") attributedString.setFont(font: UIFont.font(style: .regular, size: 14), forText: L10n.Account.Onboarding.Can.change) attributedString.setFont(font: UIFont.font(style: .medium, size: 14), forText: avaialableKeys) canChangeLabel.attributedText = attributedString } private func checkButtonState() { let keysValid = !accounts.contains(where: { $0.hasError }) let hasChecked = accounts.contains(where: { $0.isChecked }) confirmButton.isEnabled = keysValid && hasChecked } func validateKeyPair(for cell: ChangeKeyCell, row: Int, privateKey: String, publicKey: String) { let isValidPrivateKey = privateKey.count == Constants.maxPrivateKeyTextCount ? self.service.validatePrivateKey(privateKey: privateKey) : false let isValidPublicKey = publicKey.count == Constants.maxPublicKeyTextCount ? self.service.validatePrivateKey(privateKey: privateKey) : false if (isValidPrivateKey && isValidPublicKey) { let isValidKeyPair = self.service.validateKeyPair(privateKey: privateKey, publicKey: publicKey) if isValidKeyPair { cell.configureError(for: cell.privateKeyTextField, errorMessage: nil) cell.configureError(for: cell.publicKeyTextField, errorMessage: nil) accounts[row].privateKey = privateKey accounts[row].publicKey = publicKey accounts[row].hasError = false } else { cell.configureError(for: cell.privateKeyTextField, errorMessage: L10n.Error.Accounts.keyPairInvalid) cell.configureError(for: cell.publicKeyTextField, errorMessage: L10n.Error.Accounts.keyPairInvalid) accounts[row].hasError = true } } else if (!isValidPrivateKey) { cell.configureError(for: cell.privateKeyTextField, errorMessage: L10n.Error.Accounts.keyInvalid) accounts[row].hasError = true } else if (!isValidPublicKey) { cell.configureError(for: cell.publicKeyTextField, errorMessage: L10n.Error.Accounts.publicKeyInvalid) accounts[row].hasError = true } checkButtonState() } @IBAction func onConfirmClicked(_ sender: Any) { let ctrl = StoryboardScene.Account.confirmChangeKey.instantiate() ctrl.collection = accounts.filter({ $0.isChecked }) ctrl.privateKey = privateKey ctrl.changeKeyHasBeenProcessed = { self.dismiss(animated: true) } self.navigationController?.pushViewController(ctrl, animated: true) } } extension AccountControllerChangeKey: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return accounts.count } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return UITableView.automaticDimension } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(ChangeKeyCell.self, indexPath: indexPath) let account = accounts[indexPath.row] cell.configureView(account: account) cell.onCheckboxClicked = { self.accounts[indexPath.row].isChecked = !self.accounts[indexPath.row].isChecked tableView.reloadRows(at: [indexPath], with: .automatic) self.checkButtonState() } cell.onGenerateNewKeysClicked = { guard let newPrivateKey = try? EOSPrivateKey() else { return } self.accounts[indexPath.row].privateKey = newPrivateKey.base58 self.accounts[indexPath.row].publicKey = newPrivateKey.publicKey.base58 tableView.reloadRows(at: [indexPath], with: .automatic) cell.configureError(for: cell.privateKeyTextField, errorMessage: nil) cell.configureError(for: cell.publicKeyTextField, errorMessage: nil) self.checkButtonState() } cell.onValidateKeyPair = { privateKey, publicKey in self.validateKeyPair(for: cell, row: indexPath.row, privateKey: privateKey, publicKey: publicKey) } return cell } } extension AccountControllerChangeKey { enum Constants { static let maxPrivateKeyTextCount = 51 static let maxPublicKeyTextCount = 53 } }