Updated on 2026-08-14

This commit is contained in:
Tangem 2025-05-23 11:16:28 +03:00
commit ca49abf2b1
892 changed files with 17979 additions and 6555 deletions

View file

@ -4,11 +4,11 @@ import com.tangem.common.ui.bottomsheet.permission.state.ApproveType
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.staking.analytics.StakeScreenSource
import com.tangem.domain.staking.analytics.StakingAnalyticsEvent
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.features.staking.impl.presentation.state.*

View file

@ -4,7 +4,7 @@ import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
import javax.inject.Inject

View file

@ -1,6 +1,6 @@
package com.tangem.features.staking.impl.navigation
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
internal interface InnerStakingRouter {

View file

@ -3,8 +3,8 @@ package com.tangem.features.staking.impl.presentation.model
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
import com.tangem.common.ui.bottomsheet.permission.state.ApproveType
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.features.staking.impl.presentation.state.BalanceState
import com.tangem.features.staking.impl.presentation.state.bottomsheet.InfoType
import java.math.BigDecimal

View file

@ -28,6 +28,7 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.feedback.models.BlockchainErrorInfo
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.staking.*
import com.tangem.domain.staking.analytics.StakeScreenSource
import com.tangem.domain.staking.analytics.StakingAnalyticsEvent
@ -38,7 +39,6 @@ import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.domain.staking.model.stakekit.transaction.StakingTransaction
import com.tangem.domain.staking.utils.getValidatorsCount
import com.tangem.domain.tokens.*
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.transaction.error.GetFeeError
import com.tangem.domain.transaction.usecase.CreateApprovalTransactionUseCase
@ -93,7 +93,7 @@ internal class StakingModel @Inject constructor(
private val stateController: StakingStateController,
override val dispatchers: CoroutineDispatcherProvider,
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase,
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
private val getMinimumTransactionAmountSyncUseCase: GetMinimumTransactionAmountSyncUseCase,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
@ -549,7 +549,7 @@ internal class StakingModel @Inject constructor(
}
override fun onActiveStake(activeStake: BalanceState) {
val networkId = cryptoCurrencyStatus.currency.network.id.value
val networkId = cryptoCurrencyStatus.currency.network.rawId
if (isSingleAction(networkId, activeStake)) {
prepareForConfirmation(
balanceType = activeStake.type,
@ -854,7 +854,7 @@ internal class StakingModel @Inject constructor(
saveBlockchainErrorUseCase(
error = BlockchainErrorInfo(
errorMessage = errorMessage,
blockchainId = network.id.value,
blockchainId = network.rawId,
derivationPath = network.derivationPath.value,
destinationAddress = validator?.address.orEmpty(),
tokenSymbol = (cryptoCurrencyStatus.currency as? CryptoCurrency.Token)?.symbol,
@ -920,7 +920,7 @@ internal class StakingModel @Inject constructor(
)
},
)
getCurrencyStatusUpdatesUseCase(
getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
userWalletId = userWalletId,
currencyId = cryptoCurrencyId,
isSingleWalletWithTokens = false,

View file

@ -73,7 +73,7 @@ internal class BalanceItemConverter(
private fun BalanceItem.getBalanceValue(): BigDecimal {
val isIncludeStakingTotalBalance = BlockchainUtils.isIncludeStakingTotalBalance(
blockchainId = cryptoCurrencyStatus.currency.network.id.value,
blockchainId = cryptoCurrencyStatus.currency.network.rawId,
)
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data
return if (isIncludeStakingTotalBalance) {

View file

@ -77,7 +77,7 @@ internal class YieldBalancesConverter(
.toPersistentList()
private fun getRewardBlockType(): RewardBlockType {
val blockchainId = cryptoCurrencyStatus.currency.network.id.value
val blockchainId = cryptoCurrencyStatus.currency.network.rawId
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data
val rewards = yieldBalance?.balance?.items
?.filter { it.type == BalanceType.REWARDS && !it.amount.isZero() }

View file

@ -5,7 +5,7 @@ import com.tangem.common.ui.alerts.models.AlertUM
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.features.staking.impl.R
@Immutable

View file

@ -42,7 +42,7 @@ internal class StakingBalanceUpdater @AssistedInject constructor(
async {
fetchPendingTransactionsUseCase(
userWalletId = userWallet.walletId,
networks = setOf(cryptoCurrencyStatus.currency.network),
network = cryptoCurrencyStatus.currency.network,
)
},
// we should update tx history and network for new balances
@ -83,7 +83,6 @@ internal class StakingBalanceUpdater @AssistedInject constructor(
userWalletId = userWallet.walletId,
network = cryptoCurrencyStatus.currency.network,
delayMillis = delay,
refresh = true,
)
}

View file

@ -7,6 +7,7 @@ import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.common.extensions.isZero
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.staking.EstimateGasUseCase
import com.tangem.domain.staking.model.stakekit.PendingAction
import com.tangem.domain.staking.model.stakekit.StakingError
@ -14,7 +15,6 @@ import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.domain.staking.model.stakekit.transaction.ActionParams
import com.tangem.domain.staking.model.stakekit.transaction.StakingGasEstimate
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.staking.getCurrentToken
import com.tangem.domain.transaction.error.GetFeeError
@ -102,7 +102,7 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor(
?: error("No available address")
val gasEstimate = if (isCompositePendingActions(
networkId = cryptoCurrencyStatus.currency.network.id.value,
networkId = cryptoCurrencyStatus.currency.network.rawId,
pendingActions = pendingActions,
)
) {

View file

@ -120,8 +120,8 @@ internal class StakingTransactionSender @AssistedInject constructor(
onConstructError: (StakingError) -> Unit,
) = coroutineScope {
val isComposePendingActions = isCompositePendingActions(
cryptoCurrencyStatus.currency.network.id.value,
confirmationState.pendingActions,
networkId = cryptoCurrencyStatus.currency.network.rawId,
pendingActions = confirmationState.pendingActions,
)
if (isComposePendingActions) {
confirmationState.pendingActions?.map { action ->
@ -156,7 +156,7 @@ internal class StakingTransactionSender @AssistedInject constructor(
?.map { transaction ->
async {
getConstructedStakingTransactionUseCase(
networkId = cryptoCurrencyStatus.currency.network.id.value,
networkId = cryptoCurrencyStatus.currency.network.rawId,
fee = fee,
amount = amount.convertToSdkAmount(cryptoCurrencyStatus.currency),
transactionId = transaction.id,

View file

@ -2,11 +2,11 @@ package com.tangem.features.staking.impl.presentation.state.stub
import com.tangem.common.ui.bottomsheet.permission.state.ApproveType
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.features.staking.impl.presentation.model.StakingClickIntents
import com.tangem.features.staking.impl.presentation.state.BalanceState
import com.tangem.features.staking.impl.presentation.state.bottomsheet.InfoType
import com.tangem.features.staking.impl.presentation.model.StakingClickIntents
import java.math.BigDecimal
@Suppress("TooManyFunctions")

View file

@ -30,7 +30,7 @@ internal class SetConfirmationStateInitTransformer(
) : Transformer<StakingUiState> {
private val networkId
get() = cryptoCurrencyStatus.currency.network.id.value
get() = cryptoCurrencyStatus.currency.network.rawId
private val isComposePendingActions
get() = isCompositePendingActions(networkId, pendingActions)

View file

@ -7,11 +7,13 @@ import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.features.staking.impl.R
import com.tangem.features.staking.impl.presentation.state.*
import com.tangem.features.staking.impl.presentation.state.FeeState
import com.tangem.features.staking.impl.presentation.state.StakingStates
import com.tangem.features.staking.impl.presentation.state.StakingUiState
import com.tangem.features.staking.impl.presentation.state.utils.getRewardScheduleText
import com.tangem.utils.transformer.Transformer
@ -47,7 +49,7 @@ internal class SetConfirmationStateLoadingTransformer(
}
val rewardSchedule = getRewardScheduleText(
rewardSchedule = yield.metadata.rewardSchedule,
networkId = cryptoCurrency.network.id.value,
networkId = cryptoCurrency.network.rawId,
decapitalize = true,
)
return if (isEnterAction && amountDecimal != null && rewardSchedule != null) {

View file

@ -67,7 +67,7 @@ internal class SetInitialDataStateTransformer(
title = TextReference.EMPTY,
cryptoCurrencyName = cryptoCurrency.name,
cryptoCurrencySymbol = cryptoCurrency.symbol,
cryptoCurrencyBlockchainId = cryptoCurrency.network.id.value,
cryptoCurrencyBlockchainId = cryptoCurrency.network.rawId,
clickIntents = clickIntents,
currentStep = StakingStep.InitialInfo,
initialInfoState = createInitialInfoState(),
@ -150,7 +150,7 @@ internal class SetInitialDataStateTransformer(
cryptoCurrencyStatus: CryptoCurrencyStatus,
): RoundedListWithDividersItemData? {
val minimumCryptoAmount = yield.args.enter.args[Yield.Args.ArgType.AMOUNT]?.minimum ?: return null
val blockchainId = cryptoCurrencyStatus.currency.network.id.value
val blockchainId = cryptoCurrencyStatus.currency.network.rawId
if (!showMinimumRequirementInfo(blockchainId)) return null
val formattedAmount = minimumCryptoAmount.format { crypto(cryptoCurrencyStatus.currency) }
@ -193,7 +193,7 @@ internal class SetInitialDataStateTransformer(
private fun createRewardScheduleItem(): RoundedListWithDividersItemData? {
val endTextReference = getRewardScheduleText(
rewardSchedule = yield.metadata.rewardSchedule,
networkId = cryptoCurrencyStatus.currency.network.id.value,
networkId = cryptoCurrencyStatus.currency.network.rawId,
decapitalize = false,
) ?: return null

View file

@ -111,7 +111,7 @@ internal class AmountRequirementStateTransformer(
val cryptoAmountValue = amountState.amountTextField.cryptoAmount.value ?: return false
val isEnterOrExit = actionType is StakingActionCommonType.Enter || actionType is StakingActionCommonType.Exit
val isTron = isTron(cryptoCurrencyStatus.currency.network.id.value)
val isTron = isTron(cryptoCurrencyStatus.currency.network.rawId)
val isIntegerOnly = cryptoAmountValue.isZero() || cryptoAmountValue.remainder(BigDecimal.ONE).isZero()

View file

@ -13,11 +13,11 @@ import com.tangem.common.ui.notifications.NotificationsFactory.addTransactionLim
import com.tangem.core.ui.extensions.networkIconResId
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.model.stakekit.StakingErrors
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyCheck
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
@ -185,7 +185,7 @@ internal class AddStakingNotificationsTransformer(
onClick = prevState.clickIntents::openTokenDetails,
onAnalyticsEvent = { /* no-op */ },
)
if (!BlockchainUtils.isCardano(network.id.value)) {
if (!BlockchainUtils.isCardano(network.rawId)) {
addDustWarningNotification(
dustValue = currencyCheck.dustValue,
feeValue = feeValue,
@ -275,7 +275,7 @@ internal class AddStakingNotificationsTransformer(
private fun MutableList<NotificationUM>.addTonExtraFeeErrorNotification() {
val amount = cryptoCurrencyStatusProvider().value.amount.orZero()
val cryptoCurrencyNetworkIdValue = cryptoCurrencyStatusProvider().currency.network.id.value
val cryptoCurrencyNetworkIdValue = cryptoCurrencyStatusProvider().currency.network.rawId
if (isTon(cryptoCurrencyNetworkIdValue) && amount < TON_BALANCE_EXTRA_FEE_THRESHOLD) {
add(NotificationUM.Error.TonStakingExtraFeeError)

View file

@ -133,7 +133,7 @@ internal class StakingInfoNotificationsFactory(
private fun MutableList<NotificationUM>.addTronRevoteNotification() {
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val isTron = isTron(cryptoCurrencyStatus.currency.network.id.value)
val isTron = isTron(cryptoCurrencyStatus.currency.network.rawId)
val hasStakedBalance = (cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data)?.balance
?.items?.any {
it.type == BalanceType.PREPARING ||
@ -152,7 +152,7 @@ internal class StakingInfoNotificationsFactory(
private fun MutableList<NotificationUM>.addCardanoStakeNotification() {
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val isCardano = isCardano(cryptoCurrencyStatus.currency.network.id.value)
val isCardano = isCardano(cryptoCurrencyStatus.currency.network.rawId)
if (isCardano) {
add(
@ -166,7 +166,7 @@ internal class StakingInfoNotificationsFactory(
private fun MutableList<NotificationUM>.addCardanoStakeMinimumAmountNotification(feeValue: BigDecimal) {
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val isCardano = isCardano(cryptoCurrencyStatus.currency.network.id.value)
val isCardano = isCardano(cryptoCurrencyStatus.currency.network.rawId)
val balance = cryptoCurrencyStatus.value.amount.orZero()
if (isCardano && balance - feeValue < MINIMUM_STAKE_BALANCE) {
add(
@ -180,7 +180,7 @@ internal class StakingInfoNotificationsFactory(
private fun MutableList<NotificationUM>.addCardanoRestakeMinimumAmountNotification(feeValue: BigDecimal) {
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val isCardano = isCardano(cryptoCurrencyStatus.currency.network.id.value)
val isCardano = isCardano(cryptoCurrencyStatus.currency.network.rawId)
val balance = cryptoCurrencyStatus.value.amount.orZero()
if (isCardano && balance - feeValue < MINIMUM_RESTAKE_BALANCE) {
add(
@ -201,7 +201,7 @@ internal class StakingInfoNotificationsFactory(
val isEntireBalance = sendingAmount.plus(feeValue) == balance
if (isEntireBalance && isSubtractAvailable && !isCardano(cryptoCurrencyStatus.currency.network.id.value)) {
if (isEntireBalance && isSubtractAvailable && !isCardano(cryptoCurrencyStatus.currency.network.rawId)) {
add(StakingNotification.Info.StakeEntireBalance)
}
}
@ -226,7 +226,7 @@ internal class StakingInfoNotificationsFactory(
private fun MutableList<NotificationUM>.addUnstakeInfoNotification() {
val cooldownPeriodDays = yield.metadata.cooldownPeriod?.days
val cryptoCurrencyNetworkIdValue = cryptoCurrencyStatusProvider().currency.network.id.value
val cryptoCurrencyNetworkIdValue = cryptoCurrencyStatusProvider().currency.network.rawId
if (cooldownPeriodDays != null) {
add(
StakingNotification.Info.Unstake(
@ -242,7 +242,7 @@ internal class StakingInfoNotificationsFactory(
}
private fun MutableList<NotificationUM>.addTonHaveToUnstakeAllNotification(prevState: StakingUiState) {
val cryptoCurrencyNetworkIdValue = cryptoCurrencyStatusProvider().currency.network.id.value
val cryptoCurrencyNetworkIdValue = cryptoCurrencyStatusProvider().currency.network.rawId
if (isTon(cryptoCurrencyNetworkIdValue)) {
val initialInfoState = prevState.initialInfoState as? StakingStates.InitialInfoState.Data
@ -272,7 +272,7 @@ internal class StakingInfoNotificationsFactory(
private fun MutableList<NotificationUM>.addTonExtraFeeInfoNotification(tonBalanceExtraFeeThreshold: BigDecimal) {
val amount = cryptoCurrencyStatusProvider().value.amount.orZero()
val cryptoCurrencyNetworkIdValue = cryptoCurrencyStatusProvider().currency.network.id.value
val cryptoCurrencyNetworkIdValue = cryptoCurrencyStatusProvider().currency.network.rawId
if (isTon(cryptoCurrencyNetworkIdValue) && amount >= tonBalanceExtraFeeThreshold) {
add(

View file

@ -17,7 +17,7 @@ internal fun checkAndCalculateSubtractedAmount(
reduceAmountBy: BigDecimal,
): BigDecimal {
val balance = cryptoCurrencyStatus.value.amount ?: return amountValue
val isTron = isTron(cryptoCurrencyStatus.currency.network.id.value)
val isTron = isTron(cryptoCurrencyStatus.currency.network.rawId)
val feeValueRounded = if (isTron) {
feeValue.round(MathContext(0, RoundingMode.UP))
} else {
@ -32,7 +32,7 @@ internal fun checkAndCalculateSubtractedAmount(
)
return if (isFeeCoverage) {
val reducedAmount = balance.minus(reduceAmountBy).minus(feeValueRounded)
if (isTron(cryptoCurrencyStatus.currency.network.id.value)) {
if (isTron(cryptoCurrencyStatus.currency.network.rawId)) {
reducedAmount.setScale(0, RoundingMode.DOWN)
} else {
reducedAmount