From 70ab37853b81b224f507a6d2969a2cd4b1ca62e9 Mon Sep 17 00:00:00 2001 From: Ermat Date: Fri, 15 Mar 2024 14:26:47 +0600 Subject: [PATCH] Initial implementation of analytics --- .../project.pbxproj | 12 ++++++ .../Core/Managers/StatsManager.swift | 38 +++++++++++++++++++ .../UnstoppableWallet/Models/StatPage.swift | 34 +++++++++++++++++ .../Coin/Analytics/CoinAnalyticsModule.swift | 12 +++--- .../Coin/Analytics/CoinAnalyticsService.swift | 12 +++--- .../CoinOverview/CoinOverviewModule.swift | 10 ++--- .../CoinOverview/CoinOverviewService.swift | 8 ++-- .../CoinOverviewViewModelNew.swift | 8 ++-- .../Modules/Coin/CoinPageModule.swift | 12 +++--- .../Coin/Ranks/CoinRankViewController.swift | 5 ++- .../WidgetCoinAppShowModule.swift | 13 +++---- ...etAdvancedSearchResultViewController.swift | 2 +- .../MarketCategoryViewController.swift | 2 +- .../MarketGlobalMetricViewController.swift | 11 +++++- .../MarketGlobalTvlMetricViewController.swift | 2 +- .../MarketList/MarketListViewController.swift | 9 +++-- ...arketNftTopCollectionsViewController.swift | 2 +- .../MarketOverviewTopCoinsDataSource.swift | 3 +- .../MarketOverviewTopCoinsService.swift | 7 ++++ .../MarketTop/MarketTopViewController.swift | 2 +- .../MarketTopPairsViewController.swift | 2 +- .../MarketTopPlatformsViewController.swift | 2 +- .../Modules/Market/MarketViewController.swift | 7 +++- .../MarketWatchlistViewController.swift | 2 +- .../TopPlatformViewController.swift | 2 +- .../TransactionInfoViewController.swift | 3 +- .../WalletTokenBalanceDataSource.swift | 7 ++-- 27 files changed, 164 insertions(+), 65 deletions(-) create mode 100644 UnstoppableWallet/UnstoppableWallet/Core/Managers/StatsManager.swift create mode 100644 UnstoppableWallet/UnstoppableWallet/Models/StatPage.swift diff --git a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj index e55a860ab6..a677d5aeef 100644 --- a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj +++ b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj @@ -576,6 +576,7 @@ 11B355F32686B8689B4EC105 /* WalletConnectRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35CD5EBBB403D46BDEF0B /* WalletConnectRequest.swift */; }; 11B355FAD0E7823AF5F8EC83 /* SendEvmTransactionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35C7F043B6C41E53D43BC /* SendEvmTransactionService.swift */; }; 11B355FC0E3DE029EB3F95D5 /* TransactionTokenSelectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35DDC338BFE2832C07360 /* TransactionTokenSelectView.swift */; }; + 11B355FCAF8DC88550CE2DB3 /* StatsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359980AA45D6B44151D7A /* StatsManager.swift */; }; 11B3560586CBAB617211F003 /* Caution.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35D96CF03878016FC38FD /* Caution.swift */; }; 11B356075F51B38338958A4A /* MultiSwapSettingStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350910284BA2BF694FA17 /* MultiSwapSettingStorage.swift */; }; 11B35608F7D19B3E6318CB22 /* Text.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B352972B14FA6EBEFD6904 /* Text.swift */; }; @@ -793,6 +794,7 @@ 11B3586BF6AC0538272E71A4 /* NftCollectionModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35708A630D70385F34A8B /* NftCollectionModule.swift */; }; 11B3586F6BFCA16BDFD5921D /* DuressModeModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A81FB3D4C06BBFEE7E7 /* DuressModeModule.swift */; }; 11B35871BA700133050E9241 /* CexWithdrawViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B2465CB748311AF03D5 /* CexWithdrawViewModel.swift */; }; + 11B3587280273E0804CA84F2 /* StatPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35743A66A4653A3C2FDBF /* StatPage.swift */; }; 11B358781EBEFCE7CED000F0 /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A6BEF8299304625D6D0 /* SearchBar.swift */; }; 11B3587D9E89A97F63CD0C5A /* EditPasscodeModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3529CF33E51DA1C872106 /* EditPasscodeModule.swift */; }; 11B3587EF674C1E8EEE61DE7 /* MarkdownBlockQuoteCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3552D3F84BA594EFE964C /* MarkdownBlockQuoteCell.swift */; }; @@ -1078,6 +1080,7 @@ 11B35B15B1815F7EEB128C5F /* BinanceAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35AAAC675987369F2DA1B /* BinanceAdapter.swift */; }; 11B35B172B09C2017B389C07 /* AlertTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35BF766EAC97E74CD620D /* AlertTitleCell.swift */; }; 11B35B177527D30099B67C91 /* FeeData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3542B6FE4B4F0C0B65369 /* FeeData.swift */; }; + 11B35B1875DF852DE471C511 /* StatPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35743A66A4653A3C2FDBF /* StatPage.swift */; }; 11B35B1F09AE8EBC7E594974 /* ScanQrView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35FE66467E3FA27809733 /* ScanQrView.swift */; }; 11B35B1F63DBDEEF57043C97 /* PublicKeysService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B358A294479046C42D2E6B /* PublicKeysService.swift */; }; 11B35B26C32F47DE6E83FC82 /* BlockchainTokensModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35BC10B98A0770A2AC342 /* BlockchainTokensModule.swift */; }; @@ -1526,6 +1529,7 @@ 11B35FE603192CF3195115D0 /* LanguageSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35920D0AD623C5E4A4460 /* LanguageSettingsViewModel.swift */; }; 11B35FE8D60BFF31C3104484 /* SwitchAccountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350BC3E707879846AC0AA /* SwitchAccountViewModel.swift */; }; 11B35FEB268E7C6B085B56C9 /* MarketOverviewTopPairsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35AB1D0CE5D8ECE7DDF65 /* MarketOverviewTopPairsViewModel.swift */; }; + 11B35FEC7AA2A8887FCF0AE6 /* StatsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359980AA45D6B44151D7A /* StatsManager.swift */; }; 11B35FF02BADC6D832836C44 /* EvmPrivateKeyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B353262E45560C91FD6B65 /* EvmPrivateKeyViewModel.swift */; }; 11B35FF072E32C5D4028D0F6 /* TextInputCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35968F5DE9FDA6EC26FCD /* TextInputCell.swift */; }; 11B35FF10EF7FC47869EF295 /* CexWithdrawViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B2465CB748311AF03D5 /* CexWithdrawViewModel.swift */; }; @@ -3560,6 +3564,7 @@ 11B3573B3FE1FD8B476375E6 /* NftCollectionAssetsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NftCollectionAssetsViewModel.swift; sourceTree = ""; }; 11B357426B767AA64ED8E7A2 /* WalletViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletViewModel.swift; sourceTree = ""; }; 11B35743158763BD8E336770 /* InputPrefixWrapperView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputPrefixWrapperView.swift; sourceTree = ""; }; + 11B35743A66A4653A3C2FDBF /* StatPage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatPage.swift; sourceTree = ""; }; 11B35747FAD8381F2AD48276 /* MainViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewModel.swift; sourceTree = ""; }; 11B357511F8F17D8221B64E2 /* AppearanceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceView.swift; sourceTree = ""; }; 11B3575530EE722514F89A61 /* PasteInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasteInputView.swift; sourceTree = ""; }; @@ -3690,6 +3695,7 @@ 11B35995E0D358AC4DA2FA74 /* RestoreBinanceModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreBinanceModule.swift; sourceTree = ""; }; 11B35996D668B9ADC60E6B9B /* CoinAnalyticsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoinAnalyticsService.swift; sourceTree = ""; }; 11B35997A9E413878F48313B /* ActivateSubscriptionModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivateSubscriptionModule.swift; sourceTree = ""; }; + 11B359980AA45D6B44151D7A /* StatsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatsManager.swift; sourceTree = ""; }; 11B3599833F166185872A3AC /* RecipientAndSlippageMultiSwapSettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipientAndSlippageMultiSwapSettingsView.swift; sourceTree = ""; }; 11B35999E6C5518115365410 /* EvmAccountRestoreStateStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmAccountRestoreStateStorage.swift; sourceTree = ""; }; 11B359A35AEB7964A94AFFC0 /* BiometryType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BiometryType.swift; sourceTree = ""; }; @@ -5509,6 +5515,7 @@ 11B35B5570E7513DF2A455BB /* PasscodeManager.swift */, 11B35196B818E6069195BAF1 /* KeychainManager.swift */, 11B3505A43D9C2787B3BD153 /* PasscodeLockManager.swift */, + 11B359980AA45D6B44151D7A /* StatsManager.swift */, ); path = Managers; sourceTree = ""; @@ -5893,6 +5900,7 @@ ABC9A68AFE3CF24D2B88808F /* EnabledWalletCache_v_0_36.swift */, 11B35E41142BD3D2FF59BAE7 /* AutoLockPeriod.swift */, 11B35B6F5261FF3F9ECBC02E /* PasscodeLockState.swift */, + 11B35743A66A4653A3C2FDBF /* StatPage.swift */, ); path = Models; sourceTree = ""; @@ -10872,6 +10880,8 @@ ABC9A6C591067D34C6DF2673 /* SlideButtonStyling.swift in Sources */, 11B35A32114022EF422E6602 /* MultiSwapRevokeView.swift in Sources */, 11B357DCC0BA9E888DE64CB1 /* MultiSwapRevokeViewModel.swift in Sources */, + 11B35FEC7AA2A8887FCF0AE6 /* StatsManager.swift in Sources */, + 11B3587280273E0804CA84F2 /* StatPage.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -12358,6 +12368,8 @@ 11B35A920F2DB5784F178BDA /* EvmFeeEstimator.swift in Sources */, 11B3545369350E4253688D91 /* MultiSwapRevokeView.swift in Sources */, 11B35CBF59F85C3DAB5FE751 /* MultiSwapRevokeViewModel.swift in Sources */, + 11B355FCAF8DC88550CE2DB3 /* StatsManager.swift in Sources */, + 11B35B1875DF852DE471C511 /* StatPage.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Managers/StatsManager.swift b/UnstoppableWallet/UnstoppableWallet/Core/Managers/StatsManager.swift new file mode 100644 index 0000000000..f6db13bf2f --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/Core/Managers/StatsManager.swift @@ -0,0 +1,38 @@ +import Alamofire +import Foundation +import HsToolKit + +func stat(page: StatPage, section: StatSection? = nil, event: StatEvent, params: [StatParam: Any]? = nil) { + StatsManager.instance.sendStat(page: page, section: section, event: event, params: params) +} + +class StatsManager { + static let instance = StatsManager(networkManager: NetworkManager(logger: Logger(minLogLevel: .debug))) + + private let networkManager: NetworkManager + + init(networkManager: NetworkManager) { + self.networkManager = networkManager + } + + func sendStat(page: StatPage, section: StatSection? = nil, event: StatEvent, params: [StatParam: Any]? = nil) { + Task { + var parameters: Parameters = [ + "page": page.rawValue, + "event": event.rawValue, + ] + + if let section { + parameters["section"] = section.rawValue + } + + if let params { + for (key, value) in params { + parameters[key.rawValue] = value + } + } + + _ = try await networkManager.fetchJson(url: "\(AppConfig.marketApiUrl)/v1/stats", method: .head, parameters: parameters) + } + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/Models/StatPage.swift b/UnstoppableWallet/UnstoppableWallet/Models/StatPage.swift new file mode 100644 index 0000000000..d50992e56b --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/Models/StatPage.swift @@ -0,0 +1,34 @@ +enum StatPage: String { + case advancedSearchResults = "advanced_search_results" + case coinPage = "coin_page" + case coinCategory = "coin_category" + case coinRank = "coin_rank" + case globalMetricsMarketCap = "global_metrics_market_cap" + case globalMetricsVolume = "global_metrics_volume" + case globalMetricsDefiCap = "global_metrics_defi_cap" + case globalMetricsTvlInDefi = "global_metrics_tvl_in_defi" + case marketOverview = "market_overview" + case marketSearch = "market_search" + case topCoins = "top_coins" + case topMarketPairs = "top_market_pairs" + case topNftCollections = "top_nft_collections" + case topPlatform = "top_platform" + case topPlatforms = "top_platforms" + case tokenPage = "token_page" + case transactionInfo = "transaction_info" + case watchlist + case widget +} + +enum StatEvent: String { + case coinOpen = "coin_open" +} + +enum StatParam: String { + case coinUid = "coin_uid" +} + +enum StatSection: String { + case topGainers = "top_gainers" + case topLosers = "top_losers" +} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsModule.swift index 26ab172f87..b88f807fc2 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsModule.swift @@ -4,17 +4,16 @@ import ThemeKit import UIKit enum CoinAnalyticsModule { - static func view(fullCoin: FullCoin, apiTag: String) -> some View { - CoinAnalyticsView(fullCoin: fullCoin, apiTag: apiTag) + static func view(fullCoin: FullCoin) -> some View { + CoinAnalyticsView(fullCoin: fullCoin) } - static func viewController(fullCoin: FullCoin, apiTag: String) -> CoinAnalyticsViewController { + static func viewController(fullCoin: FullCoin) -> CoinAnalyticsViewController { let service = CoinAnalyticsService( fullCoin: fullCoin, marketKit: App.shared.marketKit, currencyManager: App.shared.currencyManager, - subscriptionManager: App.shared.subscriptionManager, - apiTag: apiTag + subscriptionManager: App.shared.subscriptionManager ) let technicalIndicatorService = TechnicalIndicatorService( coinUid: fullCoin.coin.uid, @@ -62,10 +61,9 @@ struct CoinAnalyticsView: UIViewControllerRepresentable { typealias UIViewControllerType = UIViewController let fullCoin: FullCoin - let apiTag: String func makeUIViewController(context _: Context) -> UIViewController { - CoinAnalyticsModule.viewController(fullCoin: fullCoin, apiTag: apiTag) + CoinAnalyticsModule.viewController(fullCoin: fullCoin) } func updateUIViewController(_: UIViewController, context _: Context) {} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsService.swift index a0e2ad27bb..7b4d198e45 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsService.swift @@ -9,18 +9,16 @@ class CoinAnalyticsService { private let marketKit: MarketKit.Kit private let currencyManager: CurrencyManager private let subscriptionManager: SubscriptionManager - private let apiTag: String private var tasks = Set() private var cancellables = Set() @PostPublished private(set) var state: State = .loading - init(fullCoin: FullCoin, marketKit: MarketKit.Kit, currencyManager: CurrencyManager, subscriptionManager: SubscriptionManager, apiTag: String) { + init(fullCoin: FullCoin, marketKit: MarketKit.Kit, currencyManager: CurrencyManager, subscriptionManager: SubscriptionManager) { self.fullCoin = fullCoin self.marketKit = marketKit self.currencyManager = currencyManager self.subscriptionManager = subscriptionManager - self.apiTag = apiTag subscriptionManager.$isAuthenticated .sink { [weak self] isAuthenticated in @@ -32,9 +30,9 @@ class CoinAnalyticsService { } private func loadPreview() { - Task { [weak self, marketKit, fullCoin, apiTag] in + Task { [weak self, marketKit, fullCoin] in do { - let analyticsPreview = try await marketKit.analyticsPreview(coinUid: fullCoin.coin.uid, apiTag: apiTag) + let analyticsPreview = try await marketKit.analyticsPreview(coinUid: fullCoin.coin.uid, apiTag: "") self?.state = .preview(analyticsPreview: analyticsPreview) } catch { self?.state = .failed(error) @@ -78,10 +76,10 @@ extension CoinAnalyticsService { state = .loading if subscriptionManager.isAuthenticated { - Task { [weak self, subscriptionManager, marketKit, fullCoin, currency, apiTag] in + Task { [weak self, subscriptionManager, marketKit, fullCoin, currency] in try await subscriptionManager.fetch( request: { - try await marketKit.analytics(coinUid: fullCoin.coin.uid, currencyCode: currency.code, apiTag: apiTag) + try await marketKit.analytics(coinUid: fullCoin.coin.uid, currencyCode: currency.code, apiTag: "") }, onSuccess: { [weak self] analytics in self?.state = .success(analytics: analytics) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewModule.swift index bea4d860ce..1e8b2d60c5 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewModule.swift @@ -3,7 +3,7 @@ import MarketKit import SwiftUI enum CoinOverviewModule { - static func view(coinUid: String, apiTag: String) -> some View { + static func view(coinUid: String) -> some View { let repository = ChartIndicatorsRepository( localStorage: App.shared.localStorage, subscriptionManager: App.shared.subscriptionManager @@ -24,8 +24,7 @@ enum CoinOverviewModule { currencyManager: App.shared.currencyManager, languageManager: LanguageManager.shared, accountManager: App.shared.accountManager, - walletManager: App.shared.walletManager, - apiTag: apiTag + walletManager: App.shared.walletManager ) return CoinOverviewView( @@ -36,15 +35,14 @@ enum CoinOverviewModule { ) } - static func viewController(coinUid: String, apiTag: String) -> CoinOverviewViewController { + static func viewController(coinUid: String) -> CoinOverviewViewController { let service = CoinOverviewService( coinUid: coinUid, marketKit: App.shared.marketKit, currencyManager: App.shared.currencyManager, languageManager: LanguageManager.shared, accountManager: App.shared.accountManager, - walletManager: App.shared.walletManager, - apiTag: apiTag + walletManager: App.shared.walletManager ) let repository = ChartIndicatorsRepository( diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewService.swift index 0f6493585d..607c9d12f8 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewService.swift @@ -13,7 +13,6 @@ class CoinOverviewService { private let languageManager: LanguageManager private let accountManager: AccountManager private let walletManager: WalletManager - private let apiTag: String private let stateRelay = PublishRelay>() private(set) var state: DataStatus = .loading { @@ -22,14 +21,13 @@ class CoinOverviewService { } } - init(coinUid: String, marketKit: MarketKit.Kit, currencyManager: CurrencyManager, languageManager: LanguageManager, accountManager: AccountManager, walletManager: WalletManager, apiTag: String) { + init(coinUid: String, marketKit: MarketKit.Kit, currencyManager: CurrencyManager, languageManager: LanguageManager, accountManager: AccountManager, walletManager: WalletManager) { self.coinUid = coinUid self.marketKit = marketKit self.currencyManager = currencyManager self.languageManager = languageManager self.accountManager = accountManager self.walletManager = walletManager - self.apiTag = apiTag } private func sync(info: MarketInfoOverview) { @@ -120,13 +118,13 @@ extension CoinOverviewService { state = .loading - Task { [weak self, marketKit, coinUid, currencyManager, languageManager, apiTag] in + Task { [weak self, marketKit, coinUid, currencyManager, languageManager] in do { let info = try await marketKit.marketInfoOverview( coinUid: coinUid, currencyCode: currencyManager.baseCurrency.code, languageCode: languageManager.currentLanguage, - apiTag: apiTag + apiTag: "" ) self?.sync(info: info) } catch { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewModelNew.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewModelNew.swift index a764a928ce..75036ac09c 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewModelNew.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewModelNew.swift @@ -12,21 +12,19 @@ class CoinOverviewViewModelNew: ObservableObject { private let languageManager: LanguageManager private let accountManager: AccountManager private let walletManager: WalletManager - private let apiTag: String private let viewItemFactory = CoinOverviewViewItemFactory() let currency: Currency @Published private(set) var state: DataStatus = .loading - init(coinUid: String, marketKit: MarketKit.Kit, currencyManager: CurrencyManager, languageManager: LanguageManager, accountManager: AccountManager, walletManager: WalletManager, apiTag: String) { + init(coinUid: String, marketKit: MarketKit.Kit, currencyManager: CurrencyManager, languageManager: LanguageManager, accountManager: AccountManager, walletManager: WalletManager) { self.coinUid = coinUid self.marketKit = marketKit self.currencyManager = currencyManager self.languageManager = languageManager self.accountManager = accountManager self.walletManager = walletManager - self.apiTag = apiTag currency = currencyManager.baseCurrency } @@ -119,13 +117,13 @@ extension CoinOverviewViewModelNew { state = .loading - Task { [weak self, marketKit, coinUid, currencyManager, languageManager, apiTag] in + Task { [weak self, marketKit, coinUid, currencyManager, languageManager] in do { let info = try await marketKit.marketInfoOverview( coinUid: coinUid, currencyCode: currencyManager.baseCurrency.code, languageCode: languageManager.currentLanguage, - apiTag: apiTag + apiTag: "" ) self?.handleSuccess(info: info) } catch { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinPageModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinPageModule.swift index 900dc7898d..5cc0d82525 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinPageModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinPageModule.swift @@ -4,11 +4,11 @@ import ThemeKit import UIKit enum CoinPageModule { - static func view(fullCoin: FullCoin, apiTag: String) -> some View { + static func view(fullCoin: FullCoin) -> some View { let viewModel = CoinPageViewModelNew(fullCoin: fullCoin, favoritesManager: App.shared.favoritesManager) - let overviewView = CoinOverviewModule.view(coinUid: fullCoin.coin.uid, apiTag: apiTag) - let analyticsView = CoinAnalyticsModule.view(fullCoin: fullCoin, apiTag: apiTag) + let overviewView = CoinOverviewModule.view(coinUid: fullCoin.coin.uid) + let analyticsView = CoinAnalyticsModule.view(fullCoin: fullCoin) let marketsView = CoinMarketsView(coin: fullCoin.coin) return CoinPageView( @@ -19,7 +19,7 @@ enum CoinPageModule { ) } - static func viewController(coinUid: String, apiTag: String) -> UIViewController? { + static func viewController(coinUid: String) -> UIViewController? { guard let fullCoin = try? App.shared.marketKit.fullCoins(coinUids: [coinUid]).first else { return nil } @@ -31,9 +31,9 @@ enum CoinPageModule { let viewModel = CoinPageViewModel(service: service) - let overviewController = CoinOverviewModule.viewController(coinUid: coinUid, apiTag: apiTag) + let overviewController = CoinOverviewModule.viewController(coinUid: coinUid) let marketsController = CoinMarketsView(coin: fullCoin.coin).toViewController() - let analyticsController = CoinAnalyticsModule.viewController(fullCoin: fullCoin, apiTag: apiTag) + let analyticsController = CoinAnalyticsModule.viewController(fullCoin: fullCoin) // let tweetsController = CoinTweetsModule.viewController(fullCoin: fullCoin) let viewController = CoinPageViewController( diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Ranks/CoinRankViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Ranks/CoinRankViewController.swift index 8590163b27..cc15ab5390 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Ranks/CoinRankViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Ranks/CoinRankViewController.swift @@ -120,8 +120,11 @@ extension CoinRankViewController: SectionsDataSource { cell.set(backgroundStyle: .transparent, isLast: isLast) }, action: { [weak self] in - if let viewController = CoinPageModule.viewController(coinUid: viewItem.uid, apiTag: "coin_rank") { + let coinUid = viewItem.uid + + if let viewController = CoinPageModule.viewController(coinUid: coinUid) { self?.present(viewController, animated: true) + stat(page: .coinRank, event: .coinOpen, params: [.coinUid: coinUid]) } } ) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Main/Workers/WidgetCoinAppShowWorker/WidgetCoinAppShowModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Main/Workers/WidgetCoinAppShowWorker/WidgetCoinAppShowModule.swift index 78aec4174b..e190ac031c 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Main/Workers/WidgetCoinAppShowWorker/WidgetCoinAppShowModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Main/Workers/WidgetCoinAppShowWorker/WidgetCoinAppShowModule.swift @@ -15,24 +15,23 @@ extension WidgetCoinAppShowModule: IEventHandler { throw EventHandler.HandleError.noSuitableHandler } - var uid: String? + var coinUid: String? switch event { case let event as String: - uid = event + coinUid = event case let event as DeepLinkManager.DeepLink: - if case let .coin(coinUid) = event { - uid = coinUid + if case let .coin(_coinUid) = event { + coinUid = _coinUid } default: () } - guard let uid, - let viewController = CoinPageModule.viewController(coinUid: uid, apiTag: "widget") - else { + guard let coinUid, let viewController = CoinPageModule.viewController(coinUid: coinUid) else { throw EventHandler.HandleError.noSuitableHandler } parentViewController?.visibleController.present(viewController, animated: true) + stat(page: .widget, event: .coinOpen, params: [.coinUid: coinUid]) } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketAdvancedSearchResults/MarketAdvancedSearchResultViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketAdvancedSearchResults/MarketAdvancedSearchResultViewController.swift index c8f4d77642..46d3ab4916 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketAdvancedSearchResults/MarketAdvancedSearchResultViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketAdvancedSearchResults/MarketAdvancedSearchResultViewController.swift @@ -13,7 +13,7 @@ class MarketAdvancedSearchResultViewController: MarketListViewController { init(listViewModel: IMarketListViewModel, headerViewModel: MarketMultiSortHeaderViewModel) { multiSortHeaderView = MarketMultiSortHeaderView(viewModel: headerViewModel) - super.init(listViewModel: listViewModel, apiTag: "market_advanced_search_results") + super.init(listViewModel: listViewModel, statPage: .advancedSearchResults) multiSortHeaderView.viewController = self } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketCategory/MarketCategoryViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketCategory/MarketCategoryViewController.swift index 9ac5be6acf..1187cd1670 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketCategory/MarketCategoryViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketCategory/MarketCategoryViewController.swift @@ -29,7 +29,7 @@ class MarketCategoryViewController: MarketListViewController { height: chartCell.cellHeight ) - super.init(listViewModel: listViewModel, apiTag: "market_category") + super.init(listViewModel: listViewModel, statPage: .coinCategory) multiSortHeaderView.viewController = self } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketGlobalMetric/MarketGlobalMetricViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketGlobalMetric/MarketGlobalMetricViewController.swift index e4e400f653..3b2317ae57 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketGlobalMetric/MarketGlobalMetricViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketGlobalMetric/MarketGlobalMetricViewController.swift @@ -38,7 +38,16 @@ class MarketGlobalMetricViewController: MarketListViewController { height: chartCell.cellHeight ) - super.init(listViewModel: listViewModel, apiTag: "market_global_metrics_\(metricsType)") + let statPage: StatPage + + switch metricsType { + case .totalMarketCap: statPage = .globalMetricsMarketCap + case .volume24h: statPage = .globalMetricsVolume + case .defiCap: statPage = .globalMetricsDefiCap + case .tvlInDefi: statPage = .globalMetricsTvlInDefi + } + + super.init(listViewModel: listViewModel, statPage: statPage) } @available(*, unavailable) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketGlobalMetric/TvlInDefi/MarketGlobalTvlMetricViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketGlobalMetric/TvlInDefi/MarketGlobalTvlMetricViewController.swift index 903683a9f3..fceef3e06c 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketGlobalMetric/TvlInDefi/MarketGlobalTvlMetricViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketGlobalMetric/TvlInDefi/MarketGlobalTvlMetricViewController.swift @@ -34,7 +34,7 @@ class MarketGlobalTvlMetricViewController: MarketListViewController { height: chartCell.cellHeight ) - super.init(listViewModel: listViewModel, apiTag: "market_global_tvl_metrics") + super.init(listViewModel: listViewModel, statPage: .globalMetricsTvlInDefi) sortHeaderView.viewController = self } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketList/MarketListViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketList/MarketListViewController.swift index 2f72107b86..0e7384d014 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketList/MarketListViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketList/MarketListViewController.swift @@ -16,7 +16,7 @@ protocol IMarketListViewModel { class MarketListViewController: ThemeViewController { private let listViewModel: IMarketListViewModel - private let apiTag: String + private let statPage: StatPage private let disposeBag = DisposeBag() let tableView = SectionsTableView(style: .plain) @@ -32,9 +32,9 @@ class MarketListViewController: ThemeViewController { var refreshEnabled: Bool { true } func topSections(loaded _: Bool) -> [SectionProtocol] { [] } - init(listViewModel: IMarketListViewModel, apiTag: String) { + init(listViewModel: IMarketListViewModel, statPage: StatPage) { self.listViewModel = listViewModel - self.apiTag = apiTag + self.statPage = statPage super.init() @@ -146,12 +146,13 @@ class MarketListViewController: ThemeViewController { } func onSelect(viewItem: MarketModule.ListViewItem) { - guard let uid = viewItem.uid, let module = CoinPageModule.viewController(coinUid: uid, apiTag: apiTag) else { + guard let coinUid = viewItem.uid, let module = CoinPageModule.viewController(coinUid: coinUid) else { HudHelper.instance.show(banner: .attention(string: "market.project_has_no_coin".localized)) return } viewController?.present(module, animated: true) + stat(page: statPage, event: .coinOpen, params: [.coinUid: coinUid]) } private func rowActions(index: Int) -> [RowAction] { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketNftTopCollections/MarketNftTopCollectionsViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketNftTopCollections/MarketNftTopCollectionsViewController.swift index 980543234b..3860c9eeba 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketNftTopCollections/MarketNftTopCollectionsViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketNftTopCollections/MarketNftTopCollectionsViewController.swift @@ -15,7 +15,7 @@ class MarketNftTopCollectionsViewController: MarketListViewController { self.viewModel = viewModel multiSortHeaderView = MarketMultiSortHeaderView(viewModel: headerViewModel) - super.init(listViewModel: listViewModel, apiTag: "") + super.init(listViewModel: listViewModel, statPage: .topNftCollections) multiSortHeaderView.viewController = self } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketOverview/TopCoins/MarketOverviewTopCoinsDataSource.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketOverview/TopCoins/MarketOverviewTopCoinsDataSource.swift index c4c851917e..f5a5013320 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketOverview/TopCoins/MarketOverviewTopCoinsDataSource.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketOverview/TopCoins/MarketOverviewTopCoinsDataSource.swift @@ -37,8 +37,9 @@ class MarketOverviewTopCoinsDataSource: BaseMarketOverviewTopListDataSource { } override func onSelect(listViewItem: MarketModule.ListViewItem) { - if let uid = listViewItem.uid, let module = CoinPageModule.viewController(coinUid: uid, apiTag: "market_overview_top_coins") { + if let coinUid = listViewItem.uid, let module = CoinPageModule.viewController(coinUid: coinUid) { presentDelegate?.present(viewController: module) + stat(page: .marketOverview, section: viewModel.listType.statSection, event: .coinOpen, params: [.coinUid: coinUid]) } } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketOverview/TopCoins/MarketOverviewTopCoinsService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketOverview/TopCoins/MarketOverviewTopCoinsService.swift index e32337e672..e513a8bf98 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketOverview/TopCoins/MarketOverviewTopCoinsService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketOverview/TopCoins/MarketOverviewTopCoinsService.swift @@ -93,5 +93,12 @@ extension MarketOverviewTopCoinsService { case .topGainers, .topLosers: return .price } } + + var statSection: StatSection { + switch self { + case .topGainers: return .topGainers + case .topLosers: return .topLosers + } + } } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTop/MarketTopViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTop/MarketTopViewController.swift index 9f90e5af20..1d11e99751 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTop/MarketTopViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTop/MarketTopViewController.swift @@ -13,7 +13,7 @@ class MarketTopViewController: MarketListViewController { init(listViewModel: IMarketListViewModel, headerViewModel: MarketMultiSortHeaderViewModel) { multiSortHeaderView = MarketMultiSortHeaderView(viewModel: headerViewModel, hasLeftSelector: true) - super.init(listViewModel: listViewModel, apiTag: "market_top") + super.init(listViewModel: listViewModel, statPage: .topCoins) multiSortHeaderView.viewController = self } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTopPairs/MarketTopPairsViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTopPairs/MarketTopPairsViewController.swift index ce1c8adadf..4ed4358764 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTopPairs/MarketTopPairsViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTopPairs/MarketTopPairsViewController.swift @@ -12,7 +12,7 @@ class MarketTopPairsViewController: MarketListViewController { init(viewModel: MarketTopPairsViewModel, listViewModel: IMarketListViewModel) { self.viewModel = viewModel - super.init(listViewModel: listViewModel, apiTag: "") + super.init(listViewModel: listViewModel, statPage: .topMarketPairs) } @available(*, unavailable) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTopPlatforms/MarketTopPlatformsViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTopPlatforms/MarketTopPlatformsViewController.swift index 56a8bab4d5..2425c8ebca 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTopPlatforms/MarketTopPlatformsViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketTopPlatforms/MarketTopPlatformsViewController.swift @@ -15,7 +15,7 @@ class MarketTopPlatformsViewController: MarketListViewController { self.viewModel = viewModel multiSortHeaderView = MarketMultiSortHeaderView(viewModel: headerViewModel) - super.init(listViewModel: listViewModel, apiTag: "") + super.init(listViewModel: listViewModel, statPage: .topPlatforms) multiSortHeaderView.viewController = self } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketViewController.swift index 0960803aa1..66e3a1263c 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketViewController.swift @@ -176,15 +176,18 @@ class MarketViewController: ThemeSearchViewController { extension MarketViewController: SectionsDataSource { private func onSelect(fullCoin: FullCoin) { - guard let module = CoinPageModule.viewController(coinUid: fullCoin.coin.uid, apiTag: "market_discovery") else { + let coinUid = fullCoin.coin.uid + + guard let module = CoinPageModule.viewController(coinUid: coinUid) else { return } DispatchQueue.global().async { [weak self] in - self?.viewModel.handleOpen(coinUid: fullCoin.coin.uid) + self?.viewModel.handleOpen(coinUid: coinUid) } present(module, animated: true) + stat(page: .marketSearch, event: .coinOpen, params: [.coinUid: coinUid]) } private func rowActions(coinUid: String) -> [RowAction] { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketWatchlist/MarketWatchlistViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketWatchlist/MarketWatchlistViewController.swift index bbe8c637e6..cf646b41c0 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketWatchlist/MarketWatchlistViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketWatchlist/MarketWatchlistViewController.swift @@ -19,7 +19,7 @@ class MarketWatchlistViewController: MarketListViewController { self.viewModel = viewModel singleSortHeaderView = MarketSingleSortHeaderView(viewModel: headerViewModel, hasTopSeparator: false) - super.init(listViewModel: listViewModel, apiTag: "market_watchlist") + super.init(listViewModel: listViewModel, statPage: .watchlist) } @available(*, unavailable) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/TopPlatform/TopPlatformViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/TopPlatform/TopPlatformViewController.swift index e1dd139348..6b0fb725ad 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/TopPlatform/TopPlatformViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/TopPlatform/TopPlatformViewController.swift @@ -27,7 +27,7 @@ class TopPlatformViewController: MarketListViewController { height: chartCell.cellHeight ) - super.init(listViewModel: listViewModel, apiTag: "market_top_platform") + super.init(listViewModel: listViewModel, statPage: .topPlatform) multiSortHeaderView.viewController = self } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/TransactionInfo/TransactionInfoViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/TransactionInfo/TransactionInfoViewController.swift index 85d9ab9a02..4f714e8399 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/TransactionInfo/TransactionInfoViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/TransactionInfo/TransactionInfoViewController.swift @@ -92,11 +92,12 @@ class TransactionInfoViewController: ThemeViewController { } private func openCoin(coinUid: String) { - guard let module = CoinPageModule.viewController(coinUid: coinUid, apiTag: "transaction_info") else { + guard let module = CoinPageModule.viewController(coinUid: coinUid) else { return } present(module, animated: true) + stat(page: .transactionInfo, event: .coinOpen, params: [.coinUid: coinUid]) } private func openNftAsset(providerCollectionUid: String, nftUid: NftUid) { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceDataSource.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceDataSource.swift index 1b9a8bbd76..c17b63e27c 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceDataSource.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceDataSource.swift @@ -59,7 +59,7 @@ class WalletTokenBalanceDataSource: NSObject { viewModel.openCoinPagePublisher .receive(on: DispatchQueue.main) .sink { [weak self] in - self?.openCoinPage(coin: $0) + self?.openCoinPage(coinUid: $0.uid) } .store(in: &cancellables) @@ -210,9 +210,10 @@ class WalletTokenBalanceDataSource: NSObject { parentViewController?.present(view.toNavigationViewController(), animated: true) } - private func openCoinPage(coin: Coin) { - if let viewController = CoinPageModule.viewController(coinUid: coin.uid, apiTag: "wallet_token_balance") { + private func openCoinPage(coinUid: String) { + if let viewController = CoinPageModule.viewController(coinUid: coinUid) { parentViewController?.present(viewController, animated: true) + stat(page: .tokenPage, event: .coinOpen, params: [.coinUid: coinUid]) } }