Files
raspberry/iOS/Wallet/Sources/Resources/Service/Setup/ResourcesServiceSetupPerformance.swift

205 lines
7.5 KiB
Swift

//
// ResourcesServiceSetupPerformance.swift
// Wallet
//
// Created by Igor Danich on 19.08.2020.
// Copyright © 2020 List. All rights reserved.
//
import Foundation
extension Resources.Service.Setup {
class Performance: Common.Service.Provider {
let performance: Resources.Service.Performance
private let _staked: Resources.Service.Staked
var title: String {
let cpu = Resources.Model.Performance.Kind.cpu
let net = Resources.Model.Performance.Kind.net
return net.prefix.isEmpty ? "\(cpu.name)/\(net.name)" : "\(cpu.prefix)/\(net.prefix) (\(cpu.name)/\(net.name))"
}
enum Action: String, CommonMenuMappable {
case stake
case unstake
var title: String { "resources.setup.action.\(rawValue)".localized }
func toMenu() -> Common.Model.Menu { .menu(uuid: rawValue, title: title) }
}
let actions: [Action] = [.stake, .unstake]
private var _action: Action?
var action: Action? {
get { _action }
set { _action = newValue;clear() }
}
private var _isOtherEnabled = false
var isOtherEnabled: Bool {
get { _isOtherEnabled }
set {
_isOtherEnabled = newValue
_otherAccount = ""
transfer = false
update()
}
}
private var _otherAccount = ""
var otherAccount: String {
get { _otherAccount }
set { _otherAccount = newValue;update() }
}
var transfer = false
private(set) var submitText: String?
private var _netAmount = ""
var netAmount: String {
get { _netAmount }
set { _netAmount = newValue;update() }
}
private var _cpuAmount = ""
var cpuAmount: String {
get { _cpuAmount }
set { _cpuAmount = newValue;update() }
}
private(set) var isValid = false
var balance: Decimal {
Wallet.Service.Tokens.shared.balances.collection.first(where: {
$0.contract == ApplicationEnvironment.shared().current.contract(.eosioToken) && $0.symbol.uppercased() == "EOS"
})?.amount ?? 0
}
var balanceText: String {
Wallet.Service.Tokens.shared.balances.collection.first(where: {
$0.contract == ApplicationEnvironment.shared().current.contract(.eosioToken) && $0.symbol.uppercased() == "EOS"
})?.description ?? ""
}
init(account: String) {
_staked = .init(account: account)
performance = .init(account: account)
}
var didUpdate: (() -> Void)?
var didReload: (() -> Void)?
func clear(force: Bool = false) {
if force {
_action = nil
performance.clear()
}
_isOtherEnabled = false
_otherAccount = ""
transfer = false
_cpuAmount = ""
_netAmount = ""
isValid = false
submitText = ""
didReload?()
update()
}
func fetch() {
performance.fetch { _ in
self._staked.fetch { _ in
self.didReload?()
self.update()
}
}
}
var staked: [Resources.Model.Staked] { _staked.collection }
private func update() {
let value = netAmount.toDecimal() + cpuAmount.toDecimal()
let string = value.toString(max: 4, symbol: "EOS")
let isAvailable = action == .stake ? self.balance >= value : getSumUnstakeAmount() >= value
if let action = action {
isValid = isOtherEnabled ? (!otherAccount.isEmpty && value > 0 && isAvailable) : (value > 0 && isAvailable)
submitText = action == .stake ? L10n.Resources.Setup.Submit.stake(string) : L10n.Resources.Setup.Submit.unstake(string)
} else {
isValid = false
submitText = ""
}
didUpdate?()
}
func getSumUnstakeAmount() -> Decimal {
if isOtherEnabled {
return staked.map { $0.cpu_weight.toDecimal() }.reduce(0, +) + staked.map { $0.net_weight.toDecimal() }.reduce(0, +)
} else {
return performance[.cpu].stakedByMe.toDecimal() + performance[.net].stakedByMe.toDecimal()
}
}
func getAvailableUnstakeAmount(isCpu: Bool) -> Decimal {
if isOtherEnabled {
return isCpu ? staked.map { $0.cpu_weight.toDecimal() }.reduce(0, +) :
staked.map { $0.net_weight.toDecimal() }.reduce(0, +)
} else {
return isCpu ? performance[.cpu].stakedByMe.toDecimal() :
performance[.net].stakedByMe.toDecimal()
}
}
func refund(privateKey: String, _ completion: @escaping (NSError?) -> Void) {
Network.Service.Blockchain.execute(contract: .eosio, action: .refund, data: [
"owner" : performance.account
], privateKeys: [privateKey]) { (result) in
completion(.error(result))
}
}
// swiftlint:disable identifier_name
private struct StakeRequest: Codable {
let from: String
let receiver: String
let stake_net_quantity: String
let stake_cpu_quantity: String
let transfer: Bool
}
// swiftlint:disable identifier_name
private struct UnstakeRequest: Codable {
let from: String
let receiver: String
let unstake_net_quantity: String
let unstake_cpu_quantity: String
}
func submit(privateKey: String, _ completion: @escaping Completion.Network) {
guard let action = action, isValid else { return }
switch action {
case .stake:
Network.Service.Blockchain.execute(
contract: .eosio,
action: .delegatebw,
data: StakeRequest(
from: performance.account,
receiver: isOtherEnabled ? otherAccount : performance.account,
stake_net_quantity: netAmount.toDecimal().toString(precision: .eosioToken),
stake_cpu_quantity: cpuAmount.toDecimal().toString(precision: .eosioToken),
transfer: isOtherEnabled ? transfer : false
), privateKeys: [privateKey]
) { (result) in
completion(.error(result))
}
case .unstake:
Network.Service.Blockchain.execute(
contract: .eosio,
action: .undelegatebw,
data: UnstakeRequest(
from: performance.account,
receiver: isOtherEnabled ? otherAccount : performance.account,
unstake_net_quantity: netAmount.toDecimal().toString(precision: .eosioToken),
unstake_cpu_quantity: cpuAmount.toDecimal().toString(precision: .eosioToken)
), privateKeys: [privateKey]
) { (result) in
completion(.error(result))
}
}
}
}
}