show usd values for more networks

This commit is contained in:
ivan grachev 2023-11-02 20:14:52 +03:00
parent b2c55bdfca
commit da16214e82
5 changed files with 50 additions and 17 deletions

View File

@ -11,7 +11,7 @@ struct EthereumNetwork: Codable, Equatable {
let isTestnet: Bool
var symbolIsETH: Bool { return symbol == "ETH" }
var hasUSDPrice: Bool { return chainId == EthereumNetwork.ethMainnetChainId } // TODO: list more chains with usd price
var mightShowPrice: Bool { return !isTestnet } // TODO: check if explicitly allowed to match price for symbol
var chainIdHexString: String { String.hex(chainId, withPrefix: true) }
var isEthMainnet: Bool { return chainId == EthereumNetwork.ethMainnetChainId }

View File

@ -21,12 +21,12 @@ struct Transaction {
return value.gweiUInt
}
func description(chain: EthereumNetwork, ethPrice: Double?) -> String {
func description(chain: EthereumNetwork, price: Double?) -> String {
var result = ["🌐 " + chain.name]
if let value = valueWithSymbol(chain: chain, ethPrice: ethPrice, withLabel: false) {
if let value = valueWithSymbol(chain: chain, price: price, withLabel: false) {
result.append(value)
}
result.append(feeWithSymbol(chain: chain, ethPrice: ethPrice))
result.append(feeWithSymbol(chain: chain, price: price))
result.append(dataWithLabel)
return result.joined(separator: "\n\n")
@ -54,13 +54,13 @@ struct Transaction {
return "Gas price: " + gwei
}
func feeWithSymbol(chain: EthereumNetwork, ethPrice: Double?) -> String {
func feeWithSymbol(chain: EthereumNetwork, price: Double?) -> String {
let feeString: String
if let gasPriceString = gasPrice, let gasString = gas,
let gasPrice = BigInt(hexString: gasPriceString),
let gas = BigInt(hexString: gasString) {
let fee = gas * gasPrice
let costString = chain.hasUSDPrice ? cost(value: fee, price: ethPrice) : ""
let costString = chain.mightShowPrice ? cost(value: fee, price: price) : ""
feeString = fee.eth.prefix(8) + " \(chain.symbol)" + costString
} else {
feeString = Strings.calculating
@ -68,9 +68,9 @@ struct Transaction {
return "Fee: " + feeString
}
func valueWithSymbol(chain: EthereumNetwork, ethPrice: Double?, withLabel: Bool) -> String? {
func valueWithSymbol(chain: EthereumNetwork, price: Double?, withLabel: Bool) -> String? {
guard let value = value, let value = BigInt(hexString: value) else { return nil }
let costString = chain.hasUSDPrice ? cost(value: value, price: ethPrice) : ""
let costString = chain.mightShowPrice ? cost(value: value, price: price) : ""
let valueString = "\(value.eth) \(chain.symbol)" + costString
return withLabel ? "Value: " + valueString : valueString
}

View File

@ -4,8 +4,20 @@ import Foundation
class PriceService {
private struct PriceResponse: Codable {
let ethereum: Price
private struct Prices: Codable {
let eth: Price?
let bnb: Price?
let matic: Price?
let ftm: Price?
enum CodingKeys: String, CodingKey, CaseIterable {
case eth = "ethereum"
case bnb = "binancecoin"
case matic = "matic-network"
case ftm = "fantom"
}
}
private struct Price: Codable {
@ -15,10 +27,14 @@ class PriceService {
static let shared = PriceService()
private let jsonDecoder = JSONDecoder()
private let urlSession = URLSession(configuration: .ephemeral)
private let idsQuery: String = {
let ids = Prices.CodingKeys.allCases.map { $0.rawValue }
return ids.joined(separator: "%2C")
}()
private init() {}
var currentPrice: Double?
private var currentPrices: Prices?
func start() {
getPrice(scheduleNextRequest: true)
@ -28,13 +44,29 @@ class PriceService {
getPrice(scheduleNextRequest: false)
}
func forNetwork(_ network: EthereumNetwork) -> Double? {
guard network.mightShowPrice else { return nil }
switch network.symbol {
case "ETH":
return currentPrices?.eth?.usd
case "BNB":
return currentPrices?.bnb?.usd
case "FTM":
return currentPrices?.ftm?.usd
case "MATIC":
return currentPrices?.matic?.usd
default:
return nil
}
}
private func getPrice(scheduleNextRequest: Bool) {
let url = URL(string: "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd")!
let url = URL(string: "https://api.coingecko.com/api/v3/simple/price?ids=\(idsQuery)&vs_currencies=usd")!
let dataTask = urlSession.dataTask(with: url) { [weak self] (data, _, _) in
if let data = data,
let priceResponse = try? self?.jsonDecoder.decode(PriceResponse.self, from: data) {
let pricesResponse = try? self?.jsonDecoder.decode(Prices.self, from: data) {
DispatchQueue.main.async {
self?.currentPrice = priceResponse.ethereum.usd
self?.currentPrices = pricesResponse
}
}
if scheduleNextRequest {

View File

@ -85,10 +85,11 @@ class ApproveTransactionViewController: UIViewController {
.textWithImage(text: chain.name, imageURL: nil, image: Images.network)
]
if let value = transaction.valueWithSymbol(chain: chain, ethPrice: priceService.currentPrice, withLabel: true) {
let price = priceService.forNetwork(chain)
if let value = transaction.valueWithSymbol(chain: chain, price: price, withLabel: true) {
cellModels.append(.text(text: value, oneLine: false))
}
cellModels.append(.text(text: transaction.feeWithSymbol(chain: chain, ethPrice: priceService.currentPrice), oneLine: false))
cellModels.append(.text(text: transaction.feeWithSymbol(chain: chain, price: price), oneLine: false))
cellModels.append(.text(text: transaction.gasPriceWithLabel(chain: chain), oneLine: false))
if let data = transaction.nonEmptyDataWithLabel {
cellModels.append(.text(text: data, oneLine: true))

View File

@ -94,7 +94,7 @@ class ApproveTransactionViewController: NSViewController {
okButton.isEnabled = transaction.hasFee
enableSpeedConfigurationIfNeeded()
let meta = transaction.description(chain: chain, ethPrice: priceService.currentPrice)
let meta = transaction.description(chain: chain, price: priceService.forNetwork(chain))
if metaTextView.string != meta {
metaTextView.string = meta
}