Files
2022-10-06 16:17:16 +03:00

235 lines
8.6 KiB
Swift

//
// P2POrder.swift
// Wallet
//
// Created by Saveliy Stavitsky on 7/30/21.
// Copyright © 2021 AM. All rights reserved.
//
import Foundation
import Resolver
import RealmSwift
enum P2POrderStatus: String, PersistableEnum, Codable {
case active = "available"
case inactive = "unavailable"
case closed = "closed"
}
// swiftlint:disable identifier_name
class P2PRating: EmbeddedObject, Codable {
@Persisted private var completed_deals: Int?
@Persisted private var failed_deals: Int?
var requests: Int { (completed_deals ?? 0) + (failed_deals ?? 0) }
var rating: Decimal? { requests > 0 ? Decimal(completed_deals ?? 0) / Decimal(requests) : nil }
}
class P2POrder: Object, Decodable {
@Persisted var id: Int
@Persisted(indexed: true) var idText: String
@Persisted var uuid: String
@Persisted(primaryKey: true) var uniqueId: String
@Persisted(indexed: true) var owner: String
@Persisted var contentType: P2P.Model.ContentType
@Persisted(indexed: true) var status: P2POrderStatus
@Persisted(indexed: true) var symbol: String
@Persisted var precision: Int
@Persisted var volume: Decimal128
@Persisted var needClose: Bool
@Persisted var insurance: Decimal128
@Persisted var min: Decimal128
@Persisted var max: Decimal128
var hasEqualAmount: Bool { min == max && (min == volume || volume == 0) }
@Persisted(indexed: true) var kind: P2P.Model.Kind
@Persisted var createdAt: Date
@Persisted var rating: P2PRating?
@Persisted var ratingValue: Decimal128?
@Persisted var currencyId: Int
@Persisted var rate: Decimal128
@Persisted var rateIsReversed: Bool
@Persisted var cardNumber: String?
@Persisted var paymentUrl: String?
@Persisted var walletNumber: String?
@Persisted var walletAddress: String?
@Persisted var blockchainId: Int?
@Persisted var paymentSystemId: Int?
@Persisted var countryId: Int?
@Persisted var cityId: Int?
@Persisted var bankIds: List<Int>
@Persisted var cardName: String?
@Persisted var cardDate: String?
@Persisted var cvv: String?
@Persisted var memo: String?
// swiftlint:disable identifier_name
enum CodingKeys: String, CodingKey {
case id = "order_id"
case uuid
case owner
case data_type
case status
case volume
case insurance
case volume_balance
case insurance_balance
case min_package
case max_package
case order_type
case created_at
case rating
case currency_id
case rate
case rateIsReversed = "is_cash_rate"
case card_number
case payment_url
case wallet_number
case wallet_address
case blockchain_id
case payment_system_id
case country_id
case city_id
case bank_ids
case card_name
case card_expiry
case cvv
case memo
}
override required init() { }
required init(from decoder: Decoder) throws {
super.init()
let values = try decoder.container(keyedBy: CodingKeys.self)
if let orderId = Int(try values.decode(String.self, forKey: .id)) {
id = orderId
idText = "\(orderId)"
} else {
throw "P2POrder decoding error order id: \(try values.decode(String.self, forKey: .id)) is not Integer"
}
uuid = try values.decode(String.self, forKey: .uuid)
owner = try values.decode(String.self, forKey: .owner)
contentType = try values.decode(P2P.Model.ContentType.self, forKey: .data_type)
status = try values.decode(P2POrderStatus.self, forKey: .status)
symbol = try values.decode(String.self, forKey: .volume).symbol
precision = try values.decode(String.self, forKey: .volume).amount.precision
uniqueId = "\(symbol)#\(id)"
volume = try Decimal128(string: try values.decode(String.self, forKey: .volume_balance).amount)
insurance = try Decimal128(string: try values.decode(String.self, forKey: .insurance_balance).amount)
min = try Decimal128(string: try values.decode(String.self, forKey: .min_package).amount)
max = try Decimal128(string: try values.decode(String.self, forKey: .max_package).amount)
needClose = volume < min
// orderType = (try? values.decode(String.self, forKey: .order_type)) == "BUY" ? .buy : .sell
kind = (try? values.decode(String.self, forKey: .order_type))?.uppercased() ?? "BUY" == "BUY"
? .buy : .sell
createdAt = try values.decode(String.self, forKey: .created_at).serverDate() ?? Date()
rating = try? values.decode(P2PRating.self, forKey: .rating)
ratingValue = rating?.rating.map({ Decimal128(value: $0) })
currencyId = try values.decode(Int.self, forKey: .currency_id)
rate = try Decimal128(string: try values.decode(String.self, forKey: .rate))
rateIsReversed = !((try? values.decode(Bool.self, forKey: .rateIsReversed)) ?? true)
cardNumber = try? values.decode(String.self, forKey: .card_number)
paymentUrl = try? values.decode(String.self, forKey: .payment_url)
walletNumber = try? values.decode(String.self, forKey: .wallet_number)
walletAddress = try? values.decode(String.self, forKey: .wallet_address)
blockchainId = try? values.decode(Int.self, forKey: .blockchain_id)
paymentSystemId = try? values.decode(Int.self, forKey: .payment_system_id)
countryId = try? values.decode(Int.self, forKey: .country_id)
cityId = try? values.decode(Int.self, forKey: .city_id)
bankIds = List<Int>()
bankIds.append(objectsIn: (try? values.decode([Int].self, forKey: .bank_ids)) ?? [])
cardName = try? values.decode(String.self, forKey: .card_name)
cardDate = try? values.decode(String.self, forKey: .card_expiry)
cvv = try? values.decode(String.self, forKey: .cvv)
memo = try? values.decode(String.self, forKey: .memo)
}
}
extension P2POrder {
var currency: P2PCurrency? {
Resolver.resolve(Realm.self, name: .realmP2PLists)
.object(ofType: P2PCurrency.self, forPrimaryKey: currencyId)
}
var blockchain: P2PBlockchain? {
Resolver.resolve(Realm.self, name: .realmP2PLists)
.object(ofType: P2PBlockchain.self, forPrimaryKey: blockchainId ?? -1)
}
var paymentSystem: P2PPaymentSystem? {
Resolver.resolve(Realm.self, name: .realmP2PLists)
.object(ofType: P2PPaymentSystem.self, forPrimaryKey: paymentSystemId ?? -1)
}
var country: P2PCountry? {
Resolver.resolve(Realm.self, name: .realmP2PLists)
.object(ofType: P2PCountry.self, forPrimaryKey: countryId ?? -1)
}
var city: P2PCity? {
Resolver.resolve(Realm.self, name: .realmP2PLists)
.object(ofType: P2PCity.self, forPrimaryKey: cityId ?? -1)
}
var bank: P2PBank? {
Resolver.resolve(Realm.self, name: .realmP2PLists)
.object(ofType: P2PBank.self, forPrimaryKey: bankIds.first ?? -1)
}
var banks: [P2PBank] {
bankIds.compactMap({
Resolver.resolve(Realm.self, name: .realmP2PLists)
.object(ofType: P2PBank.self, forPrimaryKey: $0)
})
}
}
extension P2POrder {
#warning("""
Fix this use
@InjectedOptional(name: .realmOrders) var realm: Realm
try? realm.write {
realm.delete(self)
}
where needed after swift compiler bug fixed in swift 5.5
https://forums.swift.org/t/segmentation-fault-11-with-local-property-wrappers/47905/3
""")
func delete() throws {
if let realm = self.realm?.thaw(), let order = self.thaw() {
try realm.write {
realm.delete(order)
}
}
}
#warning("""
Fix this use
@InjectedOptional(name: .realmOrders) var realm: Realm
try? realm.write {
self.status = .active
}
where needed after swift compiler bug fixed in swift 5.5
https://forums.swift.org/t/segmentation-fault-11-with-local-property-wrappers/47905/3
""")
func modify(_ action: (P2POrder) -> Void) throws {
if let realm = self.realm?.thaw(), let order = self.thaw() {
try realm.write {
action(order)
}
} else if self.realm == nil {
@OptionalInjected(name: .realmOrders) var realm: Realm?
try realm?.write {
if let order = realm?.object(ofType: P2POrder.self, forPrimaryKey: self.uniqueId) {
action(order)
}
}
}
}
}