Skip to content

Commit

Permalink
Switch global market data to new endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
ealymbaev committed May 28, 2024
1 parent a7a4f36 commit 35bf15c
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13917,7 +13917,7 @@
repositoryURL = "https://github.com/horizontalsystems/MarketKit.Swift";
requirement = {
kind = exactVersion;
version = 3.0.5;
version = 3.0.6;
};
};
D3604E7D28F03C1D0066C366 /* XCRemoteSwiftPackageReference "Chart" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class StatManager {
appId = AppConfig.appId
}

func logStat(eventPage: StatPage, eventSection: StatSection? = nil, event: StatEvent) {
func logStat(eventPage _: StatPage, eventSection _: StatSection? = nil, event _: StatEvent) {
// var parameters: [String: Any]?
//
// if let params = event.params {
Expand Down Expand Up @@ -87,9 +87,9 @@ class StatManager {
// return object
// }
//
//// let data = try JSONSerialization.data(withJSONObject: stats)
//// let string = String(data: data, encoding: .utf8)
//// print(string ?? "N/A")
//// let data = try JSONSerialization.data(withJSONObject: stats)
//// let string = String(data: data, encoding: .utf8)
//// print(string ?? "N/A")
//
// try await marketKit.send(stats: stats, appVersion: appVersion, appId: appId)
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,18 +200,7 @@ struct MarketEtfView: View {
HStack(spacing: .margin8) {
Text(name).textSubhead2()
Spacer()

if let change, let formatted = ValueFormatter.instance.formatShort(currency: viewModel.currency, value: change) {
if change == 0 {
Text(formatted).textSubhead2()
} else if change > 0 {
Text("+\(formatted)").textSubhead2(color: .themeRemus)
} else {
Text("-\(formatted)").textSubhead2(color: .themeLucian)
}
} else {
Text("----").textSubhead2()
}
DiffText(change, currency: viewModel.currency)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import MarketKit
import SwiftUI
import ThemeKit

struct MarketGlobalView: View {
@ObservedObject var viewModel: MarketGlobalViewModel

@State private var presentedGlobalMarketMetricsType: MarketGlobalModule.MetricsType?
@State private var marketCapPresented = false
@State private var volumePresented = false
@State private var etfPresented = false
@State private var tvlPresented = false

var body: some View {
VStack(spacing: 0) {
if let globalMarketData = viewModel.globalMarketData {
if let marketGlobal = viewModel.marketGlobal {
MarqueeView(targetVelocity: 30) {
content(globalMarketData: globalMarketData)
content(marketGlobal: marketGlobal, redacted: marketGlobal)
}
} else {
ZStack {
HStack(spacing: .margin8) {
content(globalMarketData: nil)
content(marketGlobal: nil, redacted: nil)
}
.padding(.leading, .margin8)
.fixedSize()
Expand All @@ -31,9 +32,9 @@ struct MarketGlobalView: View {
.frame(maxWidth: .infinity)
.frame(height: 1)
}
.animation(.default, value: viewModel.globalMarketData == nil)
.sheet(item: $presentedGlobalMarketMetricsType) { metricsType in
MarketGlobalMetricsView(metricsType: metricsType).ignoresSafeArea()
.animation(.default, value: viewModel.marketGlobal == nil)
.sheet(isPresented: $tvlPresented) {
MarketGlobalMetricsView(metricsType: .tvlInDefi).ignoresSafeArea()
}
.sheet(isPresented: $marketCapPresented) {
MarketMarketCapView(isPresented: $marketCapPresented)
Expand All @@ -46,33 +47,66 @@ struct MarketGlobalView: View {
}
}

@ViewBuilder private func content(globalMarketData: MarketGlobalViewModel.GlobalMarketData?) -> some View {
itemView(title: "market.global.market_cap".localized, item: globalMarketData?.marketCap, metricsType: .totalMarketCap)
itemView(title: "market.global.volume".localized, item: globalMarketData?.volume, metricsType: .volume24h)
itemView(title: "market.global.defi_cap".localized, item: globalMarketData?.defiCap, metricsType: .defiCap)
itemView(title: "market.global.defi_in_tvl".localized, item: globalMarketData?.tvlInDefi, metricsType: .tvlInDefi)
@ViewBuilder private func content(marketGlobal: MarketGlobal?, redacted: Any?) -> some View {
diffView(
title: "market.global.market_cap".localized,
amount: marketGlobal?.marketCap,
diff: marketGlobal?.marketCapChange.map { .percent(value: $0) },
redacted: redacted
) {
marketCapPresented = true
}

diffView(
title: "market.global.volume".localized,
amount: marketGlobal?.volume,
diff: marketGlobal?.volumeChange.map { .percent(value: $0) },
redacted: redacted
) {
volumePresented = true
}

diffView(
title: "market.global.btc_dominance".localized,
amount: marketGlobal?.btcDominance,
diff: marketGlobal?.btcDominanceChange.map { .percent(value: $0) },
redacted: redacted
) {
marketCapPresented = true
}

diffView(
title: "market.global.etf_inflow".localized,
amount: marketGlobal?.etfTotalInflow,
diff: marketGlobal?.etfDailyInflow.map { .change(value: $0, currency: viewModel.currency) },
redacted: redacted
) {
etfPresented = true
}

diffView(
title: "market.global.tvl_in_defi".localized,
amount: marketGlobal?.tvl,
diff: marketGlobal?.tvlChange.map { .percent(value: $0) },
redacted: redacted
) {
tvlPresented = true
}
}

@ViewBuilder private func itemView(title: String, item: MarketGlobalViewModel.GlobalMarketItem?, metricsType: MarketGlobalModule.MetricsType) -> some View {
@ViewBuilder private func diffView(title: String, amount: Decimal?, diff: DiffText.Diff?, redacted: Any?, onTap: @escaping () -> Void) -> some View {
HStack(spacing: .margin4) {
Text(title).textCaption()

Text(item?.amount ?? "$2.34T")
Text(amount.flatMap { ValueFormatter.instance.formatShort(currency: viewModel.currency, value: $0) } ?? "----")
.textCaption(color: .themeBran)
.redacted(value: item?.amount)
.redacted(value: redacted)

DiffText(item?.diff, font: .themeCaption)
.redacted(value: item?.diff)
DiffText(diff, font: .themeCaption)
.redacted(value: redacted)
}
.padding(.horizontal, .margin8)
.padding(.vertical, .margin16)
.onTapGesture {
switch metricsType {
case .totalMarketCap: marketCapPresented = true
case .volume24h: volumePresented = true
case .defiCap: etfPresented = true
default: presentedGlobalMarketMetricsType = metricsType
}
}
.onTapGesture(perform: onTap)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,84 +2,45 @@ import Combine
import Foundation
import HsExtensions
import MarketKit
import RxSwift

class MarketGlobalViewModel: ObservableObject {
private let marketKit = App.shared.marketKit
private let currencyManager = App.shared.currencyManager
private let appManager = App.shared.appManager

private var cancellables = Set<AnyCancellable>()
private var globalMarketDataTask: AnyTask?
private let disposeBag = DisposeBag()
private var tasks = Set<AnyTask>()

@Published var globalMarketData: GlobalMarketData?
@Published var marketGlobal: MarketGlobal?

init() {
currencyManager.$baseCurrency
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
self?.globalMarketData = nil
self?.marketGlobal = nil
self?.syncState()
}
.store(in: &cancellables)

subscribe(disposeBag, appManager.willEnterForegroundObservable) { [weak self] in self?.syncState() }

syncState()
}

private func syncState() {
globalMarketDataTask = Task { [weak self, marketKit, currencyManager] in
let marketOverview = try await marketKit.marketOverview(currencyCode: currencyManager.baseCurrency.code)
tasks = Set()

Task { [weak self, marketKit, currencyManager] in
let marketGlobal = try await marketKit.marketGlobal(currencyCode: currencyManager.baseCurrency.code)

await MainActor.run { [weak self] in
self?.handle(marketOverview: marketOverview)
self?.marketGlobal = marketGlobal
}
}
.erased()
}

private func handle(marketOverview: MarketOverview) {
let marketCapPoints = marketOverview.globalMarketPoints.map(\.marketCap)
let volumePoints = marketOverview.globalMarketPoints.map(\.volume24h)
let defiCapPoints = marketOverview.globalMarketPoints.map(\.defiMarketCap)
let tvlInDefiPoints = marketOverview.globalMarketPoints.map(\.tvl)

globalMarketData = GlobalMarketData(
marketCap: globalMarketItem(points: marketCapPoints),
volume: globalMarketItem(points: volumePoints),
defiCap: globalMarketItem(points: defiCapPoints),
tvlInDefi: globalMarketItem(points: tvlInDefiPoints)
)
}

private func globalMarketItem(points: [Decimal]) -> GlobalMarketItem? {
GlobalMarketItem(
amount: points.last.flatMap { ValueFormatter.instance.formatShort(currency: currencyManager.baseCurrency, value: $0) },
diff: diff(points: points)
)
}

private func diff(points: [Decimal]) -> Decimal? {
guard let first = points.first, let last = points.last, first != 0 else {
return nil
}

return (last - first) * 100 / first
.store(in: &tasks)
}
}

extension MarketGlobalViewModel {
struct GlobalMarketData {
let marketCap: GlobalMarketItem?
let volume: GlobalMarketItem?
let defiCap: GlobalMarketItem?
let tvlInDefi: GlobalMarketItem?
}

struct GlobalMarketItem {
let amount: String?
let diff: Decimal?
var currency: Currency {
currencyManager.baseCurrency
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,55 @@ import SwiftUI
import ThemeKit

struct DiffText: View {
private let value: Decimal?
private let diff: Diff?
private let font: Font

init(_ value: Decimal?, font: Font = .themeSubhead2) {
self.value = value
init(_ diff: Diff?, font: Font = .themeSubhead2) {
self.diff = diff
self.font = font
}

init(_ diff: Decimal?, font: Font = .themeSubhead2) {
self.diff = diff.map { .percent(value: $0) }
self.font = font
}

init(_ change: Decimal?, currency: Currency, font: Font = .themeSubhead2) {
diff = change.map { .change(value: $0, currency: currency) }
self.font = font
}

var body: some View {
Text(value.flatMap { ValueFormatter.instance.format(percentValue: $0) } ?? "----")
.foregroundColor(value.map { $0.isSignMinus ? .themeLucian : .themeRemus } ?? .themeGray)
.font(font)
.lineLimit(1)
.truncationMode(.middle)
if let (text, value) = resolved {
Text(text)
.foregroundColor(value == 0 ? .themeGray : (value.isSignMinus ? .themeLucian : .themeRemus))
.font(font)
.lineLimit(1)
.truncationMode(.middle)
} else {
Text("----")
.foregroundColor(.themeGray)
.font(font)
.lineLimit(1)
.truncationMode(.middle)
}
}

private var resolved: (String, Decimal)? {
guard let diff else {
return nil
}

switch diff {
case let .percent(value): return ValueFormatter.instance.format(percentValue: value).map { ($0, value) }
case let .change(value, currency): return ValueFormatter.instance.formatShort(currency: currency, value: value, showSign: true).map { ($0, value) }
}
}
}

extension DiffText {
enum Diff {
case percent(value: Decimal)
case change(value: Decimal, currency: Currency)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -698,10 +698,11 @@
"market.defi_cap" = "DeFi Cap";
"market.defi_tvl" = "TVL in DeFi";

"market.global.market_cap" = "Market Cap";
"market.global.volume" = "Volume";
"market.global.defi_cap" = "DeFi Cap";
"market.global.defi_in_tvl" = "TVL in DeFi";
"market.global.market_cap" = "Total Cap";
"market.global.volume" = "24h Vol.";
"market.global.btc_dominance" = "BTC Dominance";
"market.global.etf_inflow" = "ETF Inflow";
"market.global.tvl_in_defi" = "TVL in DeFi";

"market.tab.news" = "News";
"market.tab.coins" = "Coins";
Expand Down

0 comments on commit 35bf15c

Please sign in to comment.