Updated on 2026-08-14
This commit is contained in:
commit
e817b032f4
12 changed files with 83 additions and 50 deletions
|
|
@ -671,6 +671,7 @@
|
|||
<string name="staking_notification_earn_rewards_text_period_week">Staking allows you to earn %1$s. Your staking rewards arrive every week.</string>
|
||||
<string name="staking_notification_earn_rewards_title">Earn staking rewards</string>
|
||||
<string name="staking_notification_unstake_text">Rewards stop accruing immediately after you start unstaking. The unstaking process takes %s.</string>
|
||||
<string name="staking_preparing">Preparing</string>
|
||||
<string name="staking_ready_to_withdraw">Ready to withdraw</string>
|
||||
<string name="staking_rebond">Rebond</string>
|
||||
<string name="staking_restake">Restake</string>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -39,5 +39,6 @@ data class BalanceState(
|
|||
val fiatAmount: TextReference,
|
||||
val rawCurrencyId: String?,
|
||||
val unbondingPeriod: TextReference,
|
||||
val warmupPeriod: TextReference,
|
||||
val pendingActions: ImmutableList<PendingAction>,
|
||||
)
|
||||
|
|
@ -26,9 +26,7 @@ internal class StakingStateRouter(
|
|||
StakingStep.Validators,
|
||||
StakingStep.Amount,
|
||||
-> showConfirmation()
|
||||
StakingStep.Confirmation -> {
|
||||
// TODO staking handle
|
||||
}
|
||||
StakingStep.Confirmation -> showInitial()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<PendingAction>,
|
||||
): 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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ internal class SetButtonsStateTransformer : Transformer<StakingUiState> {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -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<AppCurrency>,
|
||||
|
|
@ -39,6 +37,7 @@ internal class SetConfirmationStateCompletedTransformer(
|
|||
validatorState = validatorState.copySealed(
|
||||
isClickable = false,
|
||||
),
|
||||
notifications = persistentListOf(),
|
||||
transactionDoneState = TransactionDoneState.Content(
|
||||
timestamp = System.currentTimeMillis(),
|
||||
txUrl = txUrl,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ private fun ActiveStakingBlock(groups: ImmutableList<BalanceGroupedState>, 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),
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue