Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-25 16:39:35 +03:00
commit bfd903b43c
595 changed files with 12755 additions and 19837 deletions

View file

@ -23,6 +23,7 @@ import com.tangem.domain.tokens.wallet.WalletBalanceFetcher
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.SelectWalletUseCase
import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnalyticEvents
import com.tangem.features.tangempay.TangemPayFeatureToggles
import com.tangem.features.tokendetails.deeplink.TokenDetailsDeepLinkHandler
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionTrigger
import dagger.assisted.Assisted
@ -48,6 +49,7 @@ internal class DefaultTokenDetailsDeepLinkHandler @AssistedInject constructor(
private val getUserWalletUseCase: GetUserWalletUseCase,
private val walletBalanceFetcher: WalletBalanceFetcher,
private val accountsFeatureToggles: AccountsFeatureToggles,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
) : TokenDetailsDeepLinkHandler {
@ -128,7 +130,10 @@ internal class DefaultTokenDetailsDeepLinkHandler @AssistedInject constructor(
id = cryptoCurrency.id,
)
!isMultiCurrency -> walletBalanceFetcher(
params = WalletBalanceFetcher.Params(userWalletId = userWallet.walletId),
params = WalletBalanceFetcher.Params(
userWalletId = userWallet.walletId,
isPaymentAccountRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
),
)
}
}

View file

@ -176,7 +176,6 @@ internal object TokenDetailsPreviewData {
bottomSheetConfig = null,
isBalanceHidden = false,
isMarketPriceAvailable = false,
isYieldSupplyFeatureEnabled = false,
)
val tokenDetailsState_2 = TokenDetailsState(
@ -202,7 +201,6 @@ internal object TokenDetailsPreviewData {
bottomSheetConfig = null,
isBalanceHidden = false,
isMarketPriceAvailable = true,
isYieldSupplyFeatureEnabled = true,
)
val tokenDetailsState_3 = tokenDetailsState_2.copy(stakingBlocksState = stakingBalanceBlock)

View file

@ -18,11 +18,13 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.api.AnalyticsExceptionHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.ExceptionAnalyticsEvent
import com.tangem.core.analytics.models.event.OfframpAnalyticsEvent
import com.tangem.core.decompose.di.GlobalUiMessageSender
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.clipboard.ClipboardManager
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
@ -47,15 +49,14 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.NetworkAddress
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.offramp.GetOfframpUrlUseCase
import com.tangem.domain.onramp.model.OnrampSource
import com.tangem.domain.promo.ShouldShowPromoTokenUseCase
import com.tangem.domain.promo.models.PromoId
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.staking.GetStakingAvailabilityUseCase
import com.tangem.domain.staking.GetStakingEntryInfoUseCase
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.ScenarioUnavailabilityReason
import com.tangem.domain.tokens.model.TokenActionsState
import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent
@ -91,7 +92,6 @@ import com.tangem.features.tokendetails.TokenDetailsComponent
import com.tangem.features.tokendetails.impl.R
import com.tangem.features.txhistory.entity.TxHistoryContentUpdateEmitter
import com.tangem.features.yield.supply.api.YieldSupplyDepositedWarningComponent
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.utils.Provider
import com.tangem.utils.coroutines.*
@ -130,7 +130,8 @@ internal class TokenDetailsModel @Inject constructor(
private val retryIncompleteTransactionUseCase: RetryIncompleteTransactionUseCase,
private val openTrustlineUseCase: OpenTrustlineUseCase,
private val dismissIncompleteTransactionUseCase: DismissIncompleteTransactionUseCase,
private val reduxStateHolder: ReduxStateHolder,
private val getOfframpUrlUseCase: GetOfframpUrlUseCase,
private val urlOpener: UrlOpener,
private val analyticsEventsHandler: AnalyticsEventHandler,
private val vibratorHapticManager: VibratorHapticManager,
private val clipboardManager: ClipboardManager,
@ -144,7 +145,6 @@ internal class TokenDetailsModel @Inject constructor(
private val tokenDetailsDeepLinkActionListener: TokenDetailsDeepLinkActionListener,
private val analyticsExceptionHandler: AnalyticsExceptionHandler,
private val receiveAddressesFactory: ReceiveAddressesFactory,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
private val saveViewedYieldSupplyWarningUseCase: SaveViewedYieldSupplyWarningUseCase,
private val saveViewedTokenReceiveWarningUseCase: SaveViewedTokenReceiveWarningUseCase,
private val needShowYieldSupplyDepositedWarningUseCase: NeedShowYieldSupplyDepositedWarningUseCase,
@ -193,7 +193,6 @@ internal class TokenDetailsModel @Inject constructor(
networkHasDerivationUseCase = networkHasDerivationUseCase,
getUserWalletUseCase = getUserWalletUseCase,
userWalletId = userWalletId,
yieldSupplyFeatureToggles = yieldSupplyFeatureToggles,
)
private val internalUiState = MutableStateFlow(stateFactory.getInitialState(cryptoCurrency))
@ -423,9 +422,7 @@ internal class TokenDetailsModel @Inject constructor(
}
private fun subscribeOnYieldSupplyBalanceIfActive(status: CryptoCurrencyStatus) {
if (yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled &&
status.value.yieldSupplyStatus?.isActive == true
) {
if (status.value.yieldSupplyStatus?.isActive == true) {
if (yieldSupplyBalanceJobHolder.isActive && status.value.sources.networkSource != StatusSource.ACTUAL) {
return
}
@ -709,12 +706,13 @@ internal class TokenDetailsModel @Inject constructor(
showErrorIfDemoModeOrElse {
val status = cryptoCurrencyStatus ?: return@showErrorIfDemoModeOrElse
reduxStateHolder.dispatch(
TradeCryptoAction.Sell(
cryptoCurrencyStatus = status,
appCurrencyCode = selectedAppCurrencyFlow.value.code,
),
)
getOfframpUrlUseCase(
cryptoCurrencyStatus = status,
appCurrencyCode = selectedAppCurrencyFlow.value.code,
).onRight { url ->
urlOpener.openUrl(url)
analyticsEventsHandler.send(OfframpAnalyticsEvent.ScreenOpened)
}
}
}
@ -1235,13 +1233,11 @@ internal class TokenDetailsModel @Inject constructor(
}
private suspend fun needShowYieldSupplyWarning(): Boolean {
return yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled &&
needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus)
return needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus)
}
private fun isActiveYieldSupply(): Boolean {
return yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled &&
cryptoCurrencyStatus?.value?.yieldSupplyStatus?.isActive == true
return cryptoCurrencyStatus?.value?.yieldSupplyStatus?.isActive == true
}
override fun onYieldSupplyWarningAcknowledged(tokenAction: TokenAction) {

View file

@ -23,5 +23,4 @@ internal data class TokenDetailsState(
val bottomSheetConfig: TangemBottomSheetConfig?,
val isBalanceHidden: Boolean,
val isMarketPriceAvailable: Boolean,
val isYieldSupplyFeatureEnabled: Boolean,
)

View file

@ -19,7 +19,6 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDeta
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsYieldSupplyState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification
import com.tangem.feature.tokendetails.presentation.tokendetails.state.utils.getBalance
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import com.tangem.utils.Provider
import com.tangem.utils.StringsSigns.DASH_SIGN
import com.tangem.utils.converter.Converter
@ -31,7 +30,6 @@ internal class TokenDetailsLoadedBalanceConverter(
private val currentStateProvider: Provider<TokenDetailsState>,
private val appCurrencyProvider: Provider<AppCurrency>,
private val clickIntents: TokenDetailsClickIntents,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
) : Converter<Either<CurrencyStatusError, CryptoCurrencyStatus>, TokenDetailsState> {
override fun convert(value: Either<CurrencyStatusError, CryptoCurrencyStatus>): TokenDetailsState {
@ -113,10 +111,7 @@ internal class TokenDetailsLoadedBalanceConverter(
selectedBalanceType = currentState.selectedBalanceType,
isBalanceSelectorEnabled = isBalanceSelectorEnabled,
isBalanceFlickering = status.value.isFlickering(),
yieldSupplyState =
if (yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled &&
status.value.yieldSupplyStatus?.isActive == true
) {
yieldSupplyState = if (status.value.yieldSupplyStatus?.isActive == true) {
TokenDetailsYieldSupplyState.Active(clickIntents::onYieldInfoClick)
} else {
TokenDetailsYieldSupplyState.Empty

View file

@ -19,7 +19,6 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDeta
import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton
import com.tangem.features.tokendetails.impl.R
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import com.tangem.lib.crypto.BlockchainUtils.isBitcoin
import com.tangem.utils.converter.Converter
import kotlinx.collections.immutable.ImmutableList
@ -31,7 +30,6 @@ internal class TokenDetailsSkeletonStateConverter(
private val networkHasDerivationUseCase: NetworkHasDerivationUseCase,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val userWalletId: UserWalletId,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
) : Converter<CryptoCurrency, TokenDetailsState> {
private val iconStateConverter by lazy { TokenDetailsIconStateConverter() }
@ -72,7 +70,6 @@ internal class TokenDetailsSkeletonStateConverter(
bottomSheetConfig = null,
isBalanceHidden = true,
isMarketPriceAvailable = value.id.rawCurrencyId != null,
isYieldSupplyFeatureEnabled = yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled,
)
}

View file

@ -4,7 +4,6 @@ import arrow.core.Either
import com.tangem.common.ui.bottomsheet.chooseaddress.ChooseAddressBottomSheetConfig
import com.tangem.common.ui.tokendetails.TokenDetailsDialogConfig
import com.tangem.common.ui.tokens.getUnavailabilityReasonText
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.clore.CloreMigrationBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.dropdownmenu.TangemDropdownMenuItem
import com.tangem.core.ui.extensions.TextReference
@ -33,8 +32,8 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenBala
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsAppBarMenuConfig
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsBalanceBlockState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.clore.CloreMigrationBottomSheetConfig
import com.tangem.features.tokendetails.impl.R
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import com.tangem.utils.Provider
import kotlinx.collections.immutable.toImmutableList
@ -48,7 +47,6 @@ internal class TokenDetailsStateFactory(
private val networkHasDerivationUseCase: NetworkHasDerivationUseCase,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val userWalletId: UserWalletId,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
) {
private val skeletonStateConverter by lazy {
@ -57,7 +55,6 @@ internal class TokenDetailsStateFactory(
networkHasDerivationUseCase = networkHasDerivationUseCase,
getUserWalletUseCase = getUserWalletUseCase,
userWalletId = userWalletId,
yieldSupplyFeatureToggles = yieldSupplyFeatureToggles,
)
}
@ -74,7 +71,6 @@ internal class TokenDetailsStateFactory(
currentStateProvider = currentStateProvider,
appCurrencyProvider = appCurrencyProvider,
clickIntents = tokenDetailsClickIntents,
yieldSupplyFeatureToggles = yieldSupplyFeatureToggles,
)
}

View file

@ -148,10 +148,8 @@ internal fun TokenDetailsScreen(
)
}
if (state.isYieldSupplyFeatureEnabled) {
item {
yieldSupplyComponent.Content(modifier = itemModifier)
}
item {
yieldSupplyComponent.Content(modifier = itemModifier)
}
expressTransactionsItems(