Updated on 2026-08-14
This commit is contained in:
parent
fe6c26624a
commit
5060b5c028
19 changed files with 212 additions and 64 deletions
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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<StakingError, List<P2PEthPoolVault>> = either {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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<P2PEthPoolVaultDTO, P2PEthPoolVault> {
|
||||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,15 @@ internal class DefaultP2PEthPoolBalancesStore(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun storeEmpty(userWalletId: UserWalletId, stakingIds: Set<StakingID>) {
|
||||
updateInRuntime(
|
||||
userWalletId = userWalletId,
|
||||
stakingIds = stakingIds,
|
||||
ifNotFound = ::createEmptyStakingBalance,
|
||||
update = { it.copySealed(source = StatusSource.ACTUAL) },
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun storeError(userWalletId: UserWalletId, stakingIds: Set<StakingID>) {
|
||||
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)
|
||||
}
|
||||
|
|
@ -23,6 +23,8 @@ interface P2PEthPoolBalancesStore {
|
|||
|
||||
suspend fun storeActual(userWalletId: UserWalletId, values: Set<P2PEthPoolAccountResponse>)
|
||||
|
||||
suspend fun storeEmpty(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
|
||||
suspend fun storeError(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
|
||||
suspend fun clear(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.domain.staking.model.common
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
enum class RewardClaiming {
|
||||
AUTO,
|
||||
MANUAL,
|
||||
UNKNOWN,
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue