diff --git a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt
index 20dad94e6b..79c6c304fb 100644
--- a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt
+++ b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationUM.kt
@@ -183,6 +183,22 @@ sealed class NotificationUM(val config: NotificationConfig) {
)
}
+ open class Info(
+ title: TextReference,
+ subtitle: TextReference,
+ iconResId: Int = R.drawable.ic_alert_circle_24,
+ buttonsState: NotificationConfig.ButtonsState? = null,
+ onCloseClick: (() -> Unit)? = null,
+ ) : NotificationUM(
+ config = NotificationConfig(
+ title = title,
+ subtitle = subtitle,
+ iconResId = iconResId,
+ buttonsState = buttonsState,
+ onCloseClick = onCloseClick,
+ ),
+ )
+
sealed interface Cardano {
data class MinAdaValueCharged(val tokenName: String, val minAdaValue: String) : Warning(
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 566ba9fae5..66d4cf1e8c 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -84,6 +84,7 @@
You have not given access to your camera, please adjust your privacy settings
Cancel
Choose action
+ Claim
Claim rewards
Close
Continue
@@ -666,11 +667,13 @@
Locked
Migrate
Native staking
+ Earned rewards are sent directly to your address. Once claimed, the funds are available for use.
Staking allows you to earn %1$s. Your staking rewards arrive every day.
Staking allows you to earn %1$s. Your staking rewards arrive every hour.
Staking allows you to earn %1$s. Your staking rewards arrive every month.
Staking allows you to earn %1$s. Your staking rewards arrive every week.
Earn staking rewards
+ Reinvests your earned rewards in your staked amount, increasing potential earnings.
Rewards stop accruing immediately after you start unstaking. The unstaking process takes %s.
Your funds have been unstaked. You can now withdraw them along with your earned rewards.
Preparing
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 682b777b25..3f8be15c42 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
@@ -29,6 +29,7 @@ internal object StakingNotification {
subtitle = subtitle,
)
}
+
sealed class Warning(
title: TextReference,
subtitle: TextReference,
@@ -40,17 +41,35 @@ internal object StakingNotification {
iconResId = R.drawable.ic_alert_circle_24,
buttonsState = buttonsState,
onCloseClick = onCloseClick,
+ ) {
+ data class TransactionInProgress(
+ val title: TextReference,
+ val description: TextReference,
+ ) : StakingNotification.Warning(title = title, subtitle = description)
+ }
+
+ sealed class Info(
+ title: TextReference,
+ subtitle: TextReference,
+ buttonsState: NotificationConfig.ButtonsState? = null,
+ onCloseClick: (() -> Unit)? = null,
+ ) : NotificationUM.Info(
+ title = title,
+ subtitle = subtitle,
+ buttonsState = buttonsState,
+ onCloseClick = onCloseClick,
+
) {
data class EarnRewards(
val subtitleText: TextReference,
- ) : StakingNotification.Warning(
+ ) : StakingNotification.Info(
title = resourceReference(R.string.staking_notification_earn_rewards_title),
subtitle = subtitleText,
)
data class Unstake(
val cooldownPeriodDays: Int,
- ) : StakingNotification.Warning(
+ ) : StakingNotification.Info(
title = resourceReference(R.string.common_unstake),
subtitle = resourceReference(
R.string.staking_notification_unstake_text,
@@ -64,9 +83,12 @@ internal object StakingNotification {
),
)
- data class TransactionInProgress(
+ data class PendingAction(
val title: TextReference,
- val description: TextReference,
- ) : StakingNotification.Warning(title = title, subtitle = description)
+ val text: TextReference,
+ ) : StakingNotification.Info(
+ title = title,
+ subtitle = text,
+ )
}
}
\ No newline at end of file
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/RewardsValidatorStateConverter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/RewardsValidatorStateConverter.kt
index 673e81499b..987866f39b 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/RewardsValidatorStateConverter.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/RewardsValidatorStateConverter.kt
@@ -1,6 +1,5 @@
package com.tangem.features.staking.impl.presentation.state.converters
-import com.tangem.core.ui.extensions.combinedReference
import com.tangem.core.ui.extensions.pluralReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList
@@ -13,7 +12,6 @@ import com.tangem.features.staking.impl.R
import com.tangem.features.staking.impl.presentation.state.BalanceState
import com.tangem.features.staking.impl.presentation.state.StakingStates
import com.tangem.utils.Provider
-import com.tangem.utils.StringsSigns.PLUS
import com.tangem.utils.converter.Converter
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList
@@ -74,14 +72,11 @@ internal class RewardsValidatorStateConverter(
cryptoCurrency = cryptoCurrency,
),
)
- val fiatAmount = combinedReference(
- stringReference(PLUS),
- stringReference(
- BigDecimalFormatter.formatFiatAmount(
- fiatAmount = fiatValue,
- fiatCurrencyCode = appCurrency.code,
- fiatCurrencySymbol = appCurrency.symbol,
- ),
+ val fiatAmount = stringReference(
+ BigDecimalFormatter.formatFiatAmount(
+ fiatAmount = fiatValue,
+ fiatCurrencyCode = appCurrency.code,
+ fiatCurrencySymbol = appCurrency.symbol,
),
)
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmationStatePreviewData.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmationStatePreviewData.kt
index 25879ce343..443491c582 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmationStatePreviewData.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmationStatePreviewData.kt
@@ -79,7 +79,7 @@ internal object ConfirmationStatePreviewData {
),
footerText = "You stake \$715.11 and will be receiving ~\$35 monthly",
notifications = persistentListOf(
- StakingNotification.Warning.EarnRewards(
+ StakingNotification.Info.EarnRewards(
subtitleText = resourceReference(
id = R.string.staking_notification_earn_rewards_text_period_day,
formatArgs = wrappedList("Solana"),
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/AddStakingNotificationsTransformer.kt
index fd4fb47e43..f7738e94b5 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/AddStakingNotificationsTransformer.kt
@@ -11,12 +11,17 @@ import com.tangem.common.ui.notifications.NotificationsFactory.addFeeUnreachable
import com.tangem.common.ui.notifications.NotificationsFactory.addReserveAmountErrorNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addTransactionLimitErrorNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addValidateTransactionNotifications
+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.Yield
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.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
@@ -40,6 +45,7 @@ internal class AddStakingNotificationsTransformer(
private val feeError: GetFeeError?,
private val currencyCheck: CryptoCurrencyCheck,
private val isSubtractAvailable: Boolean,
+ private val yield: Yield,
) : Transformer {
override fun transform(prevState: StakingUiState): StakingUiState {
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
@@ -87,7 +93,7 @@ internal class AddStakingNotificationsTransformer(
isFeeCoverage = isFeeCoverage && isEnterAction,
)
- addAll(confirmationState.notifications)
+ addInfoNotifications(prevState)
}.toImmutableList()
return prevState.copy(
@@ -186,4 +192,70 @@ internal class AddStakingNotificationsTransformer(
onReduceClick = prevState.clickIntents::onAmountReduceToClick,
)
}
+
+ private fun MutableList.addInfoNotifications(prevState: StakingUiState) {
+ when (prevState.actionType) {
+ StakingActionCommonType.EXIT -> {
+ add(
+ StakingNotification.Info.Unstake(
+ cooldownPeriodDays = yield.metadata.cooldownPeriod.days,
+ ),
+ )
+ }
+ StakingActionCommonType.ENTER -> {
+ add(
+ StakingNotification.Info.EarnRewards(
+ subtitleText = resourceReference(
+ id = getEarnRewardsPeriod(yield.metadata.rewardSchedule),
+ formatArgs = wrappedList(yield.token.name),
+ ),
+ ),
+ )
+ }
+ else -> {
+ val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data
+ val pendingActionType = confirmationState?.pendingAction?.type
+ val (titleId, textId) = when (pendingActionType) {
+ StakingActionType.CLAIM_REWARDS -> {
+ R.string.common_claim to R.string.staking_notification_claim_rewards_text
+ }
+ StakingActionType.RESTAKE_REWARDS -> {
+ R.string.staking_restake to R.string.staking_notification_restake_rewards_text
+ }
+ else -> null to null
+ }
+
+ if (titleId != null && textId != null) {
+ add(
+ StakingNotification.Info.PendingAction(
+ title = resourceReference(titleId),
+ text = resourceReference(textId),
+ ),
+ )
+ }
+ }
+ }
+ }
+
+ private fun getEarnRewardsPeriod(rewardSchedule: Yield.Metadata.RewardSchedule): Int {
+ return when (rewardSchedule) {
+ Yield.Metadata.RewardSchedule.BLOCK,
+ Yield.Metadata.RewardSchedule.DAY,
+ Yield.Metadata.RewardSchedule.ERA,
+ Yield.Metadata.RewardSchedule.EPOCH,
+ -> R.string.staking_notification_earn_rewards_text_period_day
+
+ Yield.Metadata.RewardSchedule.HOUR,
+ -> R.string.staking_notification_earn_rewards_text_period_hour
+
+ Yield.Metadata.RewardSchedule.WEEK,
+ -> R.string.staking_notification_earn_rewards_text_period_week
+
+ Yield.Metadata.RewardSchedule.MONTH,
+ -> R.string.staking_notification_earn_rewards_text_period_month
+
+ else
+ -> R.string.staking_notification_earn_rewards_text_period_day
+ }
+ }
}
\ No newline at end of file
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt
index e158860e89..2e09f5d90f 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt
@@ -1,14 +1,8 @@
package com.tangem.features.staking.impl.presentation.state.transformers
-import com.tangem.common.ui.notifications.NotificationUM
-import com.tangem.core.ui.extensions.resourceReference
-import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.staking.model.stakekit.Yield
-import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
-import com.tangem.features.staking.impl.R
import com.tangem.features.staking.impl.presentation.state.*
import com.tangem.utils.transformer.Transformer
-import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
internal class SetConfirmationStateLoadingTransformer(
@@ -30,52 +24,13 @@ internal class SetConfirmationStateLoadingTransformer(
chosenValidator = chosenValidator,
availableValidators = yield.validators,
),
- notifications = getNotifications(prevState),
+ notifications = persistentListOf(),
footerText = "",
transactionDoneState = TransactionDoneState.Empty,
- pendingAction = null,
+ pendingAction = possibleConfirmationState?.pendingAction,
isApprovalNeeded = false,
reduceAmountBy = null,
),
)
}
-
- private fun getNotifications(prevState: StakingUiState): ImmutableList {
- return persistentListOf(
- if (prevState.actionType == StakingActionCommonType.EXIT) {
- StakingNotification.Warning.Unstake(
- cooldownPeriodDays = yield.metadata.cooldownPeriod.days,
- )
- } else {
- StakingNotification.Warning.EarnRewards(
- subtitleText = resourceReference(
- id = getEarnRewardsPeriod(yield.metadata.rewardSchedule),
- formatArgs = wrappedList(yield.token.name),
- ),
- )
- },
- )
- }
-
- private fun getEarnRewardsPeriod(rewardSchedule: Yield.Metadata.RewardSchedule): Int {
- return when (rewardSchedule) {
- Yield.Metadata.RewardSchedule.BLOCK,
- Yield.Metadata.RewardSchedule.DAY,
- Yield.Metadata.RewardSchedule.ERA,
- Yield.Metadata.RewardSchedule.EPOCH,
- -> R.string.staking_notification_earn_rewards_text_period_day
-
- Yield.Metadata.RewardSchedule.HOUR,
- -> R.string.staking_notification_earn_rewards_text_period_hour
-
- Yield.Metadata.RewardSchedule.WEEK,
- -> R.string.staking_notification_earn_rewards_text_period_week
-
- Yield.Metadata.RewardSchedule.MONTH,
- -> R.string.staking_notification_earn_rewards_text_period_month
-
- else
- -> R.string.staking_notification_earn_rewards_text_period_day
- }
- }
}
\ No newline at end of file
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt
index b164510f98..ec70635b66 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt
@@ -64,10 +64,7 @@ internal class SetInitialDataStateTransformer(
val cryptoCurrencyName = cryptoCurrencyStatusProvider().currency.name
return prevState.copy(
- title = TextReference.Res(
- R.string.staking_title_stake,
- wrappedList(cryptoCurrencyName),
- ),
+ title = TextReference.EMPTY,
walletName = userWalletProvider.invoke().name,
cryptoCurrencyName = cryptoCurrencyName,
clickIntents = clickIntents,
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetTitleTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetTitleTransformer.kt
index 7ad24a9041..d296d29596 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetTitleTransformer.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetTitleTransformer.kt
@@ -1,11 +1,15 @@
package com.tangem.features.staking.impl.presentation.state.transformers
+import com.tangem.core.ui.extensions.isNullOrEmpty
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.features.staking.impl.R
-import com.tangem.features.staking.impl.presentation.state.*
+import com.tangem.features.staking.impl.presentation.state.StakingStates
+import com.tangem.features.staking.impl.presentation.state.StakingStep
+import com.tangem.features.staking.impl.presentation.state.StakingUiState
+import com.tangem.features.staking.impl.presentation.state.utils.getPendingActionTitle
import com.tangem.utils.transformer.Transformer
internal object SetTitleTransformer : Transformer {
@@ -14,26 +18,36 @@ internal object SetTitleTransformer : Transformer {
val actionType = prevState.actionType
val currentStep = prevState.currentStep
- val title = when {
- currentStep == StakingStep.Amount -> {
- resourceReference(R.string.send_amount_label)
- }
+ val title = when (currentStep) {
+ StakingStep.Amount -> resourceReference(R.string.send_amount_label)
+ StakingStep.Validators -> resourceReference(R.string.staking_validators)
+ StakingStep.RewardsValidators -> resourceReference(R.string.common_claim_rewards)
+ StakingStep.InitialInfo -> resourceReference(
+ R.string.staking_title_stake,
+ wrappedList(prevState.cryptoCurrencyName),
+ )
- currentStep == StakingStep.Validators -> {
- resourceReference(R.string.staking_validators)
- }
+ StakingStep.Confirmation -> {
+ when (actionType) {
+ StakingActionCommonType.ENTER -> resourceReference(
+ R.string.staking_title_stake,
+ wrappedList(prevState.cryptoCurrencyName),
+ )
+ StakingActionCommonType.EXIT -> resourceReference(
+ R.string.staking_title_unstake,
+ wrappedList(prevState.cryptoCurrencyName),
+ )
+ else -> {
+ val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data
+ val title = confirmationState?.pendingAction?.type?.getPendingActionTitle()
- actionType == StakingActionCommonType.EXIT && currentStep != StakingStep.InitialInfo -> {
- resourceReference(
- R.string.staking_title_unstake,
- wrappedList(prevState.cryptoCurrencyName),
- )
- }
- else -> {
- resourceReference(
- R.string.staking_title_stake,
- wrappedList(prevState.cryptoCurrencyName),
- )
+ title?.takeIf { it.isNullOrEmpty() }
+ ?: resourceReference(
+ R.string.staking_title_stake,
+ wrappedList(prevState.cryptoCurrencyName),
+ )
+ }
+ }
}
}
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/NotificationsBlock.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/NotificationsBlock.kt
index dca4eefe62..a46918a130 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/NotificationsBlock.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/NotificationsBlock.kt
@@ -33,8 +33,11 @@ internal fun NotificationsBlock(notifications: ImmutableList) {
Notification(
config = notification.config,
iconTint = when (notification) {
- is StakingNotification.Warning -> TangemTheme.colors.icon.accent
+ is StakingNotification.Info,
+ is NotificationUM.Info,
+ -> TangemTheme.colors.icon.accent
+ is StakingNotification.Warning,
is NotificationUM.Error.ExceedsBalance,
is NotificationUM.Warning,
-> null
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 d6869e83d1..e2e06a8b8e 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
@@ -162,6 +162,13 @@ internal class StakingViewModel @Inject constructor(
override fun onNextClick(actionTypeToOverwrite: StakingActionCommonType?, pendingAction: PendingAction?) {
if (actionTypeToOverwrite != null) {
stateController.update { it.copy(actionType = actionTypeToOverwrite) }
+ stateController.update {
+ val confirmationState = it.confirmationState as? StakingStates.ConfirmationState.Data
+ it.copy(
+ confirmationState = confirmationState?.copy(pendingAction = pendingAction)
+ ?: StakingStates.ConfirmationState.Empty(),
+ )
+ }
}
stakingStateRouter.onNextClick()
when {
@@ -407,6 +414,14 @@ internal class StakingViewModel @Inject constructor(
ShowActionSelectorBottomSheetTransformer(
pendingActions = activeStake.pendingActions,
onActionSelect = {
+ stateController.update(ValidatorSelectChangeTransformer(activeStake.validator))
+ stateController.update(
+ AmountChangeStateTransformer(
+ cryptoCurrencyStatus,
+ activeStake.cryptoValue,
+ yield,
+ ),
+ )
onNextClick(actionTypeToOverwrite = StakingActionCommonType.PENDING_OTHER, pendingAction = it)
stateController.update(DismissBottomSheetStateTransformer())
},
@@ -548,6 +563,7 @@ internal class StakingViewModel @Inject constructor(
currencyCheck = currencyStatus,
isSubtractAvailable = isAmountSubtractAvailable,
feeError = feeError,
+ yield = yield,
),
)
}