382 lines
15 KiB
Swift
382 lines
15 KiB
Swift
//
|
|
// ExchangeCryptocashViewController.swift
|
|
// PayCash
|
|
//
|
|
// Created by Saveliy Stavitsky on 9/3/22.
|
|
// Copyright © 2022 AM. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
final class ExchangeCryptocashViewController: UIViewController {
|
|
|
|
typealias FetchCompletion = () -> Void
|
|
|
|
private var tokenUSDT = Network.Model.Token(
|
|
symbol: "USDT", precision: 4, amount: 100, contract: ""
|
|
)
|
|
|
|
private var tokenOut = Network.Model.Token(
|
|
symbol: "USDCASH", precision: 5, amount: 100, contract: ApplicationEnvironment.shared().current.contract(.cash)
|
|
)
|
|
|
|
private var p2pTokenscollection = [Network.Model.Token]()
|
|
private var walletP2pTokenscollection: [Network.Model.Token] {
|
|
self.p2pTokenscollection.compactMap { Wallet.Service.Tokens.shared.balances.collection.first($0) }
|
|
}
|
|
|
|
private var selectedToken: Network.Model.Token? {
|
|
didSet {
|
|
self.amountTextField.isHidden = !self.selectedToken.isExist
|
|
|
|
let messages = [
|
|
L10n.ExchangeCryptocashViewController.Amount.error2,
|
|
L10n.ExchangeCryptocashViewController.Amount.error3
|
|
]
|
|
|
|
if messages.contains(where: { $0 == self.amountTextField.error }) {
|
|
self.amountTextField.error = nil
|
|
}
|
|
|
|
self.view.endEditing(true)
|
|
self.amountTextField.value = ""
|
|
self.infoAmountsStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
|
|
|
|
if let selectedToken = self.selectedToken {
|
|
|
|
self.amountTextField.lzText = L10n.ExchangeCryptocashViewController.Amount.info
|
|
+ (p2pTokenscollection.first(selectedToken)?.certCoef ?? 0)
|
|
.toReadebleString(precisionMax: selectedToken.precision, symbol: selectedToken.symbol, group: true)
|
|
|
|
let lImage = UIImageView(token: selectedToken)
|
|
lImage.addHeightWidthConstraints(height: 24, width: 24)
|
|
self.amountTextField.accessoryView = lImage
|
|
self.amountTextField.precision = selectedToken.precision
|
|
|
|
self.amountTextField.becomeFirstResponder()
|
|
}
|
|
}
|
|
}
|
|
|
|
private var deposits = [Deposit]()
|
|
private func calcMLNKViaDeposits(amount: Decimal) -> Decimal {
|
|
var tempAmount = amount * tokenUSDT.amount
|
|
var tempMLNK = Decimal(0)
|
|
for deposit in deposits {
|
|
if tempAmount <= 0 {
|
|
break
|
|
}
|
|
if deposit.usdt_in.amount.toDecimal() <= tempAmount {
|
|
tempMLNK += deposit.mlnk_in.amount.toDecimal()
|
|
tempAmount -= deposit.usdt_in.amount.toDecimal()
|
|
} else {
|
|
tempMLNK += tempAmount * (deposit.mlnk_in.amount.toDecimal() / deposit.usdt_in.amount.toDecimal())
|
|
tempAmount -= tempAmount
|
|
}
|
|
}
|
|
return tempMLNK
|
|
}
|
|
|
|
@IBOutlet private weak var tokeGiveView: CommonViewCard!
|
|
@IBOutlet private weak var explanationStackView: UIStackView!
|
|
@IBOutlet private weak var amountTextField: CommonTextField!
|
|
@IBOutlet private weak var infoAmountsStackView: UIStackView!
|
|
@IBOutlet private weak var warningView: CommonViewWarning!
|
|
|
|
@IBOutlet var swapButton: CommonButtonAction!
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
self.title = L10n.ExchangeCryptocashViewController.title
|
|
self.navigationItem.leftBarButtonItem = .pop(self)
|
|
|
|
for textField in [self.amountTextField] {
|
|
textField?.delegate = self
|
|
textField?.keyboardType = .decimalPad
|
|
}
|
|
self.amountTextField.lzPlaceholder = L10n.ExchangeCryptocashViewController.Amount.placeholder
|
|
self.amountTextField.lzTitle = L10n.ExchangeCryptocashViewController.Amount.title
|
|
|
|
self.swapButton.isEnabled = false
|
|
self.swapButton.isUserInteractionEnabled = false
|
|
|
|
self.warningView.lzText = L10n.ExchangeCryptocashViewController.warning
|
|
}
|
|
|
|
override func viewWillAppear(_ animated: Bool) {
|
|
super.viewWillAppear(animated)
|
|
Accounts().isLocked = true
|
|
|
|
self.fetchData(animated)
|
|
}
|
|
|
|
private func fetchData(_ animated: Bool) {
|
|
|
|
self.fetchSwap {
|
|
self.fetchSwapBack(animated: animated) { [weak self] in
|
|
self?.fetchDeposit(animated: animated)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func fetchSwap(_ completion: @escaping FetchCompletion) {
|
|
|
|
struct Income: Codable {
|
|
let income: Network.Model.TokenSmall
|
|
}
|
|
|
|
Network.table.fetch(
|
|
code: ApplicationEnvironment.shared().current.contract(.cash),
|
|
table: "swap1",
|
|
scope: ApplicationEnvironment.shared().current.contract(.cash),
|
|
type: Income.self
|
|
) { [weak self] in
|
|
if let token = $0.map({ $0.income }).first?.asToken {
|
|
self?.tokenUSDT = token
|
|
}
|
|
|
|
completion()
|
|
}
|
|
|
|
}
|
|
|
|
private func fetchSwapBack(animated: Bool, _ completion: @escaping FetchCompletion) {
|
|
|
|
struct CashToken: Codable {
|
|
private let cash: String
|
|
|
|
var symbol: String { String(cash.split(separator: " ").last!) }
|
|
var precision: Int { cash.amount.precision }
|
|
var coef: Decimal { cash.amount.toDecimal() }
|
|
|
|
func asNetworkToken() -> Network.Model.Token {
|
|
.init(symbol: symbol,
|
|
precision: precision,
|
|
amount: 0,
|
|
contract: ApplicationEnvironment.shared().current.contract(.cash),
|
|
certCoef: coef,
|
|
certName: "")
|
|
}
|
|
}
|
|
|
|
Network.table.fetch(
|
|
code: ApplicationEnvironment.shared().current.contract(.cash),
|
|
table: "swapback",
|
|
scope: ApplicationEnvironment.shared().current.contract(.cash),
|
|
type: CashToken.self) { [weak self] rows in
|
|
guard let self = self else { return }
|
|
self.p2pTokenscollection = rows.map({ $0.asNetworkToken() })
|
|
if !self.p2pTokenscollection.isEmpty {
|
|
self.tokeGiveView.action = .cards(
|
|
tokens: self.walletP2pTokenscollection,
|
|
selected: self.selectedToken,
|
|
empty: .menu(
|
|
image: Asset.commonToken.image.tinted(with: Asset.deepWater.color),
|
|
title: L10n.ExchangeCryptocashViewController.Cryptocash.placeholder
|
|
),
|
|
title: L10n.ExchangeCryptocashViewController.Cryptocash.placeholder, {
|
|
self.selectedToken = self.walletP2pTokenscollection.object(menu: $0)
|
|
}
|
|
)
|
|
} else {
|
|
self.navigationController?.popViewController(animated: animated)
|
|
}
|
|
|
|
completion()
|
|
}
|
|
|
|
}
|
|
|
|
private func fetchDeposit(animated: Bool) {
|
|
|
|
Network.table.fetch(
|
|
code: ApplicationEnvironment.shared().current.contract(.cash),
|
|
table: "deposits",
|
|
scope: ApplicationEnvironment.shared().current.contract(.cash),
|
|
keyType: "i128",
|
|
indexPosition: "2",
|
|
type: Deposit.self
|
|
) { [weak self] deposits in
|
|
self?.deposits = deposits
|
|
if deposits.isEmpty {
|
|
self?.navigationController?.popViewController(animated: animated)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
override func viewWillDisappear(_ animated: Bool) {
|
|
super.viewWillDisappear(animated)
|
|
Accounts().isLocked = false
|
|
}
|
|
|
|
@IBAction private func onAccountType(_ : AnyObject?) {
|
|
guard let selectedToken = self.selectedToken,
|
|
let coef = p2pTokenscollection.first(selectedToken)?.certCoef,
|
|
amountTextField.value.toDecimal() / coef == (amountTextField.value.toDecimal() / coef).roundUp(to: 0),
|
|
amountTextField.value.toDecimal() > 0 else {
|
|
return
|
|
}
|
|
infoAmountsStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
|
|
|
|
if let coef = p2pTokenscollection.first(selectedToken)?.certCoef {
|
|
infoAmountsStackView.insertArrangedSubview(
|
|
.field(
|
|
title: L10n.ExchangeCryptocashViewController.Get.title,
|
|
text: (tokenUSDT.amount * (amountTextField.value.toDecimal() / coef)).toString(max: tokenUSDT)
|
|
), at: 0)
|
|
|
|
infoAmountsStackView.insertArrangedSubview(
|
|
.field(
|
|
title: L10n.ExchangeCryptocashViewController.Return.title,
|
|
text: amountTextField.value.toDecimal().toString(max: selectedToken)
|
|
), at: 0)
|
|
}
|
|
}
|
|
|
|
@IBAction func swapPressed(_ sender: Any) {
|
|
view.endEditing(true)
|
|
|
|
guard let selectedToken = self.selectedToken, let coef = p2pTokenscollection.first(selectedToken)?.certCoef else {
|
|
return
|
|
}
|
|
|
|
let views: [UIView] = [
|
|
.field(
|
|
title: L10n.ExchangeCryptocashViewController.Popup1.title1,
|
|
text: amountTextField.value.toDecimal().toString(max: selectedToken)
|
|
),
|
|
.field(
|
|
title: L10n.ExchangeCryptocashViewController.Popup1.title2,
|
|
text: (tokenUSDT.amount * (amountTextField.value.toDecimal() / coef)).toString(max: tokenUSDT)
|
|
)
|
|
]
|
|
Popup.show(title: L10n.ExchangeCryptocashViewController.Popup1.title, views: views, submit: L10n.Common.Button.confirm, in: self) { ctrl in
|
|
AccountViewAuthorize.showGetPrivateKey(in: self) { privateKey in
|
|
Loader.show(in: ctrl)
|
|
|
|
var actions = [(contract: String, action: Network.Model.Blockchain.Action, data: Codable)]()
|
|
|
|
let returnToken = self.tokenUSDT
|
|
if !Wallet.Service.Tokens.shared.balances.collection.contains(returnToken) {
|
|
actions.append(
|
|
(contract: returnToken.contract,
|
|
action: .open,
|
|
data: [
|
|
"owner": Accounts().current?.name ?? "",
|
|
"symbol": "\(returnToken.precision),\(returnToken.symbol)",
|
|
"ram_payer": Accounts().current?.name ?? ""
|
|
])
|
|
)
|
|
}
|
|
|
|
actions.append(
|
|
(contract: selectedToken.contract,
|
|
action: .transfer,
|
|
data: [
|
|
"from": Accounts().current?.name ?? "",
|
|
"to": ApplicationEnvironment.shared().current.contract(.cash),
|
|
"quantity": "\(self.amountTextField.value.toDecimal().toString(precision: selectedToken))",
|
|
"memo": returnToken.symbol.lowercased()
|
|
]))
|
|
Network.Service.Blockchain.execute(actions: actions, privateKeys: [privateKey]) { (result) in
|
|
ctrl.dismiss(animated: true)
|
|
|
|
if case let .success(trxId) = result {
|
|
self.showCompletion(transactionId: trxId)
|
|
delayed(3) { Wallet.Service.Tokens.shared.balances.fetch() }
|
|
} else {
|
|
Alert.notify(result.error)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func showCompletion(transactionId: String) {
|
|
guard let selectedToken = self.selectedToken, let coef = p2pTokenscollection.first(selectedToken)?.certCoef else {
|
|
return
|
|
}
|
|
|
|
let views: [UIView] = [
|
|
.field(
|
|
title: L10n.ExchangeCryptocashViewController.Popup2.title1,
|
|
text: amountTextField.value.toDecimal().toString(max: selectedToken)
|
|
),
|
|
.field(
|
|
title: L10n.ExchangeCryptocashViewController.Popup2.title2,
|
|
text: (tokenUSDT.amount * (amountTextField.value.toDecimal() / coef)).toString(max: tokenUSDT)
|
|
),
|
|
.field(
|
|
title: L10n.Wallet.History.Details.id,
|
|
text: transactionId,
|
|
rightButtonAvailbale: true,
|
|
rightButtonImage: Asset.commonCopy.image,
|
|
rightButtonAction: {
|
|
Alert.copy(transactionId)
|
|
}
|
|
)
|
|
]
|
|
Popup.show(title: L10n.ExchangeCryptocashViewController.Popup2.title, views: views,
|
|
submit: L10n.Common.Button.checkOnBloksIO, submitStyle: .outline,
|
|
cancel: L10n.Common.Button.done, in: self, { ctrl in
|
|
guard let checkTransactionUrl = URL(transactionId: transactionId) else { return }
|
|
|
|
UIApplication.shared.open(checkTransactionUrl, options: [:], completionHandler: nil)
|
|
}, {
|
|
self.navigationController?.popViewController(animated: true)
|
|
})
|
|
}
|
|
|
|
}
|
|
|
|
extension ExchangeCryptocashViewController: CommonTextFieldDelegate {
|
|
|
|
func textFieldDidChange(_ textField: CommonTextField) {
|
|
switch textField {
|
|
|
|
case amountTextField:
|
|
textField.value = textField.value.replacingOccurrences(of: ",", with: ".")
|
|
let newPosition = textField.textField.endOfDocument
|
|
textField.textField.selectedTextRange = textField.textField.textRange(from: newPosition, to: newPosition)
|
|
|
|
infoAmountsStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
|
|
if let selectedToken = self.selectedToken,
|
|
let coef = p2pTokenscollection.first(selectedToken)?.certCoef,
|
|
amountTextField.value.toDecimal() / coef == (amountTextField.value.toDecimal() / coef).roundUp(to: 0),
|
|
amountTextField.value.toDecimal() > (selectedToken.symbol.uppercased() == "USDCASH" ? 9999 : 0),
|
|
amountTextField.value.toDecimal() <= selectedToken.amount {
|
|
swapButton.isEnabled = true
|
|
swapButton.isUserInteractionEnabled = true
|
|
|
|
infoAmountsStackView.insertArrangedSubview(
|
|
.field(
|
|
title: L10n.ExchangeCryptocashViewController.Get.title,
|
|
text: (tokenUSDT.amount * (amountTextField.value.toDecimal() / coef)).toString(max: tokenUSDT)
|
|
), at: 0)
|
|
|
|
infoAmountsStackView.insertArrangedSubview(
|
|
.field(
|
|
title: L10n.ExchangeCryptocashViewController.Return.title,
|
|
text: amountTextField.value.toDecimal().toString(max: selectedToken)
|
|
), at: 0)
|
|
} else {
|
|
swapButton.isEnabled = false
|
|
swapButton.isUserInteractionEnabled = false
|
|
|
|
if (selectedToken?.amount ?? 0) < amountTextField.value.toDecimal() {
|
|
amountTextField.error = L10n.ExchangeCryptocashViewController.Amount.error3
|
|
} else if amountTextField.value.toDecimal() > 0 {
|
|
amountTextField.error = amountTextField.lzText
|
|
} else {
|
|
amountTextField.error = nil
|
|
}
|
|
}
|
|
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
}
|