Files
2023-01-23 12:50:29 +03:00

257 lines
9.2 KiB
Swift

//
// NetworkModelToken.swift
// Wallet
//
// Created by Igor on 04.11.2020.
// Copyright © 2020 List. All rights reserved.
//
import UIKit
extension Network.Model {
struct TokenSmall: Codable {
let quantity: String
let contract: String
var asToken: Token? {
if !contract.isEmpty, !quantity.symbol.isEmpty {
return Token(
symbol: quantity.symbol,
precision: quantity.precision,
amount: quantity.amount.toDecimal(),
contract: contract,
certCoef: 0,
certName: "",
city: nil,
country: nil
)
} else {
return nil
}
}
}
struct TokenSmallParsed: Codable {
let amount: Decimal
let amountDouble: Double
let id: String
let symbol: String
let contract: String
let precision: Int
var asToken: Token? {
if !contract.isEmpty, !symbol.isEmpty {
return Token(
symbol: symbol,
precision: precision,
amount: amount,
contract: contract,
certCoef: 0,
certName: "",
city: nil,
country: nil
)
} else {
return nil
}
}
}
struct Token: Codable {
let symbol: String
let precision: Int
var amount: Decimal
let contract: String
var country: String?
var city: String?
var pool: Swap.Model.Pool?
// Cash tokens fields
var certCoef: Decimal
var certName: String
init(
symbol: String,
precision: Int,
amount: Decimal,
contract: String,
certCoef: Decimal = 100,
certName: String? = nil,
city: String? = nil,
country: String? = nil
) {
self.symbol = symbol
self.precision = precision
self.amount = amount
self.contract = contract
self.certCoef = certCoef
self.certName = certName ?? String(symbol.uppercased().dropFirst(2))
self.city = city
self.country = country
}
enum CodingKeys: String, CodingKey {
case symbol
case precision
case amount
case contract
case currency
case decimals
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
if let value = try? values.decodeIfPresent(String.self, forKey: .symbol) {
symbol = value
precision = try values.decodeIfPresent(Int.self, forKey: .precision) ?? 0
let amountString = (try values.decodeIfPresent(Double.self, forKey: .amount) ?? 0.0).toString(precision: precision)
amount = Decimal(string: amountString) ?? 0.0
} else {
symbol = try values.decodeIfPresent(String.self, forKey: .currency) ?? ""
precision = Int((try? values.decodeIfPresent(String.self, forKey: .decimals)) ?? "0") ?? 0
amount = (try? values.decodeIfPresent(String.self, forKey: .amount))?.toDecimal() ?? 0.0
}
contract = try values.decodeIfPresent(String.self, forKey: .contract) ?? ""
certCoef = 100
certName = String(symbol.uppercased().dropFirst(2))
}
func encode(to encoder: Encoder) throws {}
}
}
extension Network.Model.Token {
var swappableContracts: Bool {
(!isSwapContract || isMLNK) && checkSafeName() && !isCertificate
}
var isCashContract: Bool { contract == ApplicationEnvironment.shared().current.contract(.cash) }
var isListContract: Bool { contract == ApplicationEnvironment.shared().current.contract(.list) }
var isSwapContract: Bool { contract == ApplicationEnvironment.shared().current.contract(.swap) }
var isUSDTContract: Bool { contract == ApplicationEnvironment.shared().current.contract(.usdt) }
var isOurContract: Bool { isCashContract || isListContract || isSwapContract }
var isUSDTName: Bool { symbol.uppercased() == "USDT" }
var isUSDT: Bool { isUSDTContract && isUSDTName }
var isMLNKName: Bool { symbol.uppercased() == "MLNK" }
var isMLNK: Bool { isSwapContract && isMLNKName }
var isListName: Bool { symbol.uppercased().hasPrefix("LI") && symbol.count == 7 }
var isList: Bool { isListContract && isListName }
var isCashName: Bool { symbol.uppercased().hasSuffix("CASH") && symbol.count == 7 }
var isCash: Bool { isCashContract && isCashName }
var isKLNKName: Bool { symbol.uppercased() == "KLNK" }
var isKLNK: Bool { isCashContract && isKLNKName }
var isCertificateName: Bool { symbol.uppercased().hasPrefix("G") && !symbol.uppercased().hasSuffix("CASH") && symbol.count == 7 }
var isCertificate: Bool { isCashContract && isCertificateName }
}
extension Network.Model.Token: CustomStringConvertible {
var description: String { amount.toString(max: precision, symbol: symbol) }
}
extension Network.Model.Token {
func checkSafeName() -> Bool {
let ourNames = ["USDCASH","EURCASH",
"UAHCASH","RUBCASH",
"GBPCASH","INRCASH",
"RMBCASH","JPYCASH",
"MLNK",
"LIRUMOW","LIRUCEK",
"LIRULED","LIUAIEV"]
if !self.isOurContract {
return !ourNames.contains(self.symbol)
}
return true
}
}
extension Network.Model.Token {
var name: String? {
var name: String?
if let city = city, let country = country, isListContract {
name = "LiST \(country), \(city)"
} else if isKLNK {
return "Kalinka"
} else if isCashContract {
switch symbol.uppercased() {
case "USDCASH": name = L10n.Wallet.Token.Usdcash.description
case "EURCASH": name = L10n.Wallet.Token.Eurcash.description
case "UAHCASH": name = L10n.Wallet.Token.Uahcash.description
case "RUBCASH": name = L10n.Wallet.Token.Rubcash.description
case "GBPCASH": name = L10n.Wallet.Token.Gbpcash.description
case "INRCASH": name = L10n.Wallet.Token.Inrcash.description
case "RMBCASH": name = L10n.Wallet.Token.Rmbcash.description
case "JPYCASH": name = L10n.Wallet.Token.Jpycash.description
default:
switch symbol.uppercased().dropFirst().first {
case "U": name = L10n.Wallet.Token.Cert.description(L10n.Wallet.Token.usdcash, city ?? "")
case "E": name = L10n.Wallet.Token.Cert.description(L10n.Wallet.Token.eurcash, city ?? "")
case "H": name = L10n.Wallet.Token.Cert.description(L10n.Wallet.Token.uahcash, city ?? "")
case "R": name = L10n.Wallet.Token.Cert.description(L10n.Wallet.Token.rubcash, city ?? "")
case "G": name = L10n.Wallet.Token.Cert.description(L10n.Wallet.Token.gbpcash, city ?? "")
case "I": name = L10n.Wallet.Token.Cert.description(L10n.Wallet.Token.inrcash, city ?? "")
case "J": name = L10n.Wallet.Token.Cert.description(L10n.Wallet.Token.rmbcash, city ?? "")
case "Y": name = L10n.Wallet.Token.Cert.description(L10n.Wallet.Token.jpycash, city ?? "")
default: name = nil
}
}
} else if isMLNK {
return "Malinka"
} else if let pool = pool {
name = "\(pool.token1?.symbol ?? "") - \(pool.token2?.symbol ?? "")"
} else {
name = contract
}
return name?.uppercased().replacingOccurrences(of: "LIST", with: "LiST")
}
}
extension Network.Model.Token: CommonMenuMappable {
func toMenu() -> Common.Model.Menu {
.menu(
uuid: symbol + contract,
image: .from(token: Network.Model.TokenSmall(quantity: "0 \(symbol)", contract: contract).asToken),
imageURLs: [.from(symbol: symbol, contract: contract), .from(symbol: symbol)],
title: symbol,
text: name,
details: amount.toString(max: precision)
)
}
}
extension Network.Model.Token {
static let eosioToken = Network.Model.Token(symbol: "EOS", precision: 4, amount: 0, contract: ApplicationEnvironment.shared().current.contract(.eosioToken))
}
extension Network.Model.Token: Equatable {
static func == (lhs: Network.Model.Token, rhs: Network.Model.Token) -> Bool { lhs.symbol == rhs.symbol && lhs.contract == rhs.contract }
}
extension Network.Model.Token: Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(symbol)
hasher.combine(contract)
}
}
extension Array where Element == Network.Model.Token {
func first(_ element: Element) -> Element? {
if let index = firstIndex(of: element) {
return self[index]
}
return nil
}
}