Updated on 2026-08-14

This commit is contained in:
Tangem 2024-08-02 16:16:39 +03:00
parent 65ead13295
commit 6227d835b0
17 changed files with 250 additions and 93 deletions

View file

@ -16,7 +16,7 @@ class StakeKitErrorResponse(
@Json(name = "code")
val code: String? = null,
@Json(name = "countryCode")
val countryCode: String,
val countryCode: String?,
@Json(name = "regionCode")
val regionCode: String? = null,
@Json(name = "tags")

View file

@ -16,16 +16,39 @@ import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
private const val ROUNDED_LIST_WITH_DIVIDERS_HEADER_KEY = "ROUNDED_LIST_WITH_DIVIDERS_HEADER_KEY"
private const val ROUNDED_LIST_WITH_DIVIDERS_FOOTER_KEY = "ROUNDED_LIST_WITH_DIVIDERS_FOOTER_KEY"
@Composable
fun RoundedListWithDividers(rows: List<RoundedListWithDividersItemData>, modifier: Modifier = Modifier) {
fun RoundedListWithDividers(
rows: ImmutableList<RoundedListWithDividersItemData>,
modifier: Modifier = Modifier,
headerContent: (@Composable () -> Unit)? = null,
footerContent: (@Composable () -> Unit)? = null,
) {
LazyColumn(modifier = modifier) {
this.roundedListItems(rows)
this.roundedListWithDividersItems(
rows = rows,
headerContent = headerContent,
footerContent = footerContent,
)
}
}
fun LazyListScope.roundedListItems(rows: List<RoundedListWithDividersItemData>) {
fun LazyListScope.roundedListWithDividersItems(
rows: ImmutableList<RoundedListWithDividersItemData>,
headerContent: (@Composable () -> Unit)? = null,
footerContent: (@Composable () -> Unit)? = null,
) {
if (headerContent != null) {
item(key = ROUNDED_LIST_WITH_DIVIDERS_HEADER_KEY) {
headerContent()
}
}
itemsIndexed(
items = rows,
key = { _, item -> item.id },
@ -40,6 +63,12 @@ fun LazyListScope.roundedListItems(rows: List<RoundedListWithDividersItemData>)
RoundedListDivider()
}
}
if (footerContent != null) {
item(key = ROUNDED_LIST_WITH_DIVIDERS_FOOTER_KEY) {
footerContent()
}
}
}
@Composable

View file

@ -46,6 +46,7 @@ import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.orZero
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
@ -135,7 +136,7 @@ internal class DefaultStakingRepository(
val yield = getYield(cryptoCurrencyId, symbol)
StakingEntryInfo(
interestRate = yield.apy,
interestRate = requireNotNull(yield.validators.maxByOrNull { it.apr.orZero() }?.apr),
periodInDays = yield.metadata.cooldownPeriod.days,
tokenSymbol = yield.token.symbol,
)
@ -568,23 +569,24 @@ internal class DefaultStakingRepository(
const val AVALANCHE_INTEGRATION_ID = "avalanche-avax-native-staking"
const val TRON_INTEGRATION_ID = "tron-trx-native-staking"
const val CRONOS_INTEGRATION_ID = "cronos-cro-native-staking"
const val BINANCE_INTEGRATION_ID = "binance-bnb-native-staking"
const val BINANCE_INTEGRATION_ID = "bsc-bnb-native-staking"
const val KAVA_INTEGRATION_ID = "kava-kava-native-staking"
const val NEAR_INTEGRATION_ID = "near-near-native-staking"
const val TEZOS_INTEGRATION_ID = "tezos-xtz-native-staking"
// uncomment items as implementation is ready
val integrationIdMap = mapOf(
Blockchain.Solana.toCoinId() to SOLANA_INTEGRATION_ID,
Blockchain.Cosmos.toCoinId() to COSMOS_INTEGRATION_ID,
Blockchain.Polkadot.toCoinId() to POLKADOT_INTEGRATION_ID,
Blockchain.Polygon.toCoinId() to ETHEREUM_INTEGRATION_ID,
Blockchain.Avalanche.toCoinId() to AVALANCHE_INTEGRATION_ID,
Blockchain.Tron.toCoinId() to TRON_INTEGRATION_ID,
Blockchain.Cronos.toCoinId() to CRONOS_INTEGRATION_ID,
Blockchain.Binance.toCoinId() to BINANCE_INTEGRATION_ID,
Blockchain.Kava.toCoinId() to KAVA_INTEGRATION_ID,
Blockchain.Near.toCoinId() to NEAR_INTEGRATION_ID,
Blockchain.Tezos.toCoinId() to TEZOS_INTEGRATION_ID,
// Blockchain.Polkadot.toCoinId() to POLKADOT_INTEGRATION_ID,
// Blockchain.Polygon.toCoinId() to ETHEREUM_INTEGRATION_ID,
// Blockchain.Avalanche.toCoinId() to AVALANCHE_INTEGRATION_ID,
// Blockchain.Tron.toCoinId() to TRON_INTEGRATION_ID,
// Blockchain.Cronos.toCoinId() to CRONOS_INTEGRATION_ID,
// Blockchain.Binance.toCoinId() to BINANCE_INTEGRATION_ID,
// Blockchain.Kava.toCoinId() to KAVA_INTEGRATION_ID,
// Blockchain.Near.toCoinId() to NEAR_INTEGRATION_ID,
// Blockchain.Tezos.toCoinId() to TEZOS_INTEGRATION_ID,
)
}
}

View file

@ -1,9 +1,11 @@
package com.tangem.features.staking.impl.presentation.state
import androidx.compose.runtime.Immutable
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.domain.appcurrency.model.AppCurrency
import java.math.BigDecimal
@Immutable
sealed class FeeState {
data class Content(

View file

@ -1,5 +1,6 @@
package com.tangem.features.staking.impl.presentation.state
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.staking.model.stakekit.BalanceType
import com.tangem.domain.staking.model.stakekit.PendingAction
@ -12,12 +13,14 @@ sealed class InnerYieldBalanceState {
val rewardsCrypto: String,
val rewardsFiat: String,
val isRewardsToClaim: Boolean,
val balance: List<BalanceGroupedState>,
val balance: ImmutableList<BalanceGroupedState>,
) : InnerYieldBalanceState()
data object Empty : InnerYieldBalanceState()
}
// TODO staking get rid of unstable types
@Immutable
data class BalanceGroupedState(
val items: ImmutableList<BalanceState>,
val footer: TextReference?,
@ -26,6 +29,7 @@ data class BalanceGroupedState(
val isClickable: Boolean,
)
@Immutable
data class BalanceState(
val validator: Yield.Validator,
val cryptoValue: String,

View file

@ -3,6 +3,7 @@ package com.tangem.features.staking.impl.presentation.state
import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.features.staking.impl.R
@ -23,7 +24,15 @@ internal sealed class StakingNotification(val config: NotificationConfig) {
onCloseClick = onCloseClick,
),
) {
// TODO staking
data class StakedPositionNotFoundError(val message: String) : Error(
title = stringReference(message),
subtitle = stringReference(message),
)
data class Common(val subtitle: TextReference) : Error(
title = resourceReference(R.string.common_error),
subtitle = subtitle,
)
}
sealed class Warning(

View file

@ -3,6 +3,7 @@ package com.tangem.features.staking.impl.presentation.state
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.navigationButtons.NavigationButtonsState
import com.tangem.core.ui.event.consumedEvent
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub
import com.tangem.features.staking.impl.presentation.state.transformers.SetButtonsStateTransformer
@ -42,6 +43,7 @@ internal class StakingStateController @Inject constructor() {
private fun getInitialState(): StakingUiState {
return StakingUiState(
title = TextReference.EMPTY,
clickIntents = StakingClickIntentsStub,
cryptoCurrencyName = "",
currentStep = StakingStep.InitialInfo,

View file

@ -18,6 +18,7 @@ import kotlinx.collections.immutable.ImmutableList
*/
@Immutable
internal data class StakingUiState(
val title: TextReference,
val clickIntents: StakingClickIntents,
val cryptoCurrencyName: String,
val currentStep: StakingStep,

View file

@ -69,6 +69,7 @@ internal class YieldBalancesConverter(
)
}
}
.toPersistentList()
private fun List<BalanceItem>.mapBalances(): List<BalanceState> {
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()

View file

@ -65,7 +65,7 @@ internal object InitialStakingStatePreview {
rewardsFiat = "100 $",
rewardsCrypto = "100 SOL",
isRewardsToClaim = false,
balance = listOf(
balance = persistentListOf(
BalanceGroupedState(
title = stringReference("Staked"),
footer = null,

View file

@ -0,0 +1,36 @@
package com.tangem.features.staking.impl.presentation.state.transformers
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.features.staking.impl.presentation.state.*
import com.tangem.utils.transformer.Transformer
import kotlinx.collections.immutable.toPersistentList
internal class AddStakingErrorTransformer(
private val error: StakingError,
) : Transformer<StakingUiState> {
override fun transform(prevState: StakingUiState): StakingUiState {
val confirmationState =
prevState.confirmationState as? StakingStates.ConfirmationState.Data ?: return prevState
return prevState.copy(
confirmationState = confirmationState.copy(
notifications = (confirmationState.notifications + convertToNotification(error)).toPersistentList(),
feeState = FeeState.Error,
),
)
}
private fun convertToNotification(error: StakingError): StakingNotification {
return when (error) {
is StakingError.StakedPositionNotFoundError -> StakingNotification.Error.StakedPositionNotFoundError(
message = error.toString(),
)
// TODO staking
else -> StakingNotification.Error.Common(
subtitle = stringReference(error.toString()),
)
}
}
}

View file

@ -5,10 +5,7 @@ import com.tangem.common.ui.amountScreen.converters.AmountStateConverter
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
import com.tangem.core.ui.components.list.RoundedListWithDividersItemData
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.staking.model.stakekit.Yield
@ -28,7 +25,7 @@ import com.tangem.utils.Provider
import com.tangem.utils.extensions.orZero
import com.tangem.utils.transformer.Transformer
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
import java.math.BigDecimal
internal class SetInitialDataStateTransformer(
@ -62,6 +59,10 @@ internal class SetInitialDataStateTransformer(
override fun transform(prevState: StakingUiState): StakingUiState {
return prevState.copy(
title = TextReference.Res(
R.string.staking_initial_info_title,
wrappedList(cryptoCurrencyStatusProvider().currency.name),
),
clickIntents = clickIntents,
currentStep = StakingStep.InitialInfo,
initialInfoState = createInitialInfoState(),
@ -87,70 +88,118 @@ internal class SetInitialDataStateTransformer(
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance
return persistentListOf(
RoundedListWithDividersItemData(
id = R.string.staking_details_available,
startText = TextReference.Res(R.string.staking_details_available),
endText = TextReference.Str(
value = BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = cryptoCurrencyStatus.value.amount,
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
decimals = cryptoCurrencyStatus.currency.decimals,
),
return listOfNotNull(
createAvailableItem(cryptoCurrencyStatus),
createApyItem(),
createOnStakeItem(cryptoCurrencyStatus, yieldBalance),
createUnbondingPeriodItem(),
createMinimumRequirementItem(cryptoCurrencyStatus),
createRewardClaimingItem(),
createWarmupPeriodItem(),
createRewardScheduleItem(),
).toPersistentList()
}
private fun createAvailableItem(cryptoCurrencyStatus: CryptoCurrencyStatus): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_available,
startText = TextReference.Res(R.string.staking_details_available),
endText = TextReference.Str(
value = BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = cryptoCurrencyStatus.value.amount,
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
decimals = cryptoCurrencyStatus.currency.decimals,
),
),
RoundedListWithDividersItemData(
id = R.string.staking_details_apy,
startText = TextReference.Res(R.string.staking_details_apy),
endText = getAprRange(),
iconClick = { clickIntents.onInfoClick(InfoType.APY) },
),
RoundedListWithDividersItemData(
id = R.string.staking_details_on_stake,
startText = TextReference.Res(R.string.staking_details_on_stake),
endText = TextReference.Str(
value = BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = (yieldBalance as? YieldBalance.Data)?.getTotalStakingBalance().orZero(),
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
decimals = cryptoCurrencyStatus.currency.decimals,
),
)
}
private fun createApyItem(): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_apy,
startText = TextReference.Res(R.string.staking_details_apy),
endText = getAprRange(),
iconClick = { clickIntents.onInfoClick(InfoType.APY) },
)
}
private fun createOnStakeItem(
cryptoCurrencyStatus: CryptoCurrencyStatus,
yieldBalance: YieldBalance?,
): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_on_stake,
startText = TextReference.Res(R.string.staking_details_on_stake),
endText = TextReference.Str(
value = BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = (yieldBalance as? YieldBalance.Data)?.getTotalStakingBalance().orZero(),
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
decimals = cryptoCurrencyStatus.currency.decimals,
),
),
RoundedListWithDividersItemData(
id = R.string.staking_details_unbonding_period,
startText = TextReference.Res(R.string.staking_details_unbonding_period),
endText = TextReference.Str(yield.metadata.cooldownPeriod.days.toString()),
iconClick = { clickIntents.onInfoClick(InfoType.UNBOUNDING_PERIOD) },
)
}
private fun createUnbondingPeriodItem(): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_unbonding_period,
startText = TextReference.Res(R.string.staking_details_unbonding_period),
endText = pluralReference(
id = R.plurals.common_days,
count = yield.metadata.cooldownPeriod.days,
formatArgs = wrappedList(yield.metadata.cooldownPeriod.days),
),
iconClick = { clickIntents.onInfoClick(InfoType.UNBONDING_PERIOD) },
)
}
private fun createMinimumRequirementItem(
cryptoCurrencyStatus: CryptoCurrencyStatus,
): RoundedListWithDividersItemData? {
val minimumCryptoAmount = yield.args.enter.args[Yield.Args.ArgType.AMOUNT]?.minimum
return minimumCryptoAmount?.let {
RoundedListWithDividersItemData(
id = R.string.staking_details_minimum_requirement,
startText = TextReference.Res(R.string.staking_details_minimum_requirement),
endText = TextReference.Str(
value = BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = yield.args.enter.args[Yield.Args.ArgType.AMOUNT]?.minimum,
cryptoAmount = it,
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
decimals = cryptoCurrencyStatus.currency.decimals,
),
),
)
}
}
private fun createRewardClaimingItem(): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_reward_claiming,
startText = TextReference.Res(R.string.staking_details_reward_claiming),
endText = TextReference.Str(yield.metadata.rewardClaiming),
iconClick = { clickIntents.onInfoClick(InfoType.REWARD_CLAIMING) },
)
}
private fun createWarmupPeriodItem(): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_warmup_period,
startText = TextReference.Res(R.string.staking_details_warmup_period),
endText = pluralReference(
id = R.plurals.common_days,
count = yield.metadata.warmupPeriod.days,
formatArgs = wrappedList(yield.metadata.warmupPeriod.days),
),
RoundedListWithDividersItemData(
id = R.string.staking_details_reward_claiming,
startText = TextReference.Res(R.string.staking_details_reward_claiming),
endText = TextReference.Str(yield.metadata.rewardClaiming),
iconClick = { clickIntents.onInfoClick(InfoType.REWARD_CLAIMING) },
),
RoundedListWithDividersItemData(
id = R.string.staking_details_warmup_period,
startText = TextReference.Res(R.string.staking_details_warmup_period),
endText = TextReference.Str(yield.metadata.warmupPeriod.days.toString()),
iconClick = { clickIntents.onInfoClick(InfoType.WARMUP_PERIOD) },
),
RoundedListWithDividersItemData(
id = R.string.staking_details_reward_schedule,
startText = TextReference.Res(R.string.staking_details_reward_schedule),
endText = TextReference.Str(yield.metadata.rewardSchedule),
iconClick = { clickIntents.onInfoClick(InfoType.REWARD_SCHEDULE) },
),
iconClick = { clickIntents.onInfoClick(InfoType.WARMUP_PERIOD) },
)
}
private fun createRewardScheduleItem(): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_reward_schedule,
startText = TextReference.Res(R.string.staking_details_reward_schedule),
endText = TextReference.Str(yield.metadata.rewardSchedule),
iconClick = { clickIntents.onInfoClick(InfoType.REWARD_SCHEDULE) },
)
}

View file

@ -22,7 +22,7 @@ internal class ShowInfoBottomSheetStateTransformer(
title = resourceReference(R.string.staking_details_apy),
text = resourceReference(R.string.staking_details_apy_info),
)
InfoType.UNBOUNDING_PERIOD -> StakingInfoBottomSheetConfig(
InfoType.UNBONDING_PERIOD -> StakingInfoBottomSheetConfig(
title = resourceReference(R.string.staking_details_unbonding_period),
text = resourceReference(R.string.staking_details_unbonding_period_info),
)
@ -46,7 +46,7 @@ internal class ShowInfoBottomSheetStateTransformer(
enum class InfoType {
APY,
UNBOUNDING_PERIOD,
UNBONDING_PERIOD,
REWARD_CLAIMING,
WARMUP_PERIOD,
REWARD_SCHEDULE,

View file

@ -26,7 +26,7 @@ import com.tangem.core.ui.components.SpacerH12
import com.tangem.core.ui.components.containers.FooterContainer
import com.tangem.core.ui.components.inputrow.InputRowDefault
import com.tangem.core.ui.components.inputrow.InputRowImageInfo
import com.tangem.core.ui.components.list.roundedListItems
import com.tangem.core.ui.components.list.roundedListWithDividersItems
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -40,9 +40,12 @@ import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickInten
import com.tangem.utils.StringsSigns.DOT
import com.tangem.utils.StringsSigns.PLUS
import com.tangem.utils.extensions.orZero
import kotlinx.collections.immutable.ImmutableList
// TODO staking metrics block is temporary disabled
// private const val METRICS_BLOCK_KEY = "MetricsBlock"
private const val STAKING_REWARD_BLOCK_KEY = "StakingRewardBlock"
private const val METRICS_BLOCK_KEY = "MetricsBlock"
private const val ACTIVE_STAKING_BLOCK_KEY = "ActiveStakingBlock"
@OptIn(ExperimentalFoundationApi::class)
@ -52,21 +55,25 @@ internal fun StakingInitialInfoContent(state: StakingStates.InitialInfoState, cl
LazyColumn(
modifier = Modifier
.background(TangemTheme.colors.background.tertiary)
.background(TangemTheme.colors.background.secondary)
.fillMaxSize(),
contentPadding = PaddingValues(TangemTheme.dimens.spacing16),
) {
if (state.yieldBalance == InnerYieldBalanceState.Empty) {
item(key = METRICS_BLOCK_KEY) {
Column(modifier = Modifier.animateItemPlacement()) {
MetricsBlock(state)
SpacerH12()
}
}
}
// TODO staking metrics block is temporary disabled
// https://www.figma.com/design/Vs6SkVsFnUPsSCNwlnVf5U?node-id=12484-35755#876661319
// if (state.yieldBalance == InnerYieldBalanceState.Empty) {
// item(key = METRICS_BLOCK_KEY) {
// Column(modifier = Modifier.animateItemPlacement()) {
// MetricsBlock(state)
// SpacerH12()
// }
// }
// }
this.roundedListItems(state.infoItems)
item { SpacerH12() }
this.roundedListWithDividersItems(
rows = state.infoItems,
footerContent = { SpacerH12() },
)
if (state.yieldBalance is InnerYieldBalanceState.Data) {
item(key = STAKING_REWARD_BLOCK_KEY) {
@ -93,6 +100,7 @@ internal fun StakingInitialInfoContent(state: StakingStates.InitialInfoState, cl
}
}
@Suppress("UnusedPrivateMember")
@Composable
private fun MetricsBlock(state: StakingStates.InitialInfoState.Data) {
Column(
@ -193,7 +201,7 @@ private fun StakingRewardBlock(
}
@Composable
private fun ActiveStakingBlock(groups: List<BalanceGroupedState>, onClick: (BalanceState) -> Unit) {
private fun ActiveStakingBlock(groups: ImmutableList<BalanceGroupedState>, onClick: (BalanceState) -> Unit) {
Column(
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
) {

View file

@ -16,6 +16,7 @@ import com.tangem.common.ui.amountScreen.AmountScreenContent
import com.tangem.common.ui.navigationButtons.NavigationButtonsBlock
import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIcon
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.staking.impl.R
import com.tangem.features.staking.impl.presentation.state.StakingStates
@ -74,7 +75,7 @@ private fun SendAppBar(uiState: StakingUiState) {
StakingStep.RewardsValidators,
StakingStep.Validators,
StakingStep.Confirmation,
-> stringResource(id = R.string.common_stake)
-> uiState.title.resolveReference()
}
val backIcon = when (uiState.currentStep) {
StakingStep.Amount,

View file

@ -1,13 +1,23 @@
package com.tangem.features.staking.impl.presentation.ui.block
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.staking.impl.presentation.state.StakingNotification
import kotlinx.collections.immutable.ImmutableList
@Composable
internal fun NotificationsBlock(notifications: List<StakingNotification>) {
notifications.forEach {
Notification(config = it.config, iconTint = TangemTheme.colors.icon.accent)
internal fun NotificationsBlock(notifications: ImmutableList<StakingNotification>) {
notifications.forEach { notification ->
key(notification) {
Notification(
config = notification.config,
iconTint = when (notification) {
is StakingNotification.Error -> TangemTheme.colors.icon.warning
is StakingNotification.Warning -> TangemTheme.colors.icon.accent
},
)
}
}
}

View file

@ -180,7 +180,10 @@ internal class StakingViewModel @Inject constructor(
passthrough = pendingAction?.passthrough,
type = pendingAction?.type,
),
).getOrElse { error("Can't get fee info") }
).getOrElse {
stateController.update(AddStakingErrorTransformer(it))
return@launch
}
stateController.update(
SetConfirmationStateAssentTransformer(