Updated on 2026-08-14

This commit is contained in:
Tangem 2025-02-27 19:43:34 +03:00
parent 76e17fc21f
commit f9cc3decfb
12 changed files with 353 additions and 144 deletions

View file

@ -10,6 +10,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.core.lce.Lce
import com.tangem.domain.core.utils.getOrElse
import com.tangem.domain.exchange.ExchangeableState
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
import com.tangem.domain.settings.usercountry.models.UserCountry
@ -241,10 +242,21 @@ internal class OnrampTokenListModel @Inject constructor(
val isAvailable = rampStateManager.availableForSwap(
userWalletId = params.userWalletId,
cryptoCurrency = status.currency,
)
).isSwapAvailable() && !status.currency.isCustom
isAvailable && status.value !is CryptoCurrencyStatus.NoQuote
}
}
}
private fun ExchangeableState.isSwapAvailable(): Boolean {
return when (this) {
ExchangeableState.AssetNotFound,
ExchangeableState.Error,
ExchangeableState.Loading,
ExchangeableState.NotExchangeable,
-> false
ExchangeableState.Exchangeable -> true
}
}
}

View file

@ -45,10 +45,7 @@ import com.tangem.domain.staking.GetYieldUseCase
import com.tangem.domain.staking.model.StakingAvailability
import com.tangem.domain.tokens.*
import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.NetworkAddress
import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason
import com.tangem.domain.tokens.model.*
import com.tangem.domain.tokens.model.analytics.TokenReceiveAnalyticsEvent
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.toReasonAnalyticsText
@ -281,6 +278,7 @@ internal class TokenDetailsViewModel @Inject constructor(
.conflate()
.distinctUntilChanged()
.onEach {
sendButtonsEvents(it.states)
internalUiState.value = stateFactory.getManageButtonsState(actions = it.states)
}
.flowOn(dispatchers.main)
@ -288,6 +286,21 @@ internal class TokenDetailsViewModel @Inject constructor(
.saveIn(buttonsJobHolder)
}
private fun sendButtonsEvents(states: List<TokenActionsState.ActionState>) {
// for now send only for swap
val swapState = states.firstOrNull { it is TokenActionsState.ActionState.Swap } ?: return
if (swapState.unavailabilityReason != ScenarioUnavailabilityReason.None) {
analyticsEventsHandler.send(
TokenScreenAnalyticsEvent.ActionButtonDisabled(
token = cryptoCurrency.symbol,
status = swapState.unavailabilityReason.toReasonAnalyticsText(),
blockchain = cryptoCurrency.network.name,
action = "Swap",
),
)
}
}
private fun updateWarnings(cryptoCurrencyStatus: CryptoCurrencyStatus) {
viewModelScope.launch(dispatchers.main) {
getCurrencyWarningsUseCase.invoke(
@ -472,14 +485,15 @@ internal class TokenDetailsViewModel @Inject constructor(
}
override fun onBuyClick(unavailabilityReason: ScenarioUnavailabilityReason) {
analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonBuy(cryptoCurrency.symbol))
analyticsEventsHandler.send(
TokenScreenAnalyticsEvent.ButtonWithParams.ButtonBuy(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
status = unavailabilityReason.toReasonAnalyticsText(),
),
)
if (handleUnavailabilityReason(
unavailabilityReason = unavailabilityReason,
tokenSymbol = cryptoCurrency.symbol,
tokenAction = TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction.BuyAction,
)
) {
if (handleUnavailabilityReason(unavailabilityReason = unavailabilityReason)) {
return
}
@ -512,7 +526,13 @@ internal class TokenDetailsViewModel @Inject constructor(
}
override fun onBuyCoinClick(cryptoCurrency: CryptoCurrency) {
analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonBuy(cryptoCurrency.symbol))
analyticsEventsHandler.send(
TokenScreenAnalyticsEvent.ButtonWithParams.ButtonBuy(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
status = null,
),
)
router.openTokenDetails(userWalletId = userWalletId, currency = cryptoCurrency)
}
@ -528,14 +548,15 @@ internal class TokenDetailsViewModel @Inject constructor(
}
override fun onSendClick(unavailabilityReason: ScenarioUnavailabilityReason) {
analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonSend(cryptoCurrency.symbol))
analyticsEventsHandler.send(
TokenScreenAnalyticsEvent.ButtonWithParams.ButtonSend(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
status = unavailabilityReason.toReasonAnalyticsText(),
),
)
if (handleUnavailabilityReason(
unavailabilityReason = unavailabilityReason,
tokenSymbol = cryptoCurrency.symbol,
tokenAction = TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction.SendAction,
)
) {
if (handleUnavailabilityReason(unavailabilityReason = unavailabilityReason)) {
return
}
@ -554,17 +575,18 @@ internal class TokenDetailsViewModel @Inject constructor(
override fun onReceiveClick(unavailabilityReason: ScenarioUnavailabilityReason) {
val networkAddress = cryptoCurrencyStatus?.value?.networkAddress ?: return
if (handleUnavailabilityReason(
unavailabilityReason = unavailabilityReason,
tokenSymbol = cryptoCurrency.symbol,
tokenAction = TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction.ReceiveAction,
)
) {
if (handleUnavailabilityReason(unavailabilityReason = unavailabilityReason)) {
return
}
viewModelScope.launch(dispatchers.main) {
analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonReceive(cryptoCurrency.symbol))
analyticsEventsHandler.send(
TokenScreenAnalyticsEvent.ButtonWithParams.ButtonReceive(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
status = unavailabilityReason.toReasonAnalyticsText(),
),
)
analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ReceiveScreenOpened(cryptoCurrency.symbol))
internalUiState.value = stateFactory.getStateWithReceiveBottomSheet(
@ -583,12 +605,7 @@ internal class TokenDetailsViewModel @Inject constructor(
}
override fun onStakeClick(unavailabilityReason: ScenarioUnavailabilityReason) {
if (handleUnavailabilityReason(
unavailabilityReason = unavailabilityReason,
tokenSymbol = cryptoCurrency.symbol,
tokenAction = null,
)
) {
if (handleUnavailabilityReason(unavailabilityReason = unavailabilityReason)) {
return
}
@ -619,14 +636,15 @@ internal class TokenDetailsViewModel @Inject constructor(
}
override fun onSellClick(unavailabilityReason: ScenarioUnavailabilityReason) {
analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonSell(cryptoCurrency.symbol))
analyticsEventsHandler.send(
TokenScreenAnalyticsEvent.ButtonWithParams.ButtonSell(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
status = unavailabilityReason.toReasonAnalyticsText(),
),
)
if (handleUnavailabilityReason(
unavailabilityReason = unavailabilityReason,
tokenSymbol = cryptoCurrency.symbol,
tokenAction = TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction.SellAction,
)
) {
if (handleUnavailabilityReason(unavailabilityReason = unavailabilityReason)) {
return
}
@ -643,14 +661,15 @@ internal class TokenDetailsViewModel @Inject constructor(
}
override fun onSwapClick(unavailabilityReason: ScenarioUnavailabilityReason) {
analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonExchange(cryptoCurrency.symbol))
analyticsEventsHandler.send(
TokenScreenAnalyticsEvent.ButtonWithParams.ButtonExchange(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
status = unavailabilityReason.toReasonAnalyticsText(),
),
)
if (handleUnavailabilityReason(
unavailabilityReason = unavailabilityReason,
tokenSymbol = cryptoCurrency.symbol,
tokenAction = TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction.SwapAction,
)
) {
if (handleUnavailabilityReason(unavailabilityReason = unavailabilityReason)) {
return
}
@ -972,21 +991,8 @@ internal class TokenDetailsViewModel @Inject constructor(
internalUiState.value = stateFactory.getStateWithClosedBottomSheet()
}
private fun handleUnavailabilityReason(
unavailabilityReason: ScenarioUnavailabilityReason,
tokenSymbol: String,
tokenAction: TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction?,
): Boolean {
private fun handleUnavailabilityReason(unavailabilityReason: ScenarioUnavailabilityReason): Boolean {
if (unavailabilityReason == ScenarioUnavailabilityReason.None) return false
if (tokenAction != null) {
analyticsEventsHandler.send(
TokenScreenAnalyticsEvent.NoticeActionInactive(
token = tokenSymbol,
tokenAction = tokenAction,
reason = unavailabilityReason.toReasonAnalyticsText(),
),
)
}
internalUiState.value = stateFactory.getStateWithActionButtonErrorDialog(unavailabilityReason)

View file

@ -39,6 +39,8 @@ import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.domain.tokens.model.*
import com.tangem.domain.tokens.model.analytics.TokenReceiveAnalyticsEvent
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.AVAILABLE
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.toReasonAnalyticsText
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.usecase.GetExploreUrlUseCase
@ -133,7 +135,11 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
analyticsEventHandler.send(
event = TokenScreenAnalyticsEvent.ButtonSend(cryptoCurrencyStatus.currency.symbol),
event = TokenScreenAnalyticsEvent.ButtonWithParams.ButtonSend(
token = cryptoCurrencyStatus.currency.symbol,
status = unavailabilityReason.toReasonAnalyticsText(),
blockchain = cryptoCurrencyStatus.currency.network.name,
),
)
if (handleUnavailabilityReason(unavailabilityReason)) return
@ -151,7 +157,11 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
val userWalletId = stateHolder.getSelectedWalletId()
analyticsEventHandler.send(
event = TokenScreenAnalyticsEvent.ButtonReceive(cryptoCurrencyStatus.currency.symbol),
event = TokenScreenAnalyticsEvent.ButtonWithParams.ButtonReceive(
token = cryptoCurrencyStatus.currency.symbol,
status = AVAILABLE,
blockchain = cryptoCurrencyStatus.currency.network.name,
),
)
analyticsEventHandler.send(
@ -290,7 +300,11 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
unavailabilityReason: ScenarioUnavailabilityReason,
) {
analyticsEventHandler.send(
event = TokenScreenAnalyticsEvent.ButtonSell(cryptoCurrencyStatus.currency.symbol),
event = TokenScreenAnalyticsEvent.ButtonWithParams.ButtonSell(
token = cryptoCurrencyStatus.currency.symbol,
status = unavailabilityReason.toReasonAnalyticsText(),
blockchain = cryptoCurrencyStatus.currency.network.name,
),
)
if (handleUnavailabilityReason(unavailabilityReason)) return
@ -314,7 +328,11 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
analyticsEventHandler.send(
event = TokenScreenAnalyticsEvent.ButtonBuy(cryptoCurrencyStatus.currency.symbol),
event = TokenScreenAnalyticsEvent.ButtonWithParams.ButtonBuy(
token = cryptoCurrencyStatus.currency.symbol,
status = unavailabilityReason.toReasonAnalyticsText(),
blockchain = cryptoCurrencyStatus.currency.network.name,
),
)
if (handleUnavailabilityReason(unavailabilityReason)) return
@ -349,7 +367,11 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
unavailabilityReason: ScenarioUnavailabilityReason,
) {
analyticsEventHandler.send(
event = TokenScreenAnalyticsEvent.ButtonExchange(cryptoCurrencyStatus.currency.symbol),
event = TokenScreenAnalyticsEvent.ButtonWithParams.ButtonExchange(
token = cryptoCurrencyStatus.currency.symbol,
status = unavailabilityReason.toReasonAnalyticsText(),
blockchain = cryptoCurrencyStatus.currency.network.name,
),
)
if (handleUnavailabilityReason(unavailabilityReason)) return