Add support for currency selection

This commit is contained in:
2024-09-07 05:55:34 +03:00
parent cb0397ba98
commit edb10c48e6
11 changed files with 164 additions and 87 deletions

View File

@@ -11,35 +11,35 @@
import Foundation
private struct CoinGeckoPriceResponse: Codable {
let bitcoin: CoinGeckoPrice
}
private struct CoinGeckoPrice: Codable {
#if !SKIP
let usd: Decimal
let bitcoin: [String: Decimal]
#else
let usd: String
let bitcoin: [String: String]
#endif
}
class CoinGeckoPriceFetcher : PriceFetcher {
private static let urlString = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&precision=18"
func urlString(toCurrency currency: Locale.Currency) -> String {
"https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=\(currency.identifier.lowercased())&precision=18"
}
func btcToUsd() async throws -> Decimal? {
func convertBTC(toCurrency currency: Locale.Currency) async throws -> Decimal? {
do {
guard let urlComponents = URLComponents(string: CoinGeckoPriceFetcher.urlString), let url = urlComponents.url else {
guard let urlComponents = URLComponents(string: urlString(toCurrency: currency)), let url = urlComponents.url else {
return nil
}
let (data, _) = try await URLSession.shared.data(from: url, delegate: nil)
let priceResponse = try JSONDecoder().decode(CoinGeckoPriceResponse.self, from: data)
let price = priceResponse.bitcoin
guard let price = priceResponse.bitcoin[currency.identifier.lowercased()] else {
return nil
}
#if !SKIP
return price.usd
return price
#else
return Decimal(price.usd)
return Decimal(price)
#endif
} catch {
return nil

View File

@@ -21,13 +21,13 @@ private struct CoinbasePrice: Codable {
}
class CoinbasePriceFetcher : PriceFetcher {
private static let urlString = "https://api.coinbase.com/v2/prices/BTC-USD/spot"
private static let btc = "BTC"
private static let usd = "USD"
func urlString(toCurrency currency: Locale.Currency) -> String {
"https://api.coinbase.com/v2/prices/BTC-\(currency.identifier)/spot"
}
func btcToUsd() async throws -> Decimal? {
func convertBTC(toCurrency currency: Locale.Currency) async throws -> Decimal? {
do {
guard let urlComponents = URLComponents(string: CoinbasePriceFetcher.urlString), let url = urlComponents.url else {
guard let urlComponents = URLComponents(string: urlString(toCurrency: currency)), let url = urlComponents.url else {
return nil
}
@@ -36,7 +36,7 @@ class CoinbasePriceFetcher : PriceFetcher {
let coinbasePriceResponse = try JSONDecoder().decode(CoinbasePriceResponse.self, from: data)
let coinbasePrice = coinbasePriceResponse.data
guard coinbasePrice.base == CoinbasePriceFetcher.btc && coinbasePrice.currency == CoinbasePriceFetcher.usd else {
guard coinbasePrice.base == "BTC" && coinbasePrice.currency == currency.identifier else {
return nil
}

View File

@@ -13,7 +13,7 @@ import Foundation
/// Fake price fetcher that returns a randomized price. Useful for development testing without requiring a network call.
class FakePriceFetcher: PriceFetcher {
func btcToUsd() async throws -> Decimal? {
func convertBTC(toCurrency currency: Locale.Currency) async throws -> Decimal? {
Decimal(Double.random(in: 10000...100000))
}
}

View File

@@ -14,7 +14,7 @@ import Foundation
class ManualPriceFetcher: PriceFetcher {
var price: Decimal = Decimal(1)
func btcToUsd() async throws -> Decimal? {
func convertBTC(toCurrency currency: Locale.Currency) async throws -> Decimal? {
return price
}
}

View File

@@ -11,5 +11,5 @@
import Foundation
protocol PriceFetcher {
func btcToUsd() async throws -> Decimal?
func convertBTC(toCurrency currency: Locale.Currency) async throws -> Decimal?
}

View File

@@ -39,7 +39,7 @@ class PriceFetcherDelegator: PriceFetcher {
}
}
func btcToUsd() async throws -> Decimal? {
return try await delegate.btcToUsd()
func convertBTC(toCurrency currency: Locale.Currency) async throws -> Decimal? {
return try await delegate.convertBTC(toCurrency: currency)
}
}