diff --git a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt index 3d7221ff2d..85dbdb56f6 100644 --- a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt +++ b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt @@ -468,6 +468,7 @@ internal class DefaultOnrampRepository( OnrampQuote.Error( paymentMethod = paymentMethod, provider = provider, + error = onrampError, ) } } else { diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt index ea747277bc..4fb9ef47d2 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt @@ -138,32 +138,32 @@ internal class DefaultCurrenciesRepository( } private fun populateCurrenciesWithMissedCoins(currencies: List): List { - val networkToCoin = mutableMapOf() - val networkToTokens = mutableMapOf>() + val currenciesSequence = currencies.asSequence() - currencies.forEach { currency -> - when (currency) { - is CryptoCurrency.Coin -> { - networkToCoin[currency.network] = currency - } - is CryptoCurrency.Token -> { - val tokens = networkToTokens.getOrElse(currency.network, ::emptyList) - networkToTokens[currency.network] = tokens + currency - } - } - } + val networksWithTokens = currenciesSequence + .filterIsInstance() + .map { it.network } + .distinct() + + val networksWithCoins = currenciesSequence + .filterIsInstance() + .map { it.network } + .distinct() + + val networksNeedingCoins = (networksWithTokens - networksWithCoins.toSet()).toMutableList() + + if (networksNeedingCoins.isEmpty()) return currencies return buildList { - if (networkToTokens.isEmpty()) { - // add only coin here - addAll(networkToCoin.values) - } else { - networkToTokens.forEach { (network, networkTokens) -> - val networkCoin = networkToCoin[network] ?: cryptoCurrencyFactory.createCoin(network) + currencies.forEach { currency -> + if (currency is CryptoCurrency.Token && currency.network in networksNeedingCoins) { + val coin = cryptoCurrencyFactory.createCoin(currency.network) + add(coin) - add(networkCoin) - addAll(networkTokens) + networksNeedingCoins.remove(currency.network) } + + add(currency) } } } diff --git a/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampQuote.kt b/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampQuote.kt index 033d3f3f87..c511e04b8a 100644 --- a/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampQuote.kt +++ b/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampQuote.kt @@ -26,5 +26,6 @@ sealed class OnrampQuote { data class Error( override val paymentMethod: OnrampPaymentMethod, override val provider: OnrampProvider, + val error: OnrampError, ) : OnrampQuote() } \ No newline at end of file diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/analytics/OnrampAnalyticsEvent.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/analytics/OnrampAnalyticsEvent.kt index e577385a98..cf54baee5b 100644 --- a/domain/onramp/src/main/java/com/tangem/domain/onramp/analytics/OnrampAnalyticsEvent.kt +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/analytics/OnrampAnalyticsEvent.kt @@ -1,7 +1,6 @@ package com.tangem.domain.onramp.analytics import com.tangem.core.analytics.models.AnalyticsEvent -import com.tangem.core.analytics.models.AnalyticsParam.Key.CURRENCY import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_CODE import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_DESCRIPTION import com.tangem.core.analytics.models.AnalyticsParam.Key.PAYMENT_METHOD @@ -37,7 +36,7 @@ sealed class OnrampAnalyticsEvent( private val currency: String, ) : OnrampAnalyticsEvent( event = "Currency Chosen", - params = mapOf(CURRENCY to currency), + params = mapOf("Currency Type" to currency), ) data object CloseOnramp : OnrampAnalyticsEvent(event = "Button - Close") @@ -114,7 +113,7 @@ sealed class OnrampAnalyticsEvent( event = "Button - Buy", params = mapOf( PROVIDER to providerName, - CURRENCY to currency, + "Currency Type" to currency, TOKEN_PARAM to tokenSymbol, ), ) @@ -131,7 +130,7 @@ sealed class OnrampAnalyticsEvent( TOKEN_PARAM to tokenSymbol, PROVIDER to providerName, RESIDENCE to residence, - CURRENCY to currency, + "Currency Type" to currency, PAYMENT_METHOD to paymentMethod, ), ) @@ -143,11 +142,13 @@ sealed class OnrampAnalyticsEvent( private val tokenSymbol: String, private val errorCode: String, private val providerName: String?, + private val paymentMethod: String?, ) : OnrampAnalyticsEvent( event = "Errors", params = buildMap { put(TOKEN_PARAM, tokenSymbol) providerName?.let { put(PROVIDER, providerName) } + paymentMethod?.let { put(PAYMENT_METHOD, paymentMethod) } put(ERROR_CODE, errorCode) }, ) diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountStateFactory.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountStateFactory.kt index 70d7f41345..93b66cbc95 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountStateFactory.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountStateFactory.kt @@ -204,7 +204,7 @@ internal class OnrampAmountStateFactory( R.string.onramp_max_amount_restriction } is OnrampError.AmountError.TooSmallError -> { - analyticsEventHandler.send(OnrampAnalyticsEvent.MaxAmountError) + analyticsEventHandler.send(OnrampAnalyticsEvent.MinAmountError) R.string.onramp_min_amount_restriction } } diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt index a7955b8c84..ddcbb59d1c 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt @@ -81,7 +81,7 @@ internal class OnrampMainComponentModel @Inject constructor( private val _state: MutableStateFlow = MutableStateFlow( value = stateFactory.getInitialState( currency = params.cryptoCurrency.name, - onClose = router::pop, + onClose = ::onCloseClick, ), ) private val quotesTaskScheduler = SingleTaskScheduler() @@ -270,10 +270,13 @@ internal class OnrampMainComponentModel @Inject constructor( super.onDestroy() } + private fun onCloseClick() { + analyticsEventHandler.send(OnrampAnalyticsEvent.CloseOnramp) + router.pop() + } + private fun handleQuoteResult(quotes: List) { - quotes.filterIsInstance().forEach { errorState -> - sendOnrampErrorAnalytic(errorState.error) - } + sendOnrampQuotesErrorAnalytic(quotes) val quote = quotes.firstOrNull() @@ -346,9 +349,30 @@ internal class OnrampMainComponentModel @Inject constructor( error = error, tokenSymbol = params.cryptoCurrency.symbol, providerName = providerContent?.providerName, + paymentMethod = providerContent?.paymentMethod?.name, ) } + private fun sendOnrampQuotesErrorAnalytic(quotes: List) { + quotes.forEach { errorState -> + when (errorState) { + is OnrampQuote.Error -> analyticsEventHandler.sendOnrampErrorEvent( + error = errorState.error, + tokenSymbol = params.cryptoCurrency.symbol, + providerName = errorState.provider.info.name, + paymentMethod = errorState.paymentMethod.name, + ) + is OnrampQuote.AmountError -> analyticsEventHandler.sendOnrampErrorEvent( + error = errorState.error, + tokenSymbol = params.cryptoCurrency.symbol, + providerName = errorState.provider.info.name, + paymentMethod = errorState.paymentMethod.name, + ) + else -> { /* no-op */ } + } + } + } + private companion object { const val UPDATE_DELAY = 10_000L } diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/model/SelectProviderModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/model/SelectProviderModel.kt index e4b6bdb60b..1c94f39113 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/model/SelectProviderModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/model/SelectProviderModel.kt @@ -259,6 +259,7 @@ internal class SelectProviderModel @Inject constructor( error = error, tokenSymbol = params.cryptoCurrency.symbol, providerName = selectedProvider?.name, + paymentMethod = state.value.selectedPaymentMethod.paymentMethod.name, ) } diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/model/OnrampRedirectModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/model/OnrampRedirectModel.kt index 0ce73d2372..91b94beb8e 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/model/OnrampRedirectModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/model/OnrampRedirectModel.kt @@ -84,6 +84,7 @@ internal class OnrampRedirectModel @Inject constructor( error = error, tokenSymbol = params.cryptoCurrency.symbol, providerName = params.onrampProviderWithQuote.provider.info.name, + paymentMethod = params.onrampProviderWithQuote.paymentMethod.name, ) val contentMessage = ContentMessage { onDismiss -> BasicDialog( diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/model/OnrampSuccessComponentModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/model/OnrampSuccessComponentModel.kt index 348cbe0154..935b18a42f 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/model/OnrampSuccessComponentModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/model/OnrampSuccessComponentModel.kt @@ -81,6 +81,7 @@ internal class OnrampSuccessComponentModel @Inject constructor( error = error, tokenSymbol = cryptoCurrency.symbol, providerName = transaction.providerName, + paymentMethod = transaction.paymentMethod, ) Timber.e(error.toString()) }, @@ -101,7 +102,12 @@ internal class OnrampSuccessComponentModel @Inject constructor( goToProviderClick = ::goToProviderClick, ).convert(status) } - removeTransactionIfTerminalStatus(cryptoCurrency, transaction.providerName, status) + removeTransactionIfTerminalStatus( + cryptoCurrency = cryptoCurrency, + providerName = transaction.providerName, + paymentMethod = transaction.paymentMethod, + status = status, + ) }, ) } @@ -109,6 +115,7 @@ internal class OnrampSuccessComponentModel @Inject constructor( private fun removeTransactionIfTerminalStatus( cryptoCurrency: CryptoCurrency, providerName: String, + paymentMethod: String, status: OnrampStatus, ) { modelScope.launch { @@ -118,6 +125,7 @@ internal class OnrampSuccessComponentModel @Inject constructor( error = error, tokenSymbol = cryptoCurrency.symbol, providerName = providerName, + paymentMethod = paymentMethod, ) } } diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/utils/OnrampErrorAnalyticsSender.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/utils/OnrampErrorAnalyticsSender.kt index 5ca1b735b6..e9ec5c76c5 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/utils/OnrampErrorAnalyticsSender.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/utils/OnrampErrorAnalyticsSender.kt @@ -8,11 +8,13 @@ internal fun AnalyticsEventHandler.sendOnrampErrorEvent( error: OnrampError, tokenSymbol: String, providerName: String? = null, + paymentMethod: String? = null, ) = when (error) { is OnrampError.DataError -> send( OnrampAnalyticsEvent.Errors( tokenSymbol = tokenSymbol, providerName = providerName, + paymentMethod = paymentMethod, errorCode = error.code, ), )