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 let isTestnet: Bool
var symbolIsETH: Bool { return symbol == "ETH" } 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 chainIdHexString: String { String.hex(chainId, withPrefix: true) }
var isEthMainnet: Bool { return chainId == EthereumNetwork.ethMainnetChainId } var isEthMainnet: Bool { return chainId == EthereumNetwork.ethMainnetChainId }

View File

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

View File

@ -4,8 +4,20 @@ import Foundation
class PriceService { class PriceService {
private struct PriceResponse: Codable { private struct Prices: Codable {
let ethereum: Price
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 { private struct Price: Codable {
@ -15,10 +27,14 @@ class PriceService {
static let shared = PriceService() static let shared = PriceService()
private let jsonDecoder = JSONDecoder() private let jsonDecoder = JSONDecoder()
private let urlSession = URLSession(configuration: .ephemeral) 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() {} private init() {}
var currentPrice: Double? private var currentPrices: Prices?
func start() { func start() {
getPrice(scheduleNextRequest: true) getPrice(scheduleNextRequest: true)
@ -28,13 +44,29 @@ class PriceService {
getPrice(scheduleNextRequest: false) 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) { 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 let dataTask = urlSession.dataTask(with: url) { [weak self] (data, _, _) in
if let data = data, 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 { DispatchQueue.main.async {
self?.currentPrice = priceResponse.ethereum.usd self?.currentPrices = pricesResponse
} }
} }
if scheduleNextRequest { if scheduleNextRequest {

View File

@ -85,10 +85,11 @@ class ApproveTransactionViewController: UIViewController {
.textWithImage(text: chain.name, imageURL: nil, image: Images.network) .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: 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)) cellModels.append(.text(text: transaction.gasPriceWithLabel(chain: chain), oneLine: false))
if let data = transaction.nonEmptyDataWithLabel { if let data = transaction.nonEmptyDataWithLabel {
cellModels.append(.text(text: data, oneLine: true)) cellModels.append(.text(text: data, oneLine: true))

View File

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