From 6480fb498dafb3bbdc5c4a7f6a2841edc1d5930d Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 22 Jun 2026 15:30:39 +0200 Subject: [PATCH 1/3] Updated on 2026-08-14 --- .../impl/presentation/model/StakingModel.kt | 5 +++-- .../model/StakingModelNavigationTest.kt | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt index da5b4c29e8..580a5ac4c3 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt @@ -619,10 +619,11 @@ internal class StakingModel @Inject constructor( } override fun onAmountEnterClick() { - if (integration.preferredTargets.isEmpty()) { + val actionType = uiState.value.actionType + if (actionType !is StakingActionCommonType.Exit && integration.preferredTargets.isEmpty()) { messageSender.send(StakingAlertUM.noAvailableValidators()) } else { - if (uiState.value.actionType is StakingActionCommonType.Enter) { + if (actionType is StakingActionCommonType.Enter) { stateController.updateAll( ValidatorSelectChangeTransformer( selectedTarget = null, diff --git a/features/staking/impl/src/test/kotlin/com/tangem/features/staking/impl/presentation/model/StakingModelNavigationTest.kt b/features/staking/impl/src/test/kotlin/com/tangem/features/staking/impl/presentation/model/StakingModelNavigationTest.kt index 00d51a6c28..dde5946c11 100644 --- a/features/staking/impl/src/test/kotlin/com/tangem/features/staking/impl/presentation/model/StakingModelNavigationTest.kt +++ b/features/staking/impl/src/test/kotlin/com/tangem/features/staking/impl/presentation/model/StakingModelNavigationTest.kt @@ -354,6 +354,24 @@ internal class StakingModelNavigationTest : StakingModelTestBase() { model.onDestroy() } + @Test + fun `GIVEN empty preferredTargets AND Exit action WHEN onAmountEnterClick THEN no alert sent`() = runTest { + every { stateController.value } returns initialUiState + every { initialUiState.actionType } returns StakingActionCommonType.Exit(partiallyUnstakeDisabled = false) + every { testYield.preferredValidators } returns emptyList() + every { messageSender.send(any()) } just Runs + + val model = createModel(testScope = this) + advanceUntilIdle() + + model.onAmountEnterClick() + advanceUntilIdle() + + verify(exactly = 0) { messageSender.send(any()) } + + model.onDestroy() + } + @Test fun `GIVEN non-empty preferredTargets WHEN onAmountEnterClick THEN validator reset and onNextClick called`() = runTest { From b0ec8d2fd2e752130d8a46e2a73c736960a81388 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 23 Jun 2026 10:24:35 +0200 Subject: [PATCH 2/3] Updated on 2026-08-14 --- .../tokendetails/state/StakingBlockUM.kt | 2 ++ .../TokenDetailsStakingInfoConverter.kt | 24 ++++++++++++-- .../components/staking/StakingBalanceBlock.kt | 32 ++++++++++++++++--- .../staking/TokenStakingBlockLegacy.kt | 27 ++++++++++++---- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockUM.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockUM.kt index 789ddc5ec5..f7b398c873 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockUM.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockUM.kt @@ -18,6 +18,7 @@ internal sealed interface StakingBlockUM { val cryptoAmount: BigDecimal?, val fiatAmount: BigDecimal?, val onStakeClicked: () -> Unit, + val isBetaMode: Boolean = false, ) : StakingBlockUM data class StakeAvailable( @@ -26,5 +27,6 @@ internal sealed interface StakingBlockUM { val subtitleText: TextReference, val isEnabled: Boolean, val onStakeClicked: () -> Unit, + val isBetaMode: Boolean = false, ) : StakingBlockUM } \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStakingInfoConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStakingInfoConverter.kt index 845d22c4e1..5c6019e55d 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStakingInfoConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStakingInfoConverter.kt @@ -15,6 +15,8 @@ import com.tangem.domain.models.staking.RewardBlockType import com.tangem.domain.models.staking.StakingBalance import com.tangem.domain.staking.model.StakingAvailability import com.tangem.domain.staking.model.StakingEntryInfo +import com.tangem.domain.staking.model.StakingIntegrationID +import com.tangem.domain.staking.model.optionOrNull import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.feature.tokendetails.presentation.tokendetails.state.IconState import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockUM @@ -53,12 +55,20 @@ internal class TokenDetailsStakingInfoConverter( StakingAvailability.TemporaryUnavailable -> StakingBlockUM.TemporaryUnavailable StakingAvailability.Unavailable -> null is StakingAvailability.Full -> getStakedBlockOrNull(status) - is StakingAvailability.Available -> getStakingInfoBlock(status, state) + is StakingAvailability.Available -> getStakingInfoBlock( + status = status, + state = state, + isBetaMode = stakingAvailability.optionOrNull?.integrationId == StakingIntegrationID.P2PEthPool, + ) } } @Suppress("CyclomaticComplexMethod") - private fun getStakingInfoBlock(status: CryptoCurrencyStatus, state: TokenDetailsState): StakingBlockUM? { + private fun getStakingInfoBlock( + status: CryptoCurrencyStatus, + state: TokenDetailsState, + isBetaMode: Boolean, + ): StakingBlockUM? { val stakingBalance = status.value.stakingBalance as? StakingBalance.Data val stakingCryptoAmount = stakingBalance?.getTotalStakingBalance(status.currency.network.rawId) @@ -88,7 +98,12 @@ internal class TokenDetailsStakingInfoConverter( return when { stakingCryptoAmount.isNullOrZero() && stakingEntryInfo != null -> { if (!hasPendingBalances) { - getStakeAvailableState(stakingEntryInfo, iconState, isStakingButtonEnabled(status)) + getStakeAvailableState( + stakingEntryInfo = stakingEntryInfo, + iconState = iconState, + isEnabled = isStakingButtonEnabled(status), + isBetaMode = isBetaMode, + ) } else { getStakedBlockWithFiatAmount(status, pendingAmount, null) } @@ -165,6 +180,7 @@ internal class TokenDetailsStakingInfoConverter( stakingEntryInfo: StakingEntryInfo, iconState: IconState, isEnabled: Boolean, + isBetaMode: Boolean, ): StakingBlockUM.StakeAvailable { return StakingBlockUM.StakeAvailable( titleText = resourceReference(id = R.string.token_details_staking_block_title), @@ -175,6 +191,7 @@ internal class TokenDetailsStakingInfoConverter( iconState = iconState, isEnabled = isEnabled, onStakeClicked = clickIntents::onStakeBannerClick, + isBetaMode = isBetaMode, ) } @@ -205,6 +222,7 @@ internal class TokenDetailsStakingInfoConverter( ), rewardValue = getRewardText(status, stakingRewardAmount), onStakeClicked = clickIntents::onStakeBannerClick, + isBetaMode = status.value.stakingBalance is StakingBalance.Data.P2PEthPool, ) } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/StakingBalanceBlock.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/StakingBalanceBlock.kt index d077ce9d52..4ec33c934f 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/StakingBalanceBlock.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/StakingBalanceBlock.kt @@ -40,10 +40,8 @@ internal fun StakingBalanceBlock( verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4), modifier = Modifier.weight(1f), ) { - Text( - text = stringResourceSafe(R.string.staking_native), - style = TangemTheme.typography.subtitle2, - color = TangemTheme.colors.text.tertiary, + StakingBalanceTitleRow( + isBetaMode = state.isBetaMode, modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing2), ) Row(horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) { @@ -84,6 +82,32 @@ internal fun StakingBalanceBlock( } } +@Composable +private fun StakingBalanceTitleRow(isBetaMode: Boolean, modifier: Modifier = Modifier) { + Row( + horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4), + modifier = modifier, + ) { + Text( + text = stringResourceSafe(R.string.staking_native), + style = TangemTheme.typography.subtitle2, + color = TangemTheme.colors.text.tertiary, + ) + if (isBetaMode) { + Text( + text = StringsSigns.DOT, + style = TangemTheme.typography.subtitle2, + color = TangemTheme.colors.text.tertiary, + ) + Text( + text = stringResourceSafe(R.string.beta_mode_warning_title), + style = TangemTheme.typography.subtitle2, + color = TangemTheme.colors.text.tertiary, + ) + } + } +} + // region Preview @Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlockLegacy.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlockLegacy.kt index 4b78546b82..bac99ec38b 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlockLegacy.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlockLegacy.kt @@ -33,6 +33,7 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPre import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockUM import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.CurrencyIcon import com.tangem.features.tokendetails.impl.R +import com.tangem.utils.StringsSigns /** * Token staking block @@ -99,12 +100,26 @@ private fun StakingAvailableContent(state: StakingBlockUM.StakeAvailable, modifi ) SpacerW8() Column { - Text( - text = state.titleText.resolveReference(), - color = TangemTheme.colors.text.primary1, - style = TangemTheme.typography.subtitle2, - modifier = Modifier.testTag(TokenDetailsScreenTestTags.STAKING_SERVICE_TITLE), - ) + Row(horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4)) { + Text( + text = state.titleText.resolveReference(), + color = TangemTheme.colors.text.primary1, + style = TangemTheme.typography.subtitle2, + modifier = Modifier.testTag(TokenDetailsScreenTestTags.STAKING_SERVICE_TITLE), + ) + if (state.isBetaMode) { + Text( + text = StringsSigns.DOT, + color = TangemTheme.colors.text.primary1, + style = TangemTheme.typography.subtitle2, + ) + Text( + text = stringResourceSafe(R.string.beta_mode_warning_title), + color = TangemTheme.colors.text.primary1, + style = TangemTheme.typography.subtitle2, + ) + } + } Spacer(modifier = Modifier.size(TangemTheme.dimens.size4)) From baea9598e0fa377ccf6b46f0a42627347ad09db0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 23 Jun 2026 09:17:33 +0000 Subject: [PATCH 3/3] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index ef9bcda031..074e02bb80 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,9 +5,9 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.39-1575" +tangemBlockchainSdk = "develop-1567" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "releases-5.39-623" +tangemCardSdk = "develop-624" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "tangem-master-21" #tangemVico = "0.0.1" # Keep it! - used for local builds ^