diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 99a8ff0869..884e4e6cc6 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -566,6 +566,8 @@ Восстановление кода доступа Идентичные карты Код доступа + Оплата с + Через Группы По балансу Упорядочить токены @@ -758,6 +760,7 @@ Стейкинг в сети %1$s с новым валидатором автоматически переведет ваши текущие застейканные средства на него. Реинвестируйте свои заработанные награды в вашу застейканную сумму, увеличивая потенциальный доход Рестейк позволяет вам переместить средства из одного валидатора в другого без необходимости выхода из стейкинга. + Вы собираетесь застейкать весь баланс, рекомендуем оставить небольшую сумму для оплаты комиссии сети при выходе из стейкинга или получении награды. Разблокируйте свои средства, чтобы вывести их из стейкинга. Разблокировка займёт %s. Ваши средства будут доступны для использования после 21-дневного периода отзыва. Награда будет выведена вместе с вашими выводими средствами. Ваши средства будут доступны после %s периода отзыва. diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 9b1c743f98..486f321553 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -551,9 +551,11 @@ Access code restore Identical cards Access code + Pay with Our services are not available in this country Change or confirm it Your residence has been identified as + Via Group By balance Organize tokens @@ -742,6 +744,7 @@ Staking in the %1$s network with a new validator will automatically transfer all previously staked funds to this validator Reinvests your earned rewards in your staked amount, increasing potential earnings. Restake lets you move your funds from one validator to another without the need to unstake + You’re about to stake your entire balance. We recommend leaving a small amount to cover network fees for unstaking or claiming rewards. Unlock your money to withdraw it from staking process. Unlocking takes %s. Your funds will be available for use after the 21-day unbonding period. Reward will be withdrawn along with your unstaking funds. Your funds will be available for use after the %s unbonding period. diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingNotification.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingNotification.kt index 99a2445b74..398b15cc88 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingNotification.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingNotification.kt @@ -59,7 +59,6 @@ internal object StakingNotification { subtitle = subtitle, buttonsState = buttonsState, onCloseClick = onCloseClick, - ) { data class EarnRewards( val subtitleText: TextReference, @@ -68,6 +67,11 @@ internal object StakingNotification { subtitle = subtitleText, ) + data object StakeEntireBalance : StakingNotification.Info( + title = resourceReference(R.string.common_network_fee_title), + subtitle = resourceReference(R.string.staking_notification_stake_entire_balance_text), + ) + data class Unstake( val cooldownPeriodDays: Int, @StringRes val subtitleRes: Int, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt similarity index 67% rename from features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt rename to features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt index 0a86be295b..e933910095 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt @@ -1,4 +1,4 @@ -package com.tangem.features.staking.impl.presentation.state.transformers +package com.tangem.features.staking.impl.presentation.state.transformers.notifications import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.common.ui.notifications.NotificationUM @@ -11,21 +11,14 @@ import com.tangem.common.ui.notifications.NotificationsFactory.addReserveAmountE import com.tangem.common.ui.notifications.NotificationsFactory.addTransactionLimitErrorNotification import com.tangem.common.ui.notifications.NotificationsFactory.addValidateTransactionNotifications import com.tangem.core.ui.extensions.networkIconResId -import com.tangem.core.ui.extensions.pluralReference -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.appcurrency.model.AppCurrency -import com.tangem.domain.staking.model.stakekit.BalanceType import com.tangem.domain.staking.model.stakekit.Yield -import com.tangem.domain.staking.model.stakekit.YieldBalance 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.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.warnings.CryptoCurrencyCheck import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning import com.tangem.domain.transaction.error.GetFeeError -import com.tangem.features.staking.impl.R import com.tangem.features.staking.impl.presentation.state.FeeState import com.tangem.features.staking.impl.presentation.state.StakingNotification import com.tangem.features.staking.impl.presentation.state.StakingStates @@ -33,8 +26,6 @@ import com.tangem.features.staking.impl.presentation.state.StakingUiState import com.tangem.features.staking.impl.presentation.state.utils.checkAndCalculateSubtractedAmount import com.tangem.features.staking.impl.presentation.state.utils.checkFeeCoverage import com.tangem.lib.crypto.BlockchainUtils -import com.tangem.lib.crypto.BlockchainUtils.isCosmos -import com.tangem.lib.crypto.BlockchainUtils.isTron import com.tangem.utils.Provider import com.tangem.utils.extensions.orZero import com.tangem.utils.transformer.Transformer @@ -53,6 +44,13 @@ internal class AddStakingNotificationsTransformer( private val isSubtractAvailable: Boolean, private val yield: Yield, ) : Transformer { + + private val stakingInfoNotificationsFactory = StakingInfoNotificationsFactory( + cryptoCurrencyStatusProvider = cryptoCurrencyStatusProvider, + yield = yield, + isSubtractAvailable = isSubtractAvailable, + ) + override fun transform(prevState: StakingUiState): StakingUiState { val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() val balance = cryptoCurrencyStatus.value.amount.orZero() @@ -105,7 +103,12 @@ internal class AddStakingNotificationsTransformer( isFeeCoverage = isFeeCoverage && isEnterAction && !sendingAmount.equals(minimumRequirement), ) - addInfoNotifications(prevState) + stakingInfoNotificationsFactory.addInfoNotifications( + notifications = this, + prevState = prevState, + sendingAmount = sendingAmount, + feeValue = feeValue, + ) }.toImmutableList() return prevState.copy( @@ -241,105 +244,4 @@ internal class AddStakingNotificationsTransformer( add(notification) } } - - private fun MutableList.addInfoNotifications(prevState: StakingUiState) { - when (prevState.actionType) { - StakingActionCommonType.Enter -> addEnterInfoNotifications() - StakingActionCommonType.Exit -> addExitInfoNotifications() - is StakingActionCommonType.Pending -> addPendingInfoNotifications(prevState) - } - } - - private fun MutableList.addExitInfoNotifications() { - val cooldownPeriodDays = yield.metadata.cooldownPeriod?.days - if (cooldownPeriodDays != null) { - add( - StakingNotification.Info.Unstake( - cooldownPeriodDays = cooldownPeriodDays, - subtitleRes = if (isCosmos(cryptoCurrencyStatusProvider().currency.network.id.value)) { - R.string.staking_notification_unstake_cosmos_text - } else { - R.string.staking_notification_unstake_text - }, - ), - ) - } - } - - private fun MutableList.addEnterInfoNotifications() { - addTronRevoteNotification() - } - - private fun MutableList.addPendingInfoNotifications(prevState: StakingUiState) { - val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data - val pendingActionType = confirmationState?.pendingAction?.type - val (titleReference, textReference) = when (pendingActionType) { - StakingActionType.CLAIM_REWARDS -> { - resourceReference(R.string.common_claim) to - resourceReference(R.string.staking_notification_claim_rewards_text) - } - StakingActionType.RESTAKE_REWARDS -> { - resourceReference(R.string.staking_restake) to - resourceReference(R.string.staking_notification_restake_rewards_text) - } - StakingActionType.WITHDRAW -> { - resourceReference(R.string.staking_withdraw) to - resourceReference(R.string.staking_notification_withdraw_text) - } - StakingActionType.UNLOCK_LOCKED -> { - val cooldownPeriodDays = yield.metadata.cooldownPeriod?.days - if (cooldownPeriodDays != null) { - resourceReference(R.string.staking_unlocked_locked) to resourceReference( - R.string.staking_notification_unlock_text, - wrappedList( - pluralReference( - id = R.plurals.common_days, - count = cooldownPeriodDays, - formatArgs = wrappedList(cooldownPeriodDays), - ), - ), - ) - } else { - null to null - } - } - StakingActionType.VOTE_LOCKED -> { - resourceReference(R.string.staking_revote) to - resourceReference(R.string.staking_notifications_revote_tron_text) - } - StakingActionType.RESTAKE -> { - resourceReference(R.string.staking_restake) to - resourceReference(R.string.staking_notification_restake_text) - } - else -> null to null - } - - if (titleReference != null && textReference != null) { - add( - StakingNotification.Info.Ordinary( - title = titleReference, - text = textReference, - ), - ) - } - } - - private fun MutableList.addTronRevoteNotification() { - val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() - val isTron = isTron(cryptoCurrencyStatus.currency.network.id.value) - val hasStakedBalance = (cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data)?.balance - ?.items?.any { - it.type == BalanceType.PREPARING || - it.type == BalanceType.STAKED || - it.type == BalanceType.LOCKED - } == true - if (isTron && hasStakedBalance) { - add( - StakingNotification.Info.Ordinary( - title = resourceReference(R.string.staking_revote), - text = resourceReference(R.string.staking_notifications_revote_tron_text), - ), - ) - } - } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/DismissStakingNotificationsStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/DismissStakingNotificationsStateTransformer.kt similarity index 98% rename from features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/DismissStakingNotificationsStateTransformer.kt rename to features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/DismissStakingNotificationsStateTransformer.kt index cd7e6d8843..449cfcbe48 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/DismissStakingNotificationsStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/DismissStakingNotificationsStateTransformer.kt @@ -1,4 +1,4 @@ -package com.tangem.features.staking.impl.presentation.state.transformers +package com.tangem.features.staking.impl.presentation.state.transformers.notifications import com.tangem.common.ui.notifications.NotificationUM import com.tangem.features.staking.impl.presentation.state.StakingStates diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt new file mode 100644 index 0000000000..16526c9e0b --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt @@ -0,0 +1,152 @@ +package com.tangem.features.staking.impl.presentation.state.transformers.notifications + +import com.tangem.common.ui.notifications.NotificationUM +import com.tangem.core.ui.extensions.pluralReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.domain.staking.model.stakekit.BalanceType +import com.tangem.domain.staking.model.stakekit.Yield +import com.tangem.domain.staking.model.stakekit.YieldBalance +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.R +import com.tangem.features.staking.impl.presentation.state.StakingNotification +import com.tangem.features.staking.impl.presentation.state.StakingStates +import com.tangem.features.staking.impl.presentation.state.StakingUiState +import com.tangem.lib.crypto.BlockchainUtils.isCosmos +import com.tangem.lib.crypto.BlockchainUtils.isTron +import com.tangem.utils.Provider +import com.tangem.utils.extensions.orZero +import java.math.BigDecimal + +internal class StakingInfoNotificationsFactory( + private val cryptoCurrencyStatusProvider: Provider, + private val yield: Yield, + private val isSubtractAvailable: Boolean, +) { + + fun addInfoNotifications( + notifications: MutableList, + prevState: StakingUiState, + sendingAmount: BigDecimal, + feeValue: BigDecimal, + ) = with(notifications) { + when (prevState.actionType) { + StakingActionCommonType.Enter -> addEnterInfoNotifications(sendingAmount, feeValue) + StakingActionCommonType.Exit -> addExitInfoNotifications() + is StakingActionCommonType.Pending -> addPendingInfoNotifications(prevState) + } + } + + private fun MutableList.addExitInfoNotifications() { + val cooldownPeriodDays = yield.metadata.cooldownPeriod?.days + if (cooldownPeriodDays != null) { + add( + StakingNotification.Info.Unstake( + cooldownPeriodDays = cooldownPeriodDays, + subtitleRes = if (isCosmos(cryptoCurrencyStatusProvider().currency.network.id.value)) { + R.string.staking_notification_unstake_cosmos_text + } else { + R.string.staking_notification_unstake_text + }, + ), + ) + } + } + + private fun MutableList.addEnterInfoNotifications( + sendingAmount: BigDecimal, + feeValue: BigDecimal, + ) { + addTronRevoteNotification() + addStakingEntireBalanceNotification(sendingAmount, feeValue) + } + + private fun MutableList.addPendingInfoNotifications(prevState: StakingUiState) { + val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data + val pendingActionType = confirmationState?.pendingAction?.type + val (titleReference, textReference) = when (pendingActionType) { + StakingActionType.CLAIM_REWARDS -> { + resourceReference(R.string.common_claim) to + resourceReference(R.string.staking_notification_claim_rewards_text) + } + StakingActionType.RESTAKE_REWARDS -> { + resourceReference(R.string.staking_restake) to + resourceReference(R.string.staking_notification_restake_rewards_text) + } + StakingActionType.WITHDRAW -> { + resourceReference(R.string.staking_withdraw) to + resourceReference(R.string.staking_notification_withdraw_text) + } + StakingActionType.UNLOCK_LOCKED -> { + val cooldownPeriodDays = yield.metadata.cooldownPeriod?.days + if (cooldownPeriodDays != null) { + resourceReference(R.string.staking_unlocked_locked) to resourceReference( + R.string.staking_notification_unlock_text, + wrappedList( + pluralReference( + id = R.plurals.common_days, + count = cooldownPeriodDays, + formatArgs = wrappedList(cooldownPeriodDays), + ), + ), + ) + } else { + null to null + } + } + StakingActionType.VOTE_LOCKED -> { + resourceReference(R.string.staking_revote) to + resourceReference(R.string.staking_notifications_revote_tron_text) + } + StakingActionType.RESTAKE -> { + resourceReference(R.string.staking_restake) to + resourceReference(R.string.staking_notification_restake_text) + } + else -> null to null + } + + if (titleReference != null && textReference != null) { + add( + StakingNotification.Info.Ordinary( + title = titleReference, + text = textReference, + ), + ) + } + } + + private fun MutableList.addTronRevoteNotification() { + val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() + val isTron = isTron(cryptoCurrencyStatus.currency.network.id.value) + val hasStakedBalance = (cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data)?.balance + ?.items?.any { + it.type == BalanceType.PREPARING || + it.type == BalanceType.STAKED || + it.type == BalanceType.LOCKED + } == true + if (isTron && hasStakedBalance) { + add( + StakingNotification.Info.Ordinary( + title = resourceReference(R.string.staking_revote), + text = resourceReference(R.string.staking_notifications_revote_tron_text), + ), + ) + } + } + + private fun MutableList.addStakingEntireBalanceNotification( + sendingAmount: BigDecimal, + feeValue: BigDecimal, + ) { + val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() + val balance = cryptoCurrencyStatus.value.amount.orZero() + + val isEntireBalance = sendingAmount.plus(feeValue) == balance + + if (isEntireBalance && isSubtractAvailable) { + add(StakingNotification.Info.StakeEntireBalance) + } + } +} diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt index 7719fa6867..103058a46e 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt @@ -61,6 +61,8 @@ import com.tangem.features.staking.impl.presentation.state.helpers.StakingTransa import com.tangem.features.staking.impl.presentation.state.transformers.* import com.tangem.features.staking.impl.presentation.state.transformers.amount.* import com.tangem.features.staking.impl.presentation.state.transformers.approval.* +import com.tangem.features.staking.impl.presentation.state.transformers.notifications.AddStakingNotificationsTransformer +import com.tangem.features.staking.impl.presentation.state.transformers.notifications.DismissStakingNotificationsStateTransformer import com.tangem.features.staking.impl.presentation.state.transformers.validator.ValidatorSelectChangeTransformer import com.tangem.features.staking.impl.presentation.state.utils.isSingleAction import com.tangem.features.staking.impl.presentation.state.utils.withStubUnstakeAction