Skip to content

Commit

Permalink
Add histogram chart and ETF fetchers for chart.
Browse files Browse the repository at this point in the history
  • Loading branch information
ant013 authored and ealymbaev committed May 27, 2024
1 parent 9796d27 commit d6293ba
Show file tree
Hide file tree
Showing 16 changed files with 237 additions and 24 deletions.
16 changes: 15 additions & 1 deletion UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2132,6 +2132,8 @@
6BAAF34B2B9B245C00EFE5B2 /* SlideButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BAAF3462B9B245C00EFE5B2 /* SlideButton.swift */; };
6BB14F6B2BF49E7100E879B2 /* WalletButtonHiddenManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BB14F6A2BF49E7100E879B2 /* WalletButtonHiddenManager.swift */; };
6BB14F6C2BF49E7100E879B2 /* WalletButtonHiddenManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BB14F6A2BF49E7100E879B2 /* WalletButtonHiddenManager.swift */; };
6BB14F722BFE550600E879B2 /* MarketEtfFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BB14F712BFE550600E879B2 /* MarketEtfFetcher.swift */; };
6BB14F732BFE550600E879B2 /* MarketEtfFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BB14F712BFE550600E879B2 /* MarketEtfFetcher.swift */; };
6BBCE4A32BDA419200ABBD55 /* Web3Wallet in Frameworks */ = {isa = PBXBuildFile; productRef = 6BBCE4A22BDA419200ABBD55 /* Web3Wallet */; };
6BBCE4A52BDA419B00ABBD55 /* Web3Wallet in Frameworks */ = {isa = PBXBuildFile; productRef = 6BBCE4A42BDA419B00ABBD55 /* Web3Wallet */; };
6BCD53002A161F4100993F20 /* BackupCloudModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCD52F72A161F4100993F20 /* BackupCloudModule.swift */; };
Expand Down Expand Up @@ -4489,6 +4491,7 @@
6BAAF3452B9B245C00EFE5B2 /* SlideButtonStyling.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlideButtonStyling.swift; sourceTree = "<group>"; };
6BAAF3462B9B245C00EFE5B2 /* SlideButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlideButton.swift; sourceTree = "<group>"; };
6BB14F6A2BF49E7100E879B2 /* WalletButtonHiddenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletButtonHiddenManager.swift; sourceTree = "<group>"; };
6BB14F712BFE550600E879B2 /* MarketEtfFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketEtfFetcher.swift; sourceTree = "<group>"; };
6BCD52F72A161F4100993F20 /* BackupCloudModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackupCloudModule.swift; sourceTree = "<group>"; };
6BCD52F92A161F4100993F20 /* ICloudBackupTermsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ICloudBackupTermsViewModel.swift; sourceTree = "<group>"; };
6BCD52FA2A161F4100993F20 /* ICloudBackupTermsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ICloudBackupTermsViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -7862,6 +7865,7 @@
58AAAC5B31C9DD58D57A3EA9 /* MarketGlobalMetric */ = {
isa = PBXGroup;
children = (
6BB14F702BFE54F200E879B2 /* Etf */,
58AAA7B3EA0C8B9FDEC41837 /* MarketGlobalMetricService.swift */,
58AAA775FE9B46DA2910F508 /* MarketGlobalMetricModule.swift */,
58AAA02D981360FF0CC50A19 /* MarketGlobalMetricViewController.swift */,
Expand Down Expand Up @@ -7975,6 +7979,14 @@
path = WidgetCoinAppShowWorker;
sourceTree = "<group>";
};
6BB14F702BFE54F200E879B2 /* Etf */ = {
isa = PBXGroup;
children = (
6BB14F712BFE550600E879B2 /* MarketEtfFetcher.swift */,
);
path = Etf;
sourceTree = "<group>";
};
6BCD52F62A161F4100993F20 /* ICloud */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -10264,6 +10276,7 @@
D02A67C9272A7460009B2C1C /* CoinTweetsViewController.swift in Sources */,
D36DE0DF272FD887000BC916 /* OneInchViewModel.swift in Sources */,
D02A67C6272A7460009B2C1C /* CoinTweetsViewModel.swift in Sources */,
6BB14F732BFE550600E879B2 /* MarketEtfFetcher.swift in Sources */,
D09200C6293F21720091981A /* RestoreNonStandardViewModel.swift in Sources */,
11B35F20127C070137781ED5 /* AddTokenModule.swift in Sources */,
11B35D722A70E8B4776AB5A8 /* AddBep2TokenBlockchainService.swift in Sources */,
Expand Down Expand Up @@ -11832,6 +11845,7 @@
D36DE0C0272FD864000BC916 /* UniswapService.swift in Sources */,
11B35ED22837284580055F0A /* BalanceData.swift in Sources */,
11B3534B567884E30A871F32 /* AddTokenModule.swift in Sources */,
6BB14F722BFE550600E879B2 /* MarketEtfFetcher.swift in Sources */,
11B35758262A961566ABB87F /* AddBep2TokenBlockchainService.swift in Sources */,
58AAADEE16D9605E4FA0390A /* UniswapSettingsViewModel.swift in Sources */,
D09200C5293F21720091981A /* RestoreNonStandardViewModel.swift in Sources */,
Expand Down Expand Up @@ -13853,7 +13867,7 @@
repositoryURL = "https://github.com/horizontalsystems/Chart.Swift";
requirement = {
kind = exactVersion;
version = 3.0.0;
version = 3.0.1;
};
};
D3604E8028F03C6B0066C366 /* XCRemoteSwiftPackageReference "FeeRateKit" */ = {
Expand Down
1 change: 1 addition & 0 deletions UnstoppableWallet/UnstoppableWallet/Models/Stats.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ enum StatPage: String {
case globalMetricsDefiCap = "global_metrics_defi_cap"
case globalMetricsMarketCap = "global_metrics_market_cap"
case globalMetricsTvlInDefi = "global_metrics_tvl_in_defi"
case globalMetricsEtf = "global_metrics_etf"
case globalMetricsVolume = "global_metrics_volume"
case guide
case importFull = "import_full"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,18 +223,30 @@ class ChartUiView: UIView {
CGSize(width: UIView.noIntrinsicMetric, height: totalHeight)
}

func timePeriod(show: Bool) {
timePeriodView.isHidden = !show
timePeriodView.snp.updateConstraints { maker in
maker.height.equalTo(show ? CGFloat.heightCell48 : 0)
}

updateConstraints()
}

var totalHeight: CGFloat {
.heightDoubleLineCell
+ configuration.mainHeight
+ (configuration.showIndicatorArea ? configuration.indicatorHeight : 0)
+ .margin8 + .heightCell48 + .margin8
+ (timePeriodView.isHidden ? 0 : (.margin8 + .heightCell48))
+ .margin8
}

private func updateIntervals() {
var viewItems: [FilterView.ViewItem] = viewModel.intervals.map { .item(title: $0) }
if viewModel.showAll {
viewItems.append(.item(title: "chart.time_duration.all".localized))
}

timePeriod(show: !viewItems.isEmpty)
timePeriodView.reload(filters: viewItems)
}

Expand Down Expand Up @@ -284,6 +296,14 @@ class ChartUiView: UIView {
} else {
currentSecondaryDiffLabel.isHidden = true
}
case let .custom(title, value):
currentSecondaryTitleLabel.isHidden = false
currentSecondaryValueLabel.isHidden = false
currentSecondaryDiffLabel.isHidden = true

currentSecondaryTitleLabel.text = title
currentSecondaryValueLabel.text = value
currentSecondaryValueLabel.textColor = .themeLeah
}

if !chartView.isPressed {
Expand Down Expand Up @@ -349,6 +369,14 @@ class ChartUiView: UIView {
} else {
chartSecondaryDiffLabel.isHidden = true
}
case let .custom(title, value):
currentSecondaryTitleLabel.isHidden = false
currentSecondaryValueLabel.isHidden = false
chartSecondaryDiffLabel.isHidden = true

chartSecondaryTitleLabel.text = title
chartSecondaryValueLabel.text = value
chartSecondaryValueLabel.textColor = .themeLeah
case let .indicators(top, bottom):
chartSecondaryTitleLabel.isHidden = false
chartSecondaryValueLabel.isHidden = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class MarketWideCardCell: BaseSelectableThemeCell {
let chartConfiguration: ChartConfiguration
switch chartCurveType {
case .line: chartConfiguration = .previewChart
case .bars: chartConfiguration = .previewBarChart
case .bars, .histogram: chartConfiguration = .previewBarChart
}
showChartView(configuration: chartConfiguration)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ extension CoinAnalyticsViewController: SectionsDataSource {

switch chartCurveType {
case .line: chartTrend = viewItem.chartTrend
case .bars: chartTrend = .neutral
case .bars, .histogram: chartTrend = .neutral
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ enum ChartModule {
let chartData: ChartData
let indicators: [ChartIndicator]
let chartTrend: MovementTrend
let chartDiff: Decimal?
let chartDiff: ValueDiff?

let limitFormatter: ((Decimal) -> String?)?
}

struct SelectedPointViewItem {
let value: String?
let diff: Decimal?
let diff: ValueDiff?
let date: String
let rightSideMode: RightSideMode

init(value: String?, diff: Decimal? = nil, date: String, rightSideMode: RightSideMode) {
init(value: String?, diff: ValueDiff? = nil, date: String, rightSideMode: RightSideMode) {
self.value = value
self.diff = diff
self.date = date
Expand All @@ -35,6 +35,7 @@ enum ChartModule {
case none
case volume(value: String?)
case dominance(value: Decimal?, diff: Decimal?)
case custom(title: String, value: String?)
case indicators(top: NSAttributedString?, bottom: NSAttributedString?)
}
}
Expand All @@ -55,6 +56,11 @@ enum MovementTrend {
}
}

struct ValueDiff {
let value: String
let trend: MovementTrend
}

protocol IChartViewModel {
var showAll: Bool { get }
var intervals: [String] { get }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,17 @@ class CoinChartFactory {
}

let chartData = ChartData(items: items, startWindow: firstPoint.timestamp, endWindow: lastPoint.timestamp)
let diff = (lastPoint.value - firstPoint.value) / firstPoint.value * 100
let diffString = ValueFormatter.instance.format(percentValue: diff, showSign: true)
let valueDiff = diffString.map { ValueDiff(value: $0, trend: diff.isSignMinus ? .down : .up) }
return ChartModule.ViewItem(
value: ValueFormatter.instance.formatFull(currencyValue: CurrencyValue(currency: currency, value: item.rate)),
valueDescription: nil,
rightSideMode: .none,
chartData: chartData,
indicators: item.indicators,
chartTrend: lastPoint.value > firstPoint.value ? .up : .down,
chartDiff: (lastPoint.value - firstPoint.value) / firstPoint.value * 100,
chartDiff: valueDiff,
limitFormatter: { value in ValueFormatter.instance.formatFull(currency: currency, value: value) }
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct MarketEtfView: View {

init(isPresented: Binding<Bool>) {
_viewModel = StateObject(wrappedValue: MarketEtfViewModel())
_chartViewModel = StateObject(wrappedValue: MetricChartViewModel.instance(type: .totalMarketCap))
_chartViewModel = StateObject(wrappedValue: MetricChartViewModel.etfInstance)
_isPresented = isPresented
}

Expand Down Expand Up @@ -72,7 +72,7 @@ struct MarketEtfView: View {
}

@ViewBuilder private func chart() -> some View {
ChartView(viewModel: chartViewModel, configuration: .marketCapChart)
ChartView(viewModel: chartViewModel, configuration: .baseHistogramChart)
.frame(maxWidth: .infinity)
.onFirstAppear {
chartViewModel.start()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import UIKit

enum MarketGlobalModule {
static let dominance = "dominance"
static let totalAssets = "total_assets"
static let totalInflow = "total_inflow"

enum MetricsType: Identifiable {
case totalMarketCap, volume24h, defiCap, tvlInDefi
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Chart
import Combine
import Foundation
import MarketKit

class MarketEtfFetcher {
private let marketKit: MarketKit.Kit
private let currencyManager: CurrencyManager

private let needUpdateSubject = PassthroughSubject<Void, Never>()

init(marketKit: MarketKit.Kit, currencyManager: CurrencyManager) {
self.marketKit = marketKit
self.currencyManager = currencyManager
}
}

extension MarketEtfFetcher: IMetricChartFetcher {
var valueType: MetricChartModule.ValueType {
.compactCurrencyValue(currencyManager.baseCurrency)
}

var needUpdatePublisher: AnyPublisher<Void, Never> {
Empty().eraseToAnyPublisher()
}

var intervals: [HsPeriodType] { [] }

func fetch(interval _: HsPeriodType) async throws -> MetricChartModule.ItemData {
let points = try await marketKit.etfPoints(currencyCode: currencyManager.baseCurrency.code)

var items = [MetricChartModule.Item]()
var totalInflow = [Decimal]()
var totalAssets = [Decimal]()
for point in points.sorted(by: { p1, p2 in p1.date < p2.date }) {
items.append(MetricChartModule.Item(value: point.dailyInflow, timestamp: point.date.timeIntervalSince1970))
totalInflow.append(point.totalInflow)
totalAssets.append(point.totalAssets)
}
return MetricChartModule.ItemData(
items: items,
indicators: [
MarketGlobalModule.totalInflow: totalInflow,
MarketGlobalModule.totalAssets: totalAssets,
],
type: .etf
)
}
}
Loading

0 comments on commit d6293ba

Please sign in to comment.