Updated on 2026-08-14

This commit is contained in:
Tangem 2024-12-03 13:45:26 +05:00
parent a3e92038c7
commit 46eee92cea
27 changed files with 218 additions and 7 deletions

View file

@ -5,6 +5,7 @@ import com.tangem.blockchain.common.Blockchain
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.Analytics
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.settings.usercountry.models.UserCountry
import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.domain.tokens.model.CryptoCurrency
@ -56,14 +57,22 @@ object TradeCryptoMiddleware {
private fun proceedBuyAction(state: () -> AppState?, action: TradeCryptoAction.Buy) {
val isOnrampEnabled = store.inject(DaggerGraphState::onrampFeatureToggles).isFeatureEnabled
if (isOnrampEnabled) {
proceedWithOnramp(action.userWallet.walletId, action.cryptoCurrencyStatus.currency)
proceedWithOnramp(action.userWallet.walletId, action.cryptoCurrencyStatus.currency, action.source)
} else {
proceedWithLegacyBuyAction(state, action)
}
}
private fun proceedWithOnramp(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency) {
store.dispatchNavigationAction { push(AppRoute.Onramp(userWalletId = userWalletId, currency = cryptoCurrency)) }
private fun proceedWithOnramp(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency, source: OnrampSource) {
store.dispatchNavigationAction {
push(
AppRoute.Onramp(
userWalletId = userWalletId,
currency = cryptoCurrency,
source = source,
),
)
}
}
private fun proceedWithLegacyBuyAction(state: () -> AppState?, action: TradeCryptoAction.Buy) {

View file

@ -197,7 +197,11 @@ internal class ChildFactory @Inject constructor(
is AppRoute.Onramp -> {
route.asComponentChild(
contextProvider = contextProvider(route, contextFactory),
params = OnrampComponent.Params(userWalletId = route.userWalletId, cryptoCurrency = route.currency),
params = OnrampComponent.Params(
userWalletId = route.userWalletId,
cryptoCurrency = route.currency,
source = route.source,
),
componentFactory = onrampComponentFactory,
)
}

View file

@ -20,6 +20,7 @@ dependencies {
implementation(projects.domain.wallets.models)
implementation(projects.domain.staking.models)
implementation(projects.domain.markets.models)
implementation(projects.domain.onramp.models)
implementation(projects.domain.appCurrency.models)
/* Libs - Other */

View file

@ -8,6 +8,7 @@ import com.tangem.core.decompose.navigation.Route
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.markets.TokenMarketParams
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.qrscanning.models.SourceType
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.tokens.model.CryptoCurrency
@ -296,6 +297,7 @@ sealed class AppRoute(val path: String) : Route {
@Serializable
data class Onramp(
val source: OnrampSource,
val userWalletId: UserWalletId,
val currency: CryptoCurrency,
) : AppRoute(path = "/onramp/${userWalletId.stringValue}/${currency.symbol}"), RouteBundleParams {

View file

@ -5,6 +5,9 @@ plugins {
}
dependencies {
/** Core modules */
implementation(projects.core.analytics.models)
api(projects.domain.onramp.models)
api(projects.domain.tokens.models)
api(projects.domain.wallets.models)

View file

@ -0,0 +1,9 @@
package com.tangem.domain.onramp.model
// TODO: Move to features/onramp/api package after removing old buy logic. [REDACTED_JIRA]
enum class OnrampSource(val analyticsName: String) {
ACTION_BUTTONS("Main"),
TOKEN_LONG_TAP("Long Tap"),
TOKEN_DETAILS("Token"),
MARKETS("Markets"),
}

View file

@ -0,0 +1,104 @@
package com.tangem.domain.onramp.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.domain.onramp.model.OnrampSource
sealed class OnrampAnalyticsEvent(
event: String,
params: Map<String, String> = mapOf(),
) : AnalyticsEvent(
category = "Onramp",
event = event,
params = params,
) {
data class ScreenOpened(
val source: OnrampSource,
val cryptoCurrency: String,
) : OnrampAnalyticsEvent(
event = "Buy Screen Opened",
params = mapOf(
"Source" to source.analyticsName,
"Token" to cryptoCurrency,
),
)
data object SelectCurrencyScreenOpened : OnrampAnalyticsEvent(event = "Currency Screen Opened")
data class FiatCurrencyChosen(
private val currency: String,
) : OnrampAnalyticsEvent(
event = "Currency Chosen",
params = mapOf("Currency" to currency),
)
data object CloseOnramp : OnrampAnalyticsEvent(event = "Button - Close")
data object SettingsOpened : OnrampAnalyticsEvent(event = "Onramp Settings Screen Opened")
data object SelectResidenceOpened : OnrampAnalyticsEvent(event = "Residence Screen Opened")
data class OnResidenceChosen(
private val residence: String,
) : OnrampAnalyticsEvent(
event = "Residence Chosen",
params = mapOf("Residence" to residence),
)
data class ResidenceConfirmScreenOpened(
private val residence: String,
) : OnrampAnalyticsEvent(
event = "Residence Confirm Screen",
params = mapOf("Residence" to residence),
)
data object OnResidenceChange : OnrampAnalyticsEvent(event = "Button - Change")
data class OnResidenceConfirm(
private val residence: String,
) : OnrampAnalyticsEvent(
event = "Button - Confirm",
params = mapOf("Residence" to residence),
)
data object ProvidersScreenOpened : OnrampAnalyticsEvent(event = "Providers Screen Opened")
data class ProviderCalculated(
private val providerName: String,
private val cryptoCurrency: String,
) : OnrampAnalyticsEvent(
event = "Provider Calculated",
params = mapOf(
"Provider" to providerName,
"Token" to cryptoCurrency,
),
)
data object PaymentMethodsScreenOpened : OnrampAnalyticsEvent(event = "Payment Method Screen Opened")
data object OnPaymentMethodChosen : OnrampAnalyticsEvent(event = "Method Chosen")
data class OnProviderChosen(
private val providerName: String,
private val cryptoCurrency: String,
) : OnrampAnalyticsEvent(
event = "Provider Chosen",
params = mapOf(
"Provider" to providerName,
"Token" to cryptoCurrency,
),
)
data class OnBuyClick(
private val providerName: String,
private val currency: String,
private val cryptoCurrency: String,
) : OnrampAnalyticsEvent(
event = "Provider Chosen",
params = mapOf(
"Provider" to providerName,
"Currency" to currency,
"Token" to cryptoCurrency,
),
)
}

View file

@ -21,6 +21,7 @@ dependencies {
implementation(projects.domain.transaction.models)
implementation(projects.domain.wallets.models)
implementation(projects.domain.appCurrency.models)
implementation(projects.domain.onramp.models)
implementation(projects.domain.settings)
implementation(projects.features.swap.domain.api)
implementation(projects.features.swap.domain.models)

View file

@ -1,5 +1,6 @@
package com.tangem.domain.tokens.legacy
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.wallets.models.UserWallet
@ -13,6 +14,7 @@ sealed class TradeCryptoAction : Action {
data class Buy(
val userWallet: UserWallet,
val cryptoCurrencyStatus: CryptoCurrencyStatus,
val source: OnrampSource,
val appCurrencyCode: String,
val checkUserLocation: Boolean = true,
) : TradeCryptoAction()

View file

@ -26,6 +26,7 @@ dependencies {
implementation(projects.domain.feedback)
implementation(projects.domain.manageTokens)
implementation(projects.domain.markets)
implementation(projects.domain.onramp.models)
implementation(projects.domain.staking.models)
implementation(projects.domain.tokens)
implementation(projects.domain.tokens.models)

View file

@ -13,6 +13,7 @@ import com.tangem.core.ui.message.ContentMessage
import com.tangem.core.ui.message.SnackbarMessage
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.domain.tokens.model.TokenActionsState
@ -131,6 +132,7 @@ internal class TokenActionsHandler @AssistedInject constructor(
reduxStateHolder.dispatch(
TradeCryptoAction.Buy(
userWallet = cryptoCurrencyData.userWallet,
source = OnrampSource.MARKETS,
cryptoCurrencyStatus = cryptoCurrencyData.status,
appCurrencyCode = currentAppCurrency().code,
),

View file

@ -15,6 +15,7 @@ dependencies {
implementation(projects.core.ui)
/* Project - Domain */
implementation(projects.domain.onramp.models)
implementation(projects.domain.tokens.models)
implementation(projects.domain.wallets.models)

View file

@ -2,12 +2,13 @@ package com.tangem.features.onramp.component
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
interface OnrampComponent : ComposableContentComponent {
data class Params(val userWalletId: UserWalletId, val cryptoCurrency: CryptoCurrency)
data class Params(val userWalletId: UserWalletId, val cryptoCurrency: CryptoCurrency, val source: OnrampSource)
interface Factory : ComponentFactory<Params, OnrampComponent>
}

View file

@ -2,6 +2,7 @@ package com.tangem.features.onramp.confirmresidency.model
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ComponentScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -9,6 +10,7 @@ import com.tangem.core.decompose.navigation.Router
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.onramp.GetOnrampCountryUseCase
import com.tangem.domain.onramp.OnrampSaveDefaultCountryUseCase
import com.tangem.domain.onramp.analytics.OnrampAnalyticsEvent
import com.tangem.features.onramp.confirmresidency.ConfirmResidencyComponent
import com.tangem.features.onramp.confirmresidency.entity.ConfirmResidencyBottomSheetConfig
import com.tangem.features.onramp.confirmresidency.entity.ConfirmResidencyUM
@ -23,6 +25,7 @@ import javax.inject.Inject
@ComponentScoped
internal class ConfirmResidencyModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventHandler: AnalyticsEventHandler,
private val router: Router,
private val saveDefaultCountryUseCase: OnrampSaveDefaultCountryUseCase,
getOnrampCountryUseCase: GetOnrampCountryUseCase,
@ -45,6 +48,7 @@ internal class ConfirmResidencyModel @Inject constructor(
)
init {
analyticsEventHandler.send(OnrampAnalyticsEvent.ResidenceConfirmScreenOpened(params.country.name))
getOnrampCountryUseCase.invoke()
.onEach { maybeCountry ->
val country = maybeCountry.getOrNull()
@ -58,18 +62,23 @@ internal class ConfirmResidencyModel @Inject constructor(
private fun getPrimaryButtonConfig() = if (params.country.onrampAvailable) {
ConfirmResidencyUM.ActionButtonConfig(
onClick = {
analyticsEventHandler.send(OnrampAnalyticsEvent.OnResidenceConfirm(params.country.name))
modelScope.launch { saveDefaultCountryUseCase.invoke(params.country) }
},
text = resourceReference(R.string.common_confirm),
)
} else {
ConfirmResidencyUM.ActionButtonConfig(
onClick = router::pop,
onClick = {
analyticsEventHandler.send(OnrampAnalyticsEvent.CloseOnramp)
router.pop()
},
text = resourceReference(R.string.common_close),
)
}
private fun onChangeClick() {
analyticsEventHandler.send(OnrampAnalyticsEvent.OnResidenceChange)
bottomSheetNavigation.activate(ConfirmResidencyBottomSheetConfig.SelectCountry)
}
}

View file

@ -24,7 +24,7 @@ import dagger.assisted.AssistedInject
internal class DefaultOnrampMainComponent @AssistedInject constructor(
@Assisted appComponentContext: AppComponentContext,
@Assisted params: OnrampMainComponent.Params,
@Assisted private val params: OnrampMainComponent.Params,
private val confirmResidencyComponentFactory: ConfirmResidencyComponent.Factory,
private val selectCurrencyComponentFactory: SelectCurrencyComponent.Factory,
private val selectProviderComponentFactory: SelectProviderComponent.Factory,
@ -68,6 +68,7 @@ internal class DefaultOnrampMainComponent @AssistedInject constructor(
onProviderClick = model::onProviderSelected,
onDismiss = model.bottomSheetNavigation::dismiss,
selectedPaymentMethod = config.selectedPaymentMethod,
cryptoCurrency = params.cryptoCurrency,
),
)
}

View file

@ -3,12 +3,14 @@ package com.tangem.features.onramp.main
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.onramp.model.OnrampProviderWithQuote
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.tokens.model.CryptoCurrency
internal interface OnrampMainComponent : ComposableContentComponent {
data class Params(
val cryptoCurrency: CryptoCurrency,
val source: OnrampSource,
val openSettings: () -> Unit,
val openRedirectPage: (quote: OnrampProviderWithQuote.Data) -> Unit,
)

View file

@ -2,10 +2,12 @@ package com.tangem.features.onramp.main.model
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.domain.onramp.*
import com.tangem.domain.onramp.analytics.OnrampAnalyticsEvent
import com.tangem.domain.onramp.model.OnrampAvailability
import com.tangem.domain.onramp.model.OnrampCurrency
import com.tangem.domain.onramp.model.OnrampProviderWithQuote
@ -27,6 +29,7 @@ import javax.inject.Inject
@Suppress("LongParameterList")
internal class OnrampMainComponentModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventHandler: AnalyticsEventHandler,
private val router: Router,
private val checkOnrampAvailabilityUseCase: CheckOnrampAvailabilityUseCase,
private val getOnrampCurrencyUseCase: GetOnrampCurrencyUseCase,
@ -58,10 +61,20 @@ internal class OnrampMainComponentModel @Inject constructor(
val bottomSheetNavigation: SlotNavigation<OnrampMainBottomSheetConfig> = SlotNavigation()
init {
sendScreenOpenAnalytics()
checkResidenceCountry()
subscribeToAmountChanges()
}
private fun sendScreenOpenAnalytics() {
analyticsEventHandler.send(
OnrampAnalyticsEvent.ScreenOpened(
source = params.source,
cryptoCurrency = params.cryptoCurrency.name,
),
)
}
fun onProviderSelected(providerWithQuote: OnrampProviderWithQuote.Data) {
_state.update { amountStateFactory.getAmountSecondaryUpdatedState(providerWithQuote) }
}
@ -132,10 +145,19 @@ internal class OnrampMainComponentModel @Inject constructor(
}
override fun onBuyClick(quote: OnrampProviderWithQuote.Data) {
val currentContentState = state.value as? OnrampMainComponentUM.Content ?: return
analyticsEventHandler.send(
OnrampAnalyticsEvent.OnBuyClick(
providerName = quote.provider.info.name,
currency = currentContentState.amountBlockState.currencyUM.code,
cryptoCurrency = params.cryptoCurrency.name,
),
)
params.openRedirectPage(quote)
}
override fun openCurrenciesList() {
analyticsEventHandler.send(OnrampAnalyticsEvent.SelectCurrencyScreenOpened)
bottomSheetNavigation.activate(OnrampMainBottomSheetConfig.CurrenciesList)
}

View file

@ -4,6 +4,7 @@ import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.domain.onramp.model.OnrampPaymentMethod
import com.tangem.domain.onramp.model.OnrampProviderWithQuote
import com.tangem.domain.tokens.model.CryptoCurrency
internal interface SelectProviderComponent : ComposableBottomSheetComponent {
@ -11,6 +12,7 @@ internal interface SelectProviderComponent : ComposableBottomSheetComponent {
val onProviderClick: (OnrampProviderWithQuote.Data) -> Unit,
val onDismiss: () -> Unit,
val selectedPaymentMethod: OnrampPaymentMethod,
val cryptoCurrency: CryptoCurrency,
)
interface Factory : ComponentFactory<Params, SelectProviderComponent>

View file

@ -3,6 +3,7 @@ package com.tangem.features.onramp.providers.model
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
import com.arkivanov.decompose.router.slot.dismiss
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ComponentScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -15,6 +16,7 @@ import com.tangem.domain.onramp.GetOnrampPaymentMethodsUseCase
import com.tangem.domain.onramp.GetOnrampProviderWithQuoteUseCase
import com.tangem.domain.onramp.GetOnrampSelectedPaymentMethodUseCase
import com.tangem.domain.onramp.OnrampSaveSelectedPaymentMethod
import com.tangem.domain.onramp.analytics.OnrampAnalyticsEvent
import com.tangem.domain.onramp.model.OnrampPaymentMethod
import com.tangem.domain.onramp.model.OnrampProviderWithQuote
import com.tangem.features.onramp.impl.R
@ -31,9 +33,11 @@ import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@Suppress("LongParameterList")
@ComponentScoped
internal class SelectProviderModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventHandler: AnalyticsEventHandler,
private val getSelectedPaymentMethodsUseCase: GetOnrampPaymentMethodsUseCase,
private val getOnrampSelectedPaymentMethodUseCase: GetOnrampSelectedPaymentMethodUseCase,
private val getOnrampProviderWithQuoteUseCase: GetOnrampProviderWithQuoteUseCase,
@ -47,6 +51,7 @@ internal class SelectProviderModel @Inject constructor(
private val _state = MutableStateFlow(getInitialState())
init {
analyticsEventHandler.send(OnrampAnalyticsEvent.ProvidersScreenOpened)
getProviders(params.selectedPaymentMethod)
subscribeToPaymentMethodUpdates()
}
@ -80,6 +85,7 @@ internal class SelectProviderModel @Inject constructor(
}
private fun openPaymentMethods() {
analyticsEventHandler.send(OnrampAnalyticsEvent.PaymentMethodsScreenOpened)
modelScope.launch {
val methods = getSelectedPaymentMethodsUseCase.invoke().getOrNull().orEmpty()
bottomSheetNavigation.activate(
@ -101,6 +107,7 @@ internal class SelectProviderModel @Inject constructor(
}
private fun onPaymentMethodSelected(paymentMethod: OnrampPaymentMethod) {
analyticsEventHandler.send(OnrampAnalyticsEvent.OnPaymentMethodChosen)
modelScope.launch {
saveSelectedPaymentMethod.invoke(paymentMethod)
_state.update { state ->
@ -128,6 +135,12 @@ internal class SelectProviderModel @Inject constructor(
rate = rate,
isSelected = index == 0,
onClick = {
analyticsEventHandler.send(
OnrampAnalyticsEvent.OnProviderChosen(
providerName = quote.provider.info.name,
cryptoCurrency = params.cryptoCurrency.name,
),
)
params.onProviderClick(quote)
params.onDismiss()
},

View file

@ -67,6 +67,7 @@ internal class DefaultOnrampComponent @AssistedInject constructor(
params = OnrampMainComponent.Params(
cryptoCurrency = params.cryptoCurrency,
openSettings = { navigation.push(OnrampChild.Settings) },
source = params.source,
openRedirectPage = {
navigation.push(
OnrampChild.RedirectPage(

View file

@ -1,5 +1,6 @@
package com.tangem.features.onramp.selectcountry.model
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ComponentScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -8,6 +9,7 @@ import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.onramp.GetOnrampCountriesUseCase
import com.tangem.domain.onramp.GetOnrampCountryUseCase
import com.tangem.domain.onramp.OnrampSaveDefaultCountryUseCase
import com.tangem.domain.onramp.analytics.OnrampAnalyticsEvent
import com.tangem.domain.onramp.model.OnrampCountry
import com.tangem.features.onramp.impl.R
import com.tangem.features.onramp.selectcountry.SelectCountryComponent
@ -27,9 +29,11 @@ import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject
@Suppress("LongParameterList")
@ComponentScoped
internal class OnrampSelectCountryModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventHandler: AnalyticsEventHandler,
private val searchManager: InputManager,
private val getOnrampCountriesUseCase: GetOnrampCountriesUseCase,
private val saveDefaultCountryUseCase: OnrampSaveDefaultCountryUseCase,
@ -46,6 +50,7 @@ internal class OnrampSelectCountryModel @Inject constructor(
private val refreshTrigger = MutableSharedFlow<Unit>()
init {
analyticsEventHandler.send(OnrampAnalyticsEvent.SelectResidenceOpened)
modelScope.launch { subscribeOnUpdateState() }
}
@ -73,6 +78,7 @@ internal class OnrampSelectCountryModel @Inject constructor(
}
private fun saveCountry(country: OnrampCountry) {
analyticsEventHandler.send(OnrampAnalyticsEvent.OnResidenceChosen(country.name))
modelScope.launch {
saveDefaultCountryUseCase.invoke(country)
dismiss()

View file

@ -1,5 +1,6 @@
package com.tangem.features.onramp.selectcurrency.model
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ComponentScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -8,6 +9,7 @@ import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.onramp.GetOnrampCurrenciesUseCase
import com.tangem.domain.onramp.OnrampSaveDefaultCurrencyUseCase
import com.tangem.domain.onramp.analytics.OnrampAnalyticsEvent
import com.tangem.domain.onramp.model.OnrampCurrency
import com.tangem.features.onramp.impl.R
import com.tangem.features.onramp.selectcurrency.SelectCurrencyComponent
@ -31,6 +33,7 @@ import javax.inject.Inject
@ComponentScoped
internal class OnrampSelectCurrencyModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventHandler: AnalyticsEventHandler,
private val searchManager: InputManager,
private val getOnrampCurrenciesUseCase: GetOnrampCurrenciesUseCase,
private val saveDefaultCurrencyUseCase: OnrampSaveDefaultCurrencyUseCase,
@ -72,6 +75,7 @@ internal class OnrampSelectCurrencyModel @Inject constructor(
}
private fun saveDefaultCurrency(currency: OnrampCurrency) {
analyticsEventHandler.send(OnrampAnalyticsEvent.FiatCurrencyChosen(currency.code))
modelScope.launch {
saveDefaultCurrencyUseCase.invoke(currency)
dismiss()

View file

@ -18,6 +18,7 @@ import com.tangem.core.ui.message.ContentMessage
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
@ -118,6 +119,7 @@ internal class OnrampOperationModel @Inject constructor(
return TradeCryptoAction.Buy(
userWallet = selectedUserWallet,
cryptoCurrencyStatus = status,
source = OnrampSource.ACTION_BUTTONS,
appCurrencyCode = appCurrencyCode,
)
}

View file

@ -3,10 +3,12 @@ package com.tangem.features.onramp.settings.model
import arrow.core.Either
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ComponentScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.domain.onramp.GetOnrampCountryUseCase
import com.tangem.domain.onramp.analytics.OnrampAnalyticsEvent
import com.tangem.domain.onramp.model.OnrampCountry
import com.tangem.features.onramp.settings.OnrampSettingsComponent
import com.tangem.features.onramp.settings.entity.OnrampSettingsConfig
@ -20,6 +22,7 @@ import javax.inject.Inject
@ComponentScoped
internal class OnrampSettingsModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventHandler: AnalyticsEventHandler,
private val getOnrampCountryUseCase: GetOnrampCountryUseCase,
paramsContainer: ParamsContainer,
) : Model() {
@ -31,6 +34,7 @@ internal class OnrampSettingsModel @Inject constructor(
private val _state: MutableStateFlow<OnrampSettingsUM> = MutableStateFlow(getInitialState())
init {
analyticsEventHandler.send(OnrampAnalyticsEvent.SettingsOpened)
subscribeOnUpdateState()
}

View file

@ -29,6 +29,7 @@ import com.tangem.domain.card.GetExtendedPublicKeyForCurrencyUseCase
import com.tangem.domain.card.NetworkHasDerivationUseCase
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.settings.ShouldShowSwapPromoTokenUseCase
import com.tangem.domain.staking.GetStakingAvailabilityUseCase
@ -441,6 +442,7 @@ internal class TokenDetailsViewModel @Inject constructor(
reduxStateHolder.dispatch(
TradeCryptoAction.Buy(
userWallet = userWallet,
source = OnrampSource.TOKEN_DETAILS,
cryptoCurrencyStatus = status,
appCurrencyCode = selectedAppCurrencyFlow.value.code,
),

View file

@ -81,6 +81,7 @@ dependencies {
implementation(projects.domain.staking.models)
implementation(projects.domain.markets.models)
implementation(projects.domain.feedback)
implementation(projects.domain.onramp.models)
//TODO: Create api/impl modules for onboarding [REDACTED_JIRA]
implementation(projects.features.onboarding)

View file

@ -26,6 +26,7 @@ import com.tangem.domain.core.utils.lceError
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.markets.TokenMarketParams
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
import com.tangem.domain.settings.usercountry.models.UserCountry
@ -374,6 +375,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
reduxStateHolder.dispatch(
TradeCryptoAction.Buy(
userWallet = userWallet,
source = OnrampSource.TOKEN_LONG_TAP,
cryptoCurrencyStatus = cryptoCurrencyStatus,
appCurrencyCode = getSelectedAppCurrencyUseCase.unwrap().code,
),