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

161 lines
6.3 KiB
Swift

//
// SwapModelPool.swift
// Wallet
//
// Created by Saveliy Stavitsky on 3/18/21.
// Copyright © 2021 AM. All rights reserved.
//
import Foundation
extension Swap.Model {
struct Pool: Decodable {
let id: Int
let code: String
let k: Decimal // swiftlint:disable:this identifier_name
let totalFee: Decimal
let kDouble: Double
let totalFeeDouble: Double
private let parsedToken1: Network.Model.TokenSmallParsed
private let parsedToken2: Network.Model.TokenSmallParsed
private(set) var isReversed: Bool = false
func reversed() -> Pool {
var newPool = self
newPool.isReversed = true
return newPool
}
var token1: Network.Model.Token? { isReversed ? parsedToken2.asToken : parsedToken1.asToken }
var token2: Network.Model.Token? { isReversed ? parsedToken1.asToken : parsedToken2.asToken }
var token1Light: Network.Model.TokenSmallParsed? { isReversed ? parsedToken2 : parsedToken1 }
var token2Light: Network.Model.TokenSmallParsed? { isReversed ? parsedToken1 : parsedToken2 }
var forwardExchangeRate: Decimal { (token2?.amount ?? 0) / (token1?.amount ?? 1.0) }
var backwardExchangeRate: Decimal { (token1?.amount ?? 0) / (token2?.amount ?? 1.0) }
enum CodingKeys: String, CodingKey {
case id
case code
case token1
case token2
case poolFee = "pool_fee"
case platformFee = "platform_fee"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decode(Int.self, forKey: .id)
code = try values.decode(String.self, forKey: .code)
let token1 = try values.decode(Network.Model.TokenSmall.self, forKey: .token1).asToken
parsedToken1 = Network.Model.TokenSmallParsed(
amount: token1?.amount ?? 0,
amountDouble: NSDecimalNumber(decimal: (token1?.amount ?? 0)).doubleValue,
id: "\(token1?.symbol ?? "")#\(token1?.contract ?? "")",
symbol: token1?.symbol ?? "",
contract: token1?.contract ?? "",
precision: token1?.precision ?? 0)
let token2 = try values.decode(Network.Model.TokenSmall.self, forKey: .token2).asToken
parsedToken2 = Network.Model.TokenSmallParsed(
amount: token2?.amount ?? 0,
amountDouble: NSDecimalNumber(decimal: (token2?.amount ?? 0)).doubleValue,
id: "\(token2?.symbol ?? "")#\(token2?.contract ?? "")",
symbol: token2?.symbol ?? "",
contract: token2?.contract ?? "",
precision: token2?.precision ?? 0)
k = (token1?.amount ?? 0) * (token2?.amount ?? 0)
kDouble = NSDecimalNumber(decimal: k).doubleValue
let poolFee = try values.decode(String.self, forKey: .poolFee).amount.toDecimal() / 100.0
let platformFee = try values.decode(String.self, forKey: .platformFee).amount.toDecimal() / 100.0
totalFee = poolFee + platformFee
totalFeeDouble = NSDecimalNumber(decimal: totalFee).doubleValue
}
let cashContractName = ApplicationEnvironment.shared().current.contract(.cash)
func processSend(amount: Decimal, forward: Bool) -> Decimal {
// guard let token1 = (token1 == amountToken ? token1 : token2),
// let token2 = (token1 == amountToken ? token2 : token1),
// token1 == amountToken || token2 == amountToken else {
// return 0
// }
guard let token1 = forward ? self.token1Light : self.token2Light,
let token2 = forward ? self.token2Light : self.token1Light else {
return 0
}
let minTokenAmount = (Decimal(1) / pow(Decimal(10), token1.precision))
if amount < Decimal(800) * minTokenAmount {
return 0
}
let withoutCommission = amount
.receive(percent: totalFee, precision: token1.precision, ignoreMaxCommission: true)
let newPool = token1.amount + withoutCommission
let otherTokenNewPool = (k / newPool).roundDown(to: token2.precision)
return token2.amount - otherTokenNewPool
}
func processReceive(amount: Decimal, forward: Bool) -> Decimal {
guard let tokenTo = forward ? self.token2Light : self.token1Light,
let tokenFrom = forward ? self.token1Light : self.token2Light else {
return 0
}
let newPool = (tokenFrom.amount - amount).roundDown(to: tokenFrom.precision)
let otherTokenNewPool = (k / newPool).roundDown(to: tokenTo.precision)
let withCommission = (otherTokenNewPool - tokenTo.amount)
.send(percent: totalFee, precision: tokenTo.precision, ignoreMaxCommission: true)
// let minTokenAmount = (Decimal(1) / pow(Decimal(10), tokenTo.precision))
// if tokenTo.contract == cashContractName && withCommission < Decimal(4000) * minTokenAmount {
// return Decimal(4000) * minTokenAmount
// }
// if withCommission < Decimal(800) * minTokenAmount {
// return Decimal(800) * minTokenAmount
// }
return withCommission
}
}
struct PoolStat: Codable {
let supply: String
var token: Network.Model.Token? {
Network.Model.Token(
symbol: supply.symbol,
precision: 0,
amount: supply.amount.toDecimal(),
contract: ApplicationEnvironment.shared().current.contract(.swap)
)
}
}
}
struct SpeedPool: Hashable {
let id: Int
private(set) var isReversed: Bool = false
func reversed() -> SpeedPool {
var newPool = self
newPool.isReversed = true
return newPool
}
let token1Code: Int
let token2Code: Int
var token1: Int { isReversed ? token2Code : token1Code }
var token2: Int { isReversed ? token1Code : token2Code }
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
extension SpeedPool: Equatable {
static func == (lhs: SpeedPool, rhs: SpeedPool) -> Bool {
lhs.id == rhs.id
}
}