161 lines
6.3 KiB
Swift
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
|
|
}
|
|
}
|