From 5060b5c0281b959b0fd6b09bde2ece5a77315c39 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 18 Dec 2025 16:25:57 +0200 Subject: [PATCH] Updated on 2026-08-14 --- .../response/P2PEthPoolVaultsResponse.kt | 11 +++-- .../staking/DefaultP2PEthPoolRepository.kt | 2 +- .../P2PEthPoolStakingBalanceConverter.kt | 26 +++++++--- .../ethpool/P2PEthPoolVaultConverter.kt | 15 ++++-- .../DefaultMultiStakingBalanceFetcher.kt | 4 +- .../store/DefaultP2PEthPoolBalancesStore.kt | 12 +++++ .../staking/store/P2PEthPoolBalancesStore.kt | 2 + .../tangem/data/staking/StakingBalanceExt.kt | 2 +- .../staking/model/common/RewardClaiming.kt | 10 ++++ .../staking/model/common/RewardSchedule.kt | 15 ++++++ .../staking/model/common/StakingActionArgs.kt | 17 +++++++ .../model/common/StakingAmountRequirement.kt | 19 ++++++++ .../staking/model/P2PEthPoolIntegration.kt | 27 +++++++++-- .../staking/model/StakeKitIntegration.kt | 47 +++++++++++++++++-- .../staking/model/StakingIntegration.kt | 13 ++--- .../SetInitialDataStateTransformer.kt | 10 ++-- .../AmountRequirementStateTransformer.kt | 11 ++--- .../StakingInfoNotificationsFactory.kt | 5 +- .../state/utils/StakingRewardsUtils.kt | 28 +++++------ 19 files changed, 212 insertions(+), 64 deletions(-) create mode 100644 domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/RewardClaiming.kt create mode 100644 domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/RewardSchedule.kt create mode 100644 domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/StakingActionArgs.kt create mode 100644 domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/StakingAmountRequirement.kt diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/models/response/P2PEthPoolVaultsResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/models/response/P2PEthPoolVaultsResponse.kt index 1e3bde7a5a..8a8eaf6167 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/models/response/P2PEthPoolVaultsResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/models/response/P2PEthPoolVaultsResponse.kt @@ -2,6 +2,7 @@ package com.tangem.datasource.api.ethpool.models.response import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import java.math.BigDecimal /** * Response for GET /api/v1/staking/pool/{network}/vaults @@ -33,15 +34,15 @@ data class P2PEthPoolVaultDTO( @Json(name = "displayName") val displayName: String, @Json(name = "apy") - val apy: Double, + val apy: BigDecimal, @Json(name = "baseApy") - val baseApy: Double, + val baseApy: BigDecimal, @Json(name = "capacity") - val capacity: Double, + val capacity: BigDecimal, @Json(name = "totalAssets") - val totalAssets: Double, + val totalAssets: BigDecimal, @Json(name = "feePercent") - val feePercent: Double, + val feePercent: BigDecimal, @Json(name = "isPrivate") val isPrivate: Boolean, @Json(name = "isGenesis") diff --git a/data/staking/src/main/java/com/tangem/data/staking/DefaultP2PEthPoolRepository.kt b/data/staking/src/main/java/com/tangem/data/staking/DefaultP2PEthPoolRepository.kt index 33ea700fb0..54d82d69e9 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/DefaultP2PEthPoolRepository.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/DefaultP2PEthPoolRepository.kt @@ -44,7 +44,7 @@ internal class DefaultP2PEthPoolRepository( Timber.e("Error fetching P2PEthPool vaults: $error") emptyList() } - p2pEthPoolVaultsStore.store(vaults) + p2pEthPoolVaultsStore.store(vaults.filter { !it.isPrivate }) // TODO eth isSmoothingPool? } override suspend fun getVaults(network: P2PEthPoolNetwork): Either> = either { diff --git a/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolStakingBalanceConverter.kt b/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolStakingBalanceConverter.kt index 61962eae94..9940c0d306 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolStakingBalanceConverter.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolStakingBalanceConverter.kt @@ -8,11 +8,12 @@ import com.tangem.domain.models.StatusSource import com.tangem.domain.models.staking.* import com.tangem.domain.staking.model.StakingIntegrationID import kotlinx.datetime.Instant +import java.math.BigDecimal -/** Converts P2PEthPool API response to [StakingBalance.Data.P2PEthPool] */ +/** Converts P2PEthPool API response to [StakingBalance] */ internal object P2PEthPoolStakingBalanceConverter { - fun convert(response: P2PEthPoolAccountResponse, source: StatusSource): StakingBalance.Data.P2PEthPool { + fun convert(response: P2PEthPoolAccountResponse, source: StatusSource): StakingBalance { val stakingId = StakingID( integrationId = StakingIntegrationID.P2PEthPool.value, address = response.delegatorAddress, @@ -27,11 +28,22 @@ internal object P2PEthPoolStakingBalanceConverter { exitQueue = convertExitQueue(response.exitQueue), ) - return StakingBalance.Data.P2PEthPool( - stakingId = stakingId, - source = source, - account = account, - ) + val hasActivePosition = account.stake.assets > BigDecimal.ZERO || + account.exitQueue.total > BigDecimal.ZERO || + account.availableToWithdraw > BigDecimal.ZERO + + return if (hasActivePosition) { + StakingBalance.Data.P2PEthPool( + stakingId = stakingId, + source = source, + account = account, + ) + } else { + StakingBalance.Empty( + stakingId = stakingId, + source = source, + ) + } } private fun convertStake(dto: P2PEthPoolStakeDTO): P2PEthPoolStake { diff --git a/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolVaultConverter.kt b/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolVaultConverter.kt index 75f9a6a470..1925cd298e 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolVaultConverter.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolVaultConverter.kt @@ -3,21 +3,26 @@ package com.tangem.data.staking.converters.ethpool import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolVaultDTO import com.tangem.domain.staking.model.ethpool.P2PEthPoolVault import com.tangem.utils.converter.Converter +import java.math.BigDecimal +import java.math.RoundingMode /** * Converter from P2PEthPool Vault DTO to Domain model */ internal object P2PEthPoolVaultConverter : Converter { + private val HUNDRED = BigDecimal(100) + private const val DIVIDE_SCALE = 8 + override fun convert(value: P2PEthPoolVaultDTO): P2PEthPoolVault { return P2PEthPoolVault( vaultAddress = value.vaultAddress, displayName = value.displayName, - apy = value.apy.toBigDecimal(), - baseApy = value.baseApy.toBigDecimal(), - capacity = value.capacity.toBigDecimal(), - totalAssets = value.totalAssets.toBigDecimal(), - feePercent = value.feePercent.toBigDecimal(), + apy = value.apy.divide(HUNDRED, DIVIDE_SCALE, RoundingMode.HALF_UP), + baseApy = value.baseApy.divide(HUNDRED, DIVIDE_SCALE, RoundingMode.HALF_UP), + capacity = value.capacity, + totalAssets = value.totalAssets, + feePercent = value.feePercent, isPrivate = value.isPrivate, isGenesis = value.isGenesis, isSmoothingPool = value.isSmoothingPool, diff --git a/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiStakingBalanceFetcher.kt b/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiStakingBalanceFetcher.kt index 60c12b3b12..2ff4700bb3 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiStakingBalanceFetcher.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiStakingBalanceFetcher.kt @@ -136,8 +136,8 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor( val vaults = runSuspendCatching { p2pEthPoolVaultsStore.getSync() }.getOrNull().orEmpty() if (vaults.isEmpty()) { - Timber.w("No P2PEthPool vaults available for $userWalletId") - p2PEthPoolBalancesStore.storeError(userWalletId = userWalletId, stakingIds = stakingIds) + Timber.w("No P2PEthPool vaults available for $userWalletId, storing empty balances") + p2PEthPoolBalancesStore.storeEmpty(userWalletId = userWalletId, stakingIds = stakingIds) return } diff --git a/data/staking/src/main/java/com/tangem/data/staking/store/DefaultP2PEthPoolBalancesStore.kt b/data/staking/src/main/java/com/tangem/data/staking/store/DefaultP2PEthPoolBalancesStore.kt index 2be492ef3a..35f65f95da 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/store/DefaultP2PEthPoolBalancesStore.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/store/DefaultP2PEthPoolBalancesStore.kt @@ -90,6 +90,15 @@ internal class DefaultP2PEthPoolBalancesStore( } } + override suspend fun storeEmpty(userWalletId: UserWalletId, stakingIds: Set) { + updateInRuntime( + userWalletId = userWalletId, + stakingIds = stakingIds, + ifNotFound = ::createEmptyStakingBalance, + update = { it.copySealed(source = StatusSource.ACTUAL) }, + ) + } + override suspend fun storeError(userWalletId: UserWalletId, stakingIds: Set) { updateInRuntime( userWalletId = userWalletId, @@ -187,5 +196,8 @@ internal class DefaultP2PEthPoolBalancesStore( } } + private fun createEmptyStakingBalance(id: StakingID): StakingBalance = + StakingBalance.Empty(stakingId = id, source = StatusSource.ACTUAL) + private fun createErrorStakingBalance(id: StakingID): StakingBalance = StakingBalance.Error(stakingId = id) } \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/store/P2PEthPoolBalancesStore.kt b/data/staking/src/main/java/com/tangem/data/staking/store/P2PEthPoolBalancesStore.kt index 72891d6a1b..06d300af6e 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/store/P2PEthPoolBalancesStore.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/store/P2PEthPoolBalancesStore.kt @@ -23,6 +23,8 @@ interface P2PEthPoolBalancesStore { suspend fun storeActual(userWalletId: UserWalletId, values: Set) + suspend fun storeEmpty(userWalletId: UserWalletId, stakingIds: Set) + suspend fun storeError(userWalletId: UserWalletId, stakingIds: Set) suspend fun clear(userWalletId: UserWalletId, stakingIds: Set) diff --git a/data/staking/src/test/kotlin/com/tangem/data/staking/StakingBalanceExt.kt b/data/staking/src/test/kotlin/com/tangem/data/staking/StakingBalanceExt.kt index ee45a232fe..aec8fadd1f 100644 --- a/data/staking/src/test/kotlin/com/tangem/data/staking/StakingBalanceExt.kt +++ b/data/staking/src/test/kotlin/com/tangem/data/staking/StakingBalanceExt.kt @@ -13,7 +13,7 @@ internal fun YieldBalanceWrapperDTO.toDomain(source: StatusSource = StatusSource internal fun P2PEthPoolAccountResponse.toDomain( source: StatusSource = StatusSource.CACHE, -): StakingBalance.Data.P2PEthPool { +): StakingBalance { return P2PEthPoolStakingBalanceConverter.convert( response = this, source = source, diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/RewardClaiming.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/RewardClaiming.kt new file mode 100644 index 0000000000..47ea02a99a --- /dev/null +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/RewardClaiming.kt @@ -0,0 +1,10 @@ +package com.tangem.domain.staking.model.common + +import kotlinx.serialization.Serializable + +@Serializable +enum class RewardClaiming { + AUTO, + MANUAL, + UNKNOWN, +} \ No newline at end of file diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/RewardSchedule.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/RewardSchedule.kt new file mode 100644 index 0000000000..8dffddf1e6 --- /dev/null +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/RewardSchedule.kt @@ -0,0 +1,15 @@ +package com.tangem.domain.staking.model.common + +import kotlinx.serialization.Serializable + +@Serializable +enum class RewardSchedule { + BLOCK, + HOUR, + DAY, + WEEK, + MONTH, + ERA, + EPOCH, + UNKNOWN, +} \ No newline at end of file diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/StakingActionArgs.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/StakingActionArgs.kt new file mode 100644 index 0000000000..bdf0f5a05b --- /dev/null +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/StakingActionArgs.kt @@ -0,0 +1,17 @@ +package com.tangem.domain.staking.model.common + +import kotlinx.serialization.Serializable + +/** + * Provider-agnostic representation of staking action arguments. + * Contains amount requirements and constraints for enter/exit operations. + * + * Maps from: + * - StakeKit: Yield.Args.Enter + * - P2PEthPool: P2PEthPoolStaking.Metadata + */ +@Serializable +data class StakingActionArgs( + val amountRequirement: StakingAmountRequirement?, + val isPartialAmountDisabled: Boolean, +) \ No newline at end of file diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/StakingAmountRequirement.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/StakingAmountRequirement.kt new file mode 100644 index 0000000000..87b4eb083d --- /dev/null +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/common/StakingAmountRequirement.kt @@ -0,0 +1,19 @@ +package com.tangem.domain.staking.model.common + +import com.tangem.domain.models.serialization.SerializedBigDecimal +import kotlinx.serialization.Serializable + +/** + * Provider-agnostic representation of staking amount requirements. + * Contains validation constraints for stake/unstake amounts. + * + * Maps from: + * - StakeKit: AddressArgument with ArgType.AMOUNT + * - P2PEthPool: P2PEthPoolStaking.Metadata minimumStake/maximumStake + */ +@Serializable +data class StakingAmountRequirement( + val isRequired: Boolean, + val minimum: SerializedBigDecimal? = null, + val maximum: SerializedBigDecimal? = null, +) \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/model/P2PEthPoolIntegration.kt b/domain/staking/src/main/java/com/tangem/domain/staking/model/P2PEthPoolIntegration.kt index 97fc1c11cf..052cb4509b 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/model/P2PEthPoolIntegration.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/model/P2PEthPoolIntegration.kt @@ -2,8 +2,11 @@ package com.tangem.domain.staking.model import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.staking.YieldToken +import com.tangem.domain.staking.model.common.RewardClaiming +import com.tangem.domain.staking.model.common.RewardSchedule +import com.tangem.domain.staking.model.common.StakingActionArgs +import com.tangem.domain.staking.model.common.StakingAmountRequirement import com.tangem.domain.staking.model.ethpool.P2PEthPoolVault -import com.tangem.domain.staking.model.stakekit.Yield import java.math.BigDecimal /** @@ -39,9 +42,23 @@ class P2PEthPoolIntegration( override val exitMinimumAmount: BigDecimal? = null - override val enterArgs: Yield.Args.Enter? = null + override val enterArgs: StakingActionArgs = StakingActionArgs( + amountRequirement = StakingAmountRequirement( + isRequired = true, + minimum = DEFAULT_MINIMUM_STAKE, + maximum = null, + ), + isPartialAmountDisabled = false, + ) - override val exitArgs: Yield.Args.Enter? = null + override val exitArgs: StakingActionArgs = StakingActionArgs( + amountRequirement = StakingAmountRequirement( + isRequired = true, + minimum = null, + maximum = null, + ), + isPartialAmountDisabled = false, + ) // Metadata @@ -49,9 +66,9 @@ class P2PEthPoolIntegration( override val cooldownPeriodDays: Int = DEFAULT_COOLDOWN_DAYS - override val rewardSchedule: Yield.Metadata.RewardSchedule = Yield.Metadata.RewardSchedule.DAY + override val rewardSchedule: RewardSchedule = RewardSchedule.DAY - override val rewardClaiming: Yield.Metadata.RewardClaiming = Yield.Metadata.RewardClaiming.AUTO + override val rewardClaiming: RewardClaiming = RewardClaiming.AUTO override fun getCurrentToken(rawCurrencyId: CryptoCurrency.RawID?): YieldToken = token diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/model/StakeKitIntegration.kt b/domain/staking/src/main/java/com/tangem/domain/staking/model/StakeKitIntegration.kt index d6b3ad49e5..fa2d4542a7 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/model/StakeKitIntegration.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/model/StakeKitIntegration.kt @@ -2,6 +2,10 @@ package com.tangem.domain.staking.model import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.staking.YieldToken +import com.tangem.domain.staking.model.common.RewardClaiming +import com.tangem.domain.staking.model.common.RewardSchedule +import com.tangem.domain.staking.model.common.StakingActionArgs +import com.tangem.domain.staking.model.common.StakingAmountRequirement import com.tangem.domain.staking.model.stakekit.Yield import java.math.BigDecimal @@ -39,9 +43,9 @@ class StakeKitIntegration( yield.args.exit?.args ?.get(Yield.Args.ArgType.AMOUNT)?.minimum - override val enterArgs: Yield.Args.Enter = yield.args.enter + override val enterArgs: StakingActionArgs = yield.args.enter.toStakingActionArgs() - override val exitArgs: Yield.Args.Enter? = yield.args.exit + override val exitArgs: StakingActionArgs? = yield.args.exit?.toStakingActionArgs() // Metadata @@ -49,12 +53,47 @@ class StakeKitIntegration( override val cooldownPeriodDays: Int? = yield.metadata.cooldownPeriod?.days - override val rewardSchedule: Yield.Metadata.RewardSchedule = yield.metadata.rewardSchedule + override val rewardSchedule: RewardSchedule = yield.metadata.rewardSchedule.toRewardSchedule() - override val rewardClaiming: Yield.Metadata.RewardClaiming = yield.metadata.rewardClaiming + override val rewardClaiming: RewardClaiming = yield.metadata.rewardClaiming.toRewardClaiming() // Basic override fun getCurrentToken(rawCurrencyId: CryptoCurrency.RawID?): YieldToken = tokens.firstOrNull { rawCurrencyId?.value == it.coinGeckoId } ?: token + + private fun Yield.Args.Enter.toStakingActionArgs(): StakingActionArgs { + val amountArg = args[Yield.Args.ArgType.AMOUNT] + return StakingActionArgs( + amountRequirement = amountArg?.let { arg -> + StakingAmountRequirement( + isRequired = arg.required, + minimum = arg.minimum, + maximum = arg.maximum, + ) + }, + isPartialAmountDisabled = isPartialAmountDisabled, + ) + } + + private fun Yield.Metadata.RewardSchedule.toRewardSchedule(): RewardSchedule { + return when (this) { + Yield.Metadata.RewardSchedule.BLOCK -> RewardSchedule.BLOCK + Yield.Metadata.RewardSchedule.HOUR -> RewardSchedule.HOUR + Yield.Metadata.RewardSchedule.DAY -> RewardSchedule.DAY + Yield.Metadata.RewardSchedule.WEEK -> RewardSchedule.WEEK + Yield.Metadata.RewardSchedule.MONTH -> RewardSchedule.MONTH + Yield.Metadata.RewardSchedule.ERA -> RewardSchedule.ERA + Yield.Metadata.RewardSchedule.EPOCH -> RewardSchedule.EPOCH + Yield.Metadata.RewardSchedule.UNKNOWN -> RewardSchedule.UNKNOWN + } + } + + private fun Yield.Metadata.RewardClaiming.toRewardClaiming(): RewardClaiming { + return when (this) { + Yield.Metadata.RewardClaiming.AUTO -> RewardClaiming.AUTO + Yield.Metadata.RewardClaiming.MANUAL -> RewardClaiming.MANUAL + Yield.Metadata.RewardClaiming.UNKNOWN -> RewardClaiming.UNKNOWN + } + } } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegration.kt b/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegration.kt index a20e1d6ebb..37f76ede7f 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegration.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegration.kt @@ -2,14 +2,15 @@ package com.tangem.domain.staking.model import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.staking.YieldToken -import com.tangem.domain.staking.model.stakekit.Yield +import com.tangem.domain.staking.model.common.RewardClaiming +import com.tangem.domain.staking.model.common.RewardSchedule +import com.tangem.domain.staking.model.common.StakingActionArgs import java.math.BigDecimal /** * Strategy interface for staking integrations. * Abstracts over StakeKit and P2PEthPool staking providers. */ -// TODO p2p get rid of stakekit-specific models in StakingIntegration and implementors interface StakingIntegration { // Basic @@ -36,9 +37,9 @@ interface StakingIntegration { val exitMinimumAmount: BigDecimal? - val enterArgs: Yield.Args.Enter? + val enterArgs: StakingActionArgs? - val exitArgs: Yield.Args.Enter? + val exitArgs: StakingActionArgs? // Metadata @@ -46,9 +47,9 @@ interface StakingIntegration { val cooldownPeriodDays: Int? - val rewardSchedule: Yield.Metadata.RewardSchedule + val rewardSchedule: RewardSchedule - val rewardClaiming: Yield.Metadata.RewardClaiming + val rewardClaiming: RewardClaiming // Basic 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 86fdcfd533..f1404c4a63 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 @@ -19,10 +19,10 @@ import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.staking.BalanceItem import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.staking.model.common.RewardType import com.tangem.domain.staking.model.StakingIntegration import com.tangem.domain.staking.model.StakingTarget -import com.tangem.domain.staking.model.stakekit.Yield +import com.tangem.domain.staking.model.common.RewardClaiming +import com.tangem.domain.staking.model.common.RewardType import com.tangem.features.staking.impl.R import com.tangem.features.staking.impl.presentation.model.StakingClickIntents import com.tangem.features.staking.impl.presentation.state.InnerYieldBalanceState @@ -293,9 +293,9 @@ internal class SetInitialDataStateTransformer( val EQUALITY_THRESHOLD = BigDecimal(1E-10) val rewardClaimingResources = mapOf( - Yield.Metadata.RewardClaiming.MANUAL to R.string.staking_reward_claiming_manual, - Yield.Metadata.RewardClaiming.AUTO to R.string.staking_reward_claiming_auto, - Yield.Metadata.RewardSchedule.UNKNOWN to null, + RewardClaiming.MANUAL to R.string.staking_reward_claiming_manual, + RewardClaiming.AUTO to R.string.staking_reward_claiming_auto, + RewardClaiming.UNKNOWN to null, ) } } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt index 8af103c0f1..5421794d27 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt @@ -13,8 +13,7 @@ import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.utils.parseBigDecimal import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.staking.model.StakingIntegration -import com.tangem.domain.staking.model.stakekit.AddressArgument -import com.tangem.domain.staking.model.stakekit.Yield +import com.tangem.domain.staking.model.common.StakingAmountRequirement import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType import com.tangem.features.staking.impl.R import com.tangem.lib.crypto.BlockchainUtils.isTron @@ -97,11 +96,11 @@ internal class AmountRequirementStateTransformer( return when (actionType) { is StakingActionCommonType.Enter -> { - val enterRequirements = integration.enterArgs?.args?.get(Yield.Args.ArgType.AMOUNT) + val enterRequirements = integration.enterArgs?.amountRequirement enterRequirements?.getError(amountDecimal, R.string.staking_amount_requirement_error) } is StakingActionCommonType.Exit -> { - val exitRequirements = integration.exitArgs?.args?.get(Yield.Args.ArgType.AMOUNT) + val exitRequirements = integration.exitArgs?.amountRequirement exitRequirements?.getError(amountDecimal, R.string.staking_unstake_amount_requirement_error) } else -> null @@ -119,7 +118,7 @@ internal class AmountRequirementStateTransformer( return isEnterOrExit && isTron && !isIntegerOnly } - private fun AddressArgument.getError(amount: BigDecimal, @StringRes errorTextRes: Int): TextReference? { + private fun StakingAmountRequirement.getError(amount: BigDecimal, @StringRes errorTextRes: Int): TextReference? { val isExceedsMinRequirement = minimum?.compareTo(amount) == 1 val isExceedsMaxRequirement = if (maximum?.isPositive() == true) { maximum?.compareTo(amount) == -1 @@ -143,7 +142,7 @@ internal class AmountRequirementStateTransformer( return resourceReference( errorTextRes, wrappedList(errorText), - ).takeIf { required && (isExceedsMinRequirement || isExceedsMaxRequirement) } + ).takeIf { isRequired && (isExceedsMinRequirement || isExceedsMaxRequirement) } } data class Data( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt index 7b6e21df7d..905ca35ddb 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt @@ -9,7 +9,6 @@ import com.tangem.domain.models.staking.BalanceType import com.tangem.domain.models.staking.StakingBalance import com.tangem.domain.models.staking.action.StakingActionType import com.tangem.domain.staking.model.StakingIntegration -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.InnerYieldBalanceState @@ -214,12 +213,12 @@ internal class StakingInfoNotificationsFactory( if (prevState.actionType !is StakingActionCommonType.Exit) return val maxAmount = prevState.balanceState?.cryptoAmount ?: return - val exitRequirements = integration.exitArgs?.args?.get(Yield.Args.ArgType.AMOUNT) ?: return + val exitRequirements = integration.exitArgs?.amountRequirement ?: return val amountLeft = maxAmount - actionAmount val isNotEnoughLeft = !amountLeft.isZero() && amountLeft < exitRequirements.minimum.orZero() - if (exitRequirements.required && isNotEnoughLeft) { + if (exitRequirements.isRequired && isNotEnoughLeft) { add(StakingNotification.Warning.LowStakedBalance) } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/StakingRewardsUtils.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/StakingRewardsUtils.kt index ba5cc07eee..7abfa03318 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/StakingRewardsUtils.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/StakingRewardsUtils.kt @@ -1,12 +1,12 @@ package com.tangem.features.staking.impl.presentation.state.utils import com.tangem.core.ui.extensions.* +import com.tangem.domain.staking.model.common.RewardSchedule import com.tangem.domain.staking.model.common.RewardType -import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.features.staking.impl.R -import com.tangem.features.staking.impl.presentation.state.utils.StakingRewardSchedule.COSMOS_SCHEDULE -import com.tangem.features.staking.impl.presentation.state.utils.StakingRewardSchedule.SOLANA_SCHEDULE -import com.tangem.features.staking.impl.presentation.state.utils.StakingRewardSchedule.TON_SCHEDULE +import com.tangem.features.staking.impl.presentation.state.utils.StakingRewardScheduleConstants.COSMOS_SCHEDULE +import com.tangem.features.staking.impl.presentation.state.utils.StakingRewardScheduleConstants.SOLANA_SCHEDULE +import com.tangem.features.staking.impl.presentation.state.utils.StakingRewardScheduleConstants.TON_SCHEDULE import com.tangem.lib.crypto.BlockchainUtils.isCosmos import com.tangem.lib.crypto.BlockchainUtils.isSolana import com.tangem.lib.crypto.BlockchainUtils.isTon @@ -14,42 +14,42 @@ import com.tangem.lib.crypto.BlockchainUtils.isTron import com.tangem.utils.StringsSigns.MINUS import com.tangem.utils.StringsSigns.NON_BREAKING_SPACE -private data object StakingRewardSchedule { +private data object StakingRewardScheduleConstants { val COSMOS_SCHEDULE = 5 to 12 val SOLANA_SCHEDULE = 2 to 3 val TON_SCHEDULE = 1 to 2 } internal fun getRewardScheduleText( - rewardSchedule: Yield.Metadata.RewardSchedule, + rewardSchedule: RewardSchedule, networkId: String, decapitalize: Boolean, ): TextReference? { return when (rewardSchedule) { - Yield.Metadata.RewardSchedule.WEEK -> resourceReference( + RewardSchedule.WEEK -> resourceReference( id = R.string.staking_reward_schedule_week, decapitalize = decapitalize, ) - Yield.Metadata.RewardSchedule.HOUR -> resourceReference( + RewardSchedule.HOUR -> resourceReference( id = R.string.staking_reward_schedule_hour, decapitalize = decapitalize, ) - Yield.Metadata.RewardSchedule.DAY -> resourceReference( + RewardSchedule.DAY -> resourceReference( id = R.string.staking_reward_schedule_day, decapitalize = decapitalize, ) - Yield.Metadata.RewardSchedule.MONTH -> resourceReference( + RewardSchedule.MONTH -> resourceReference( id = R.string.staking_reward_schedule_month, decapitalize = decapitalize, ) - Yield.Metadata.RewardSchedule.BLOCK, - Yield.Metadata.RewardSchedule.EPOCH, - Yield.Metadata.RewardSchedule.ERA, + RewardSchedule.BLOCK, + RewardSchedule.EPOCH, + RewardSchedule.ERA, -> getCustomRewardSchedule( networkId = networkId, decapitalize = decapitalize, ) - else -> null + RewardSchedule.UNKNOWN -> null } }