// // 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 } }