From 681fe664c632c7eb3592525e0fe6c71a6bb09c05 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 30 Aug 2024 15:23:16 +0500 Subject: [PATCH 1/3] Updated on 2026-08-14 --- .../transformers/SetConfirmationStateCompletedTransformer.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateCompletedTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateCompletedTransformer.kt index 27e6593bd0..d2e2435917 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateCompletedTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateCompletedTransformer.kt @@ -4,11 +4,9 @@ import com.tangem.blockchain.common.transaction.Fee import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus 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.StakingUiState -import com.tangem.features.staking.impl.presentation.state.TransactionDoneState import com.tangem.utils.Provider import com.tangem.utils.transformer.Transformer +import kotlinx.collections.immutable.persistentListOf internal class SetConfirmationStateCompletedTransformer( private val appCurrencyProvider: Provider, @@ -39,6 +37,7 @@ internal class SetConfirmationStateCompletedTransformer( validatorState = validatorState.copySealed( isClickable = false, ), + notifications = persistentListOf(), transactionDoneState = TransactionDoneState.Content( timestamp = System.currentTimeMillis(), txUrl = txUrl, From 01b655feb7a6012a0c1ed8f08d5350ba5cf57bd2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 30 Aug 2024 15:23:48 +0500 Subject: [PATCH 2/3] Updated on 2026-08-14 --- .../presentation/state/StakingStateRouter.kt | 4 +--- .../transformers/SetButtonsStateTransformer.kt | 2 +- .../ui/StakingConfirmationContent.kt | 11 ++++++++--- .../presentation/viewmodel/StakingViewModel.kt | 16 ++++++++-------- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt index 03cc906908..5dd1f3de27 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt @@ -26,9 +26,7 @@ internal class StakingStateRouter( StakingStep.Validators, StakingStep.Amount, -> showConfirmation() - StakingStep.Confirmation -> { - // TODO staking handle - } + StakingStep.Confirmation -> showInitial() } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt index 6bd2c902fa..b18c96f147 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt @@ -152,7 +152,7 @@ internal class SetButtonsStateTransformer : Transformer { private fun StakingUiState.onConfirmationClick() { if (confirmationState is StakingStates.ConfirmationState.Data) { if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) { - clickIntents.onBackClick() + clickIntents.onNextClick() } else { val isEnterAction = actionType == StakingActionCommonType.ENTER val isApproveNeeded = confirmationState.isApprovalNeeded diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmationContent.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmationContent.kt index ae5079b938..d7a9431621 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmationContent.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmationContent.kt @@ -3,11 +3,15 @@ package com.tangem.features.staking.impl.presentation.ui import android.content.res.Configuration import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview @@ -45,11 +49,12 @@ internal fun StakingConfirmationContent( .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16), ) { + val doneState = state.transactionDoneState AnimatedVisibility( - visible = state.transactionDoneState is TransactionDoneState.Content, + visible = doneState is TransactionDoneState.Content, modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing12), ) { - val transactionDoneStateContent = state.transactionDoneState as TransactionDoneState.Content + val transactionDoneStateContent = remember(this) { doneState as TransactionDoneState.Content } TransactionDoneTitle( titleRes = R.string.sent_transaction_sent_title, date = transactionDoneStateContent.timestamp, 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 1c18173837..4eba6fabde 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 @@ -164,23 +164,19 @@ internal class StakingViewModel @Inject constructor( stateController.update { it.copy(actionType = actionType) } } stakingStateRouter.onNextClick() - if (isAssentState()) { - getFee(pendingAction) + when { + isInitState() -> stateController.update(SetConfirmationStateLoadingTransformer(yield)) + isAssentState() -> getFee(pendingAction) } } override fun onActionClick() { handleOnNextConfirmationClick() - stakingStateRouter.onNextClick() } override fun getFee(pendingAction: PendingAction?) { viewModelScope.launch { - stateController.update( - SetConfirmationStateLoadingTransformer( - yield = yield, - ), - ) + stateController.update(SetConfirmationStateLoadingTransformer(yield)) val cryptoCurrencyValue = cryptoCurrencyStatus.value val confirmationState = value.confirmationState as? StakingStates.ConfirmationState.Data ?: error("No confirmation state") @@ -871,6 +867,10 @@ internal class StakingViewModel @Inject constructor( InnerConfirmationStakingState.ASSENT } + private fun isInitState(): Boolean { + return value.currentStep == StakingStep.InitialInfo + } + private suspend fun checkIfSubtractAvailable() { isAmountSubtractAvailable = isAmountSubtractAvailableUseCase(userWalletId, cryptoCurrencyStatus.currency) .getOrElse { false } From a809fa07b6a4a10d4a14742e1d1630fab7085a88 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 30 Aug 2024 15:24:18 +0500 Subject: [PATCH 3/3] Updated on 2026-08-14 --- core/res/src/main/res/values/strings.xml | 1 + .../staking/model/stakekit/YieldBalance.kt | 25 ++++++++++++++--- .../state/InnerYieldBalanceState.kt | 1 + .../RewardsValidatorStateConverter.kt | 27 ++++++++++++------- .../converters/YieldBalancesConverter.kt | 21 ++++----------- .../previewdata/InitialStakingStatePreview.kt | 6 ++++- .../ui/StakingInitialInfoContent.kt | 14 +++++++++- 7 files changed, 63 insertions(+), 32 deletions(-) diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 314a9a07d4..7b30804e92 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -671,6 +671,7 @@ Staking allows you to earn %1$s. Your staking rewards arrive every week. Earn staking rewards Rewards stop accruing immediately after you start unstaking. The unstaking process takes %s. + Preparing Ready to withdraw Rebond Restake diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/YieldBalance.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/YieldBalance.kt index adf85b9751..1c7c27ac54 100644 --- a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/YieldBalance.kt +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/YieldBalance.kt @@ -78,11 +78,28 @@ data class PendingAction( enum class BalanceType { AVAILABLE, STAKED, - UNSTAKING, - UNSTAKED, PREPARING, - REWARDS, - LOCKED, + UNSTAKING, UNLOCKING, + UNSTAKED, + LOCKED, + REWARDS, UNKNOWN, + ; + + companion object { + fun BalanceType.isClickable() = when (this) { + STAKED, + UNSTAKED, + -> true + AVAILABLE, + UNSTAKING, + PREPARING, + REWARDS, + LOCKED, + UNLOCKING, + UNKNOWN, + -> false + } + } } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/InnerYieldBalanceState.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/InnerYieldBalanceState.kt index ef7e4e8fec..c2ed6f2d62 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/InnerYieldBalanceState.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/InnerYieldBalanceState.kt @@ -39,5 +39,6 @@ data class BalanceState( val fiatAmount: TextReference, val rawCurrencyId: String?, val unbondingPeriod: TextReference, + val warmupPeriod: TextReference, val pendingActions: ImmutableList, ) \ 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 a1c35482de..b27bdf6c41 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,9 @@ package com.tangem.features.staking.impl.presentation.state.converters -import com.tangem.core.ui.extensions.* +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 import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.core.ui.utils.parseBigDecimal import com.tangem.domain.appcurrency.model.AppCurrency @@ -46,16 +49,11 @@ internal class RewardsValidatorStateConverter( } val cryptoValue = balance.amount val fiatValue = cryptoCurrencyStatus.value.fiatRate?.times(cryptoValue) - val unbondingPeriod = yield.metadata.cooldownPeriod.days + validator?.toBalanceState( cryptoCurrencyStatus = cryptoCurrencyStatus, cryptoValue = cryptoValue, fiatValue = fiatValue, - unbondingPeriod = pluralReference( - id = R.plurals.common_days, - count = unbondingPeriod, - formatArgs = wrappedList(unbondingPeriod), - ), pendingActions = balance.pendingActions.toPersistentList(), ) } @@ -64,12 +62,12 @@ internal class RewardsValidatorStateConverter( cryptoCurrencyStatus: CryptoCurrencyStatus, cryptoValue: BigDecimal, fiatValue: BigDecimal?, - unbondingPeriod: TextReference, pendingActions: ImmutableList, ): BalanceState { val appCurrency = appCurrencyProvider() val cryptoCurrency = cryptoCurrencyStatus.currency - + val unbondingPeriod = yield.metadata.cooldownPeriod.days + val warmupPeriod = yield.metadata.warmupPeriod.days val cryptoAmount = stringReference( BigDecimalFormatter.formatCryptoAmount( cryptoAmount = cryptoValue, @@ -94,7 +92,16 @@ internal class RewardsValidatorStateConverter( cryptoAmount = cryptoAmount, fiatAmount = fiatAmount, rawCurrencyId = cryptoCurrency.id.rawCurrencyId, - unbondingPeriod = unbondingPeriod, + unbondingPeriod = pluralReference( + id = R.plurals.common_days, + count = unbondingPeriod, + formatArgs = wrappedList(unbondingPeriod), + ), + warmupPeriod = pluralReference( + id = R.plurals.common_days, + count = unbondingPeriod, + formatArgs = wrappedList(warmupPeriod), + ), pendingActions = pendingActions, ) } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/YieldBalancesConverter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/YieldBalancesConverter.kt index 9be3086028..17c6e659d7 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/YieldBalancesConverter.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/YieldBalancesConverter.kt @@ -6,6 +6,7 @@ import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.core.ui.utils.parseBigDecimal import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.staking.model.stakekit.* +import com.tangem.domain.staking.model.stakekit.BalanceType.Companion.isClickable import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.features.staking.impl.R import com.tangem.features.staking.impl.presentation.state.BalanceGroupedState @@ -61,7 +62,7 @@ internal class YieldBalancesConverter( .groupBy { it.type.toGroup() } .mapNotNull { item -> val (title, footer) = getGroupTitle(item.key) - val isClickable = getClickableType(item.key) + val isClickable = item.key.isClickable() title?.let { BalanceGroupedState( items = item.value.mapBalances().toPersistentList(), @@ -88,6 +89,7 @@ internal class YieldBalancesConverter( val cryptoAmount = balance.amount val fiatAmount = cryptoCurrencyStatus.value.fiatRate?.times(cryptoAmount) val unbonding = getUnbondingDate(balance.date) + val warmupPeriod = yield.metadata.warmupPeriod.days validator?.let { BalanceState( validator = validator, @@ -108,6 +110,7 @@ internal class YieldBalancesConverter( ), rawCurrencyId = balance.rawCurrencyId, unbondingPeriod = unbonding, + warmupPeriod = pluralReference(R.plurals.common_days, warmupPeriod, wrappedList(warmupPeriod)), pendingActions = balance.pendingActions.toPersistentList(), ) } @@ -128,27 +131,13 @@ internal class YieldBalancesConverter( resourceReference(R.string.staking_unstaked_footer) BalanceType.UNSTAKING -> resourceReference(R.string.staking_unstaking) to null BalanceType.AVAILABLE -> null to null - BalanceType.PREPARING -> null to null + BalanceType.PREPARING -> resourceReference(R.string.staking_preparing) to null BalanceType.REWARDS -> null to null BalanceType.LOCKED -> null to null BalanceType.UNLOCKING -> null to null BalanceType.UNKNOWN -> null to null } - private fun getClickableType(type: BalanceType) = when (type) { - BalanceType.STAKED, - BalanceType.UNSTAKED, - -> true - BalanceType.AVAILABLE, - BalanceType.UNSTAKING, - BalanceType.PREPARING, - BalanceType.REWARDS, - BalanceType.LOCKED, - BalanceType.UNLOCKING, - BalanceType.UNKNOWN, - -> false - } - private fun getUnbondingDate(date: DateTime?): TextReference { val now = DateTime.now().millis val nowCalendar = Calendar.getInstance() diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/InitialStakingStatePreview.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/InitialStakingStatePreview.kt index 66d92d8f89..15efd12337 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/InitialStakingStatePreview.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/InitialStakingStatePreview.kt @@ -6,7 +6,10 @@ import com.tangem.core.ui.extensions.stringReference import com.tangem.domain.staking.model.stakekit.BalanceType import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.features.staking.impl.R -import com.tangem.features.staking.impl.presentation.state.* +import com.tangem.features.staking.impl.presentation.state.BalanceGroupedState +import com.tangem.features.staking.impl.presentation.state.BalanceState +import com.tangem.features.staking.impl.presentation.state.InnerYieldBalanceState +import com.tangem.features.staking.impl.presentation.state.StakingStates import kotlinx.collections.immutable.persistentListOf internal object InitialStakingStatePreview { @@ -87,6 +90,7 @@ internal object InitialStakingStatePreview { ), unbondingPeriod = stringReference("3 days"), pendingActions = persistentListOf(), + warmupPeriod = stringReference("3 days"), ), ), ), diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt index 8bd4543778..c84e8247e3 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt @@ -209,7 +209,7 @@ private fun ActiveStakingBlock(groups: ImmutableList, onCli InputRowImageInfo( subtitle = stringReference(balance.validator.name), caption = getCaption(group.type, balance), - isGrayscaleImage = group.type == BalanceType.UNSTAKING, + isGrayscaleImage = !group.isClickable, infoTitle = balance.fiatAmount, infoSubtitle = balance.cryptoAmount, imageUrl = balance.validator.image.orEmpty(), @@ -248,6 +248,18 @@ private fun getCaption(balanceType: BalanceType, balance: BalanceState): TextRef BalanceType.UNSTAKED -> { resourceReference(R.string.staking_ready_to_withdraw) } + BalanceType.PREPARING -> { + combinedReference( + resourceReference(R.string.staking_details_warmup_period), + annotatedReference { + appendSpace() + appendColored( + text = balance.warmupPeriod.resolveReference(), + color = TangemTheme.colors.text.accent, + ) + }, + ) + } else -> { combinedReference( resourceReference(R.string.staking_details_apr),