Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-19 10:20:09 +03:00
commit f0e4aec9a4
858 changed files with 13724 additions and 5705 deletions

View file

@ -2,13 +2,12 @@
<SmellBaseline>
<ManuallySuppressedIssues/>
<CurrentIssues>
<ID>CanBeNonNullable:StakingAnalyticsEvent.kt$StakingAnalyticsEvent$value: Any?</ID>
<ID>MultilineLambdaItParameter:FetchStakingYieldBalanceUseCase.kt$FetchStakingYieldBalanceUseCase${ when (it) { is StakingIdFactory.Error.UnableToGetAddress -&gt; raise(StakingError.DomainError("$it")) StakingIdFactory.Error.UnsupportedCurrency -&gt; Unit.right() } return@either }</ID>
<ID>MultilineLambdaItParameter:InvalidatePendingTransactionsUseCase.kt$InvalidatePendingTransactionsUseCase${ !it.isPending &amp;&amp; action.amount &lt; it.amount &amp;&amp; it.type == BalanceType.STAKED &amp;&amp; it.validatorAddress == action.validatorAddress }</ID>
<ID>NamedArguments:GetConstructedStakingTransactionUseCase.kt$GetConstructedStakingTransactionUseCase$constructTransaction(networkId, fee, amount, transactionId)</ID>
<ID>NullableToStringCall:StakingApyFlowUseCase.kt$StakingApyFlowUseCase$${yield.token.coinGeckoId}</ID>
<ID>UnnecessaryAbstractClass:MultiYieldBalanceSupplier.kt$MultiYieldBalanceSupplier$MultiYieldBalanceSupplier</ID>
<ID>UnnecessaryAbstractClass:SingleYieldBalanceSupplier.kt$SingleYieldBalanceSupplier$SingleYieldBalanceSupplier</ID>
<ID>UnnecessaryAbstractClass:MultiStakingBalanceSupplier.kt$MultiStakingBalanceSupplier$MultiStakingBalanceSupplier</ID>
<ID>UnnecessaryAbstractClass:SingleStakingBalanceSupplier.kt$SingleStakingBalanceSupplier$SingleStakingBalanceSupplier</ID>
<ID>UseEmptyCounterpart:StakingAnalyticsEvent.kt$StakingAnalyticsEvent$mapOf()</ID>
<ID>UseOrEmpty:InvalidatePendingTransactionsUseCase.kt$InvalidatePendingTransactionsUseCase$action.validatorAddress ?: action.validatorAddresses?.getOrNull(0) ?: ""</ID>
</CurrentIssues>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" ?>
<SmellBaseline>
<ManuallySuppressedIssues/>
<CurrentIssues>
<ID>BooleanPropertyNaming:P2PEthPoolStaking.kt$P2PEthPoolStaking.Metadata.Fee$val enabled: Boolean</ID>
<ID>BooleanPropertyNaming:P2PEthPoolStaking.kt$P2PEthPoolStaking.Status$val enter: Boolean</ID>
<ID>BooleanPropertyNaming:P2PEthPoolStaking.kt$P2PEthPoolStaking.Status$val exit: Boolean</ID>
<ID>BooleanPropertyNaming:StakingActionCommonType.kt$StakingActionCommonType.Enter$val skipEnterAmount: Boolean</ID>
<ID>BooleanPropertyNaming:StakingActionCommonType.kt$StakingActionCommonType.Exit$val partiallyUnstakeDisabled: Boolean</ID>
<ID>BooleanPropertyNaming:StakingActionCommonType.kt$StakingActionCommonType.Pending.Stake$val skipEnterAmount: Boolean</ID>
<ID>BooleanPropertyNaming:Yield.kt$AddressArgument$val required: Boolean</ID>
<ID>BooleanPropertyNaming:Yield.kt$Yield$val allValidatorsFull: Boolean = validators.all { it.status == Validator.ValidatorStatus.FULL }</ID>
<ID>BooleanPropertyNaming:Yield.kt$Yield.Metadata$val supportsMultipleValidators: Boolean?</ID>
<ID>BooleanPropertyNaming:Yield.kt$Yield.Metadata.Enabled$val enabled: Boolean</ID>
<ID>BooleanPropertyNaming:Yield.kt$Yield.Status$val enter: Boolean</ID>
<ID>BooleanPropertyNaming:Yield.kt$Yield.Status$val exit: Boolean?</ID>
<ID>BooleanPropertyNaming:Yield.kt$Yield.Validator$val preferred: Boolean</ID>
</CurrentIssues>
</SmellBaseline>

View file

@ -39,12 +39,11 @@ sealed interface StakingOption {
* P2P pooled staking option
* Wraps P2P ETH Pool vault information
*/
data class P2P(val vault: P2PEthPoolVault) : StakingOption {
override val integrationId: String =
"p2p-ethereum-pooled:${vault.vaultAddress}"
override val apy: SerializedBigDecimal = vault.apy
data class P2P(val vaults: List<P2PEthPoolVault>) : StakingOption {
override val integrationId: String = "p2p-ethereum-pooled"
override val apy: SerializedBigDecimal = vaults.maxOf { it.apy }
override val token: YieldToken = createEthToken()
override val isAvailable: Boolean = !vault.isPrivate
override val isAvailable: Boolean = vaults.isNotEmpty()
private fun createEthToken(): YieldToken { // TODO
return YieldToken(

View file

@ -11,6 +11,8 @@ enum class P2PEthPoolNetwork(
val value: String,
val displayName: String,
val chainId: Int,
val stakingNetworkId: String,
val isTestnet: Boolean,
) {
/**
* Ethereum mainnet
@ -20,16 +22,20 @@ enum class P2PEthPoolNetwork(
value = "mainnet",
displayName = "Ethereum",
chainId = 1,
stakingNetworkId = "ethereum",
isTestnet = false,
),
/**
* Ethereum testnet (Holesky)
* Ethereum testnet (Hoodi)
* Chain ID: 17000
*/
TESTNET(
value = "hoodi",
displayName = "Holesky Testnet",
displayName = "Hoodi Testnet",
chainId = 17000,
stakingNetworkId = "ethereum/test",
isTestnet = true,
),
;

View file

@ -0,0 +1,14 @@
package com.tangem.domain.staking.model.ethpool
/**
* Configuration for P2P Ethereum staking network.
*
* Change [USE_TESTNET] to switch between testnet and mainnet.
*/
object P2PStakingConfig {
const val USE_TESTNET: Boolean = true
val activeNetwork: P2PEthPoolNetwork
get() = if (USE_TESTNET) P2PEthPoolNetwork.TESTNET else P2PEthPoolNetwork.MAINNET
}

View file

@ -7,10 +7,10 @@ import arrow.core.right
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
import com.tangem.domain.staking.single.SingleStakingBalanceFetcher
class FetchStakingYieldBalanceUseCase(
private val singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
private val singleStakingBalanceFetcher: SingleStakingBalanceFetcher,
private val stakingIdFactory: StakingIdFactory,
) {
@ -32,8 +32,8 @@ class FetchStakingYieldBalanceUseCase(
return@either
}
singleYieldBalanceFetcher(
params = SingleYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingId = stakingId),
singleStakingBalanceFetcher(
params = SingleStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingId = stakingId),
)
.mapLeft { StakingError.DomainError("$it") }
.bind()

View file

@ -2,7 +2,6 @@ package com.tangem.domain.staking.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.domain.staking.analytics.StakingAnalyticsEvent.ButtonRewards.addIfValueIsNotNull
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.models.staking.action.StakingActionType
@ -24,11 +23,11 @@ sealed class StakingAnalyticsEvent(
),
)
data object WhatIsStaking : StakingAnalyticsEvent(
class WhatIsStaking : StakingAnalyticsEvent(
event = "Link - What Is Staking",
)
data object AmountScreenOpened : StakingAnalyticsEvent(
class AmountScreenOpened : StakingAnalyticsEvent(
event = "Amount Screen Opened",
)
@ -54,7 +53,7 @@ sealed class StakingAnalyticsEvent(
),
)
data object RewardScreenOpened : StakingAnalyticsEvent(
class RewardScreenOpened : StakingAnalyticsEvent(
event = "Reward Screen Opened",
)
@ -67,7 +66,7 @@ sealed class StakingAnalyticsEvent(
),
)
data object ButtonMax : StakingAnalyticsEvent(
class ButtonMax : StakingAnalyticsEvent(
event = "Button - Max",
)
@ -98,7 +97,7 @@ sealed class StakingAnalyticsEvent(
),
)
data object ButtonRewards : StakingAnalyticsEvent(
class ButtonRewards : StakingAnalyticsEvent(
event = "Button - Rewards",
)
@ -112,9 +111,9 @@ sealed class StakingAnalyticsEvent(
),
)
data object ButtonShare : StakingAnalyticsEvent(event = "Button - Share")
class ButtonShare : StakingAnalyticsEvent(event = "Button - Share")
data object ButtonExplore : StakingAnalyticsEvent(event = "Button - Explore")
class ButtonExplore : StakingAnalyticsEvent(event = "Button - Explore")
data class StakeKitApiError(
val stakingError: StakingError.StakeKitApiError,
@ -145,12 +144,6 @@ sealed class StakingAnalyticsEvent(
},
)
fun MutableMap<String, String>.addIfValueIsNotNull(key: String, value: Any?) {
if (value != null) {
put(key, value.toString())
}
}
data class TransactionError(
val errorCode: String,
) : StakingAnalyticsEvent(
@ -178,4 +171,11 @@ sealed class StakingAnalyticsEvent(
enum class StakeScreenSource {
Info, Amount, Confirmation, Validators,
}
@Suppress("CanBeNonNullable")
fun MutableMap<String, String>.addIfValueIsNotNull(key: String, value: Any?) {
if (value != null) {
put(key, value.toString())
}
}

View file

@ -5,17 +5,17 @@ import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWalletId
/**
* Params for fetchers of yield balance
* Params for fetchers of staking balance
*
[REDACTED_AUTHOR]
*/
sealed interface YieldBalanceFetcherParams {
sealed interface StakingBalanceFetcherParams {
/** User wallet ID */
val userWalletId: UserWalletId
/**
* Params for fetching multiple yield balances
* Params for fetching multiple staking balances
*
* @property userWalletId user wallet ID
* @property currencyIdWithNetworkMap map of currency ID to network
@ -23,10 +23,10 @@ sealed interface YieldBalanceFetcherParams {
data class Multi(
override val userWalletId: UserWalletId,
val currencyIdWithNetworkMap: Map<CryptoCurrency.ID, Network>,
) : YieldBalanceFetcherParams
) : StakingBalanceFetcherParams
/**
* Params for fetching single yield balance
* Params for fetching single staking balance
*
* @property userWalletId user wallet ID
* @property currencyId currency ID
@ -36,5 +36,5 @@ sealed interface YieldBalanceFetcherParams {
override val userWalletId: UserWalletId,
val currencyId: CryptoCurrency.ID,
val network: Network,
) : YieldBalanceFetcherParams
) : StakingBalanceFetcherParams
}

View file

@ -5,6 +5,7 @@ import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.blockchainsdk.utils.toMigratedCoinId
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.staking.model.ethpool.P2PStakingConfig
/**
* Represents a staking integration identifier.
@ -101,8 +102,10 @@ sealed interface StakingIntegrationID {
enum class P2P : StakingIntegrationID {
EthereumPooled {
override val value: String = "p2p-ethereum-pooled"
override val blockchain: Blockchain = Blockchain.Ethereum
override val networkId: String = "ethereum"
override val blockchain: Blockchain
get() = if (P2PStakingConfig.USE_TESTNET) Blockchain.EthereumTestnet else Blockchain.Ethereum
override val networkId: String
get() = P2PStakingConfig.activeNetwork.stakingNetworkId
},
}

View file

@ -5,14 +5,14 @@ import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.staking.StakingID
/**
* Fetcher of yields balances
* Fetcher of staking balances
*
[REDACTED_AUTHOR]
*/
interface MultiYieldBalanceFetcher : FlowFetcher<MultiYieldBalanceFetcher.Params> {
interface MultiStakingBalanceFetcher : FlowFetcher<MultiStakingBalanceFetcher.Params> {
/**
* Params for fetching multiple yield balances
* Params for fetching multiple staking balances
*
* @property userWalletId user wallet ID
* @property stakingIds map of currency ID to network
@ -24,7 +24,7 @@ interface MultiYieldBalanceFetcher : FlowFetcher<MultiYieldBalanceFetcher.Params
override fun toString(): String {
return """
MultiYieldBalanceFetcher.Params(
MultiStakingBalanceFetcher.Params(
userWalletId = $userWalletId,
stakingIds: ${stakingIds.joinToString()}
)

View file

@ -0,0 +1,17 @@
package com.tangem.domain.staking.multi
import com.tangem.domain.core.flow.FlowProducer
import com.tangem.domain.models.staking.StakingBalance
import com.tangem.domain.models.wallet.UserWalletId
/**
* Producer of all staking balances for selected wallet [UserWalletId]
*
[REDACTED_AUTHOR]
*/
interface MultiStakingBalanceProducer : FlowProducer<Set<StakingBalance>> {
data class Params(val userWalletId: UserWalletId)
interface Factory : FlowProducer.Factory<Params, MultiStakingBalanceProducer>
}

View file

@ -0,0 +1,18 @@
package com.tangem.domain.staking.multi
import com.tangem.domain.core.flow.FlowCachingSupplier
import com.tangem.domain.core.flow.FlowProducer
import com.tangem.domain.models.staking.StakingBalance
/**
* Supplier of all staking balances for selected wallet [MultiStakingBalanceProducer.Params]
*
* @property factory factory for creating [MultiStakingBalanceProducer]
* @property keyCreator key creator
*
[REDACTED_AUTHOR]
*/
abstract class MultiStakingBalanceSupplier(
override val factory: FlowProducer.Factory<MultiStakingBalanceProducer.Params, MultiStakingBalanceProducer>,
override val keyCreator: (MultiStakingBalanceProducer.Params) -> String,
) : FlowCachingSupplier<MultiStakingBalanceProducer, MultiStakingBalanceProducer.Params, Set<StakingBalance>>()

View file

@ -1,17 +0,0 @@
package com.tangem.domain.staking.multi
import com.tangem.domain.core.flow.FlowProducer
import com.tangem.domain.models.staking.YieldBalance
import com.tangem.domain.models.wallet.UserWalletId
/**
* Producer of all yield balances for selected wallet [UserWalletId]
*
[REDACTED_AUTHOR]
*/
interface MultiYieldBalanceProducer : FlowProducer<Set<YieldBalance>> {
data class Params(val userWalletId: UserWalletId)
interface Factory : FlowProducer.Factory<Params, MultiYieldBalanceProducer>
}

View file

@ -1,18 +0,0 @@
package com.tangem.domain.staking.multi
import com.tangem.domain.core.flow.FlowCachingSupplier
import com.tangem.domain.core.flow.FlowProducer
import com.tangem.domain.models.staking.YieldBalance
/**
* Supplier of all yield balances for selected wallet [MultiYieldBalanceProducer.Params]
*
* @property factory factory for creating [MultiYieldBalanceProducer]
* @property keyCreator key creator
*
[REDACTED_AUTHOR]
*/
abstract class MultiYieldBalanceSupplier(
override val factory: FlowProducer.Factory<MultiYieldBalanceProducer.Params, MultiYieldBalanceProducer>,
override val keyCreator: (MultiYieldBalanceProducer.Params) -> String,
) : FlowCachingSupplier<MultiYieldBalanceProducer, MultiYieldBalanceProducer.Params, Set<YieldBalance>>()

View file

@ -2,7 +2,13 @@ package com.tangem.domain.staking.repositories
import arrow.core.Either
import com.tangem.domain.staking.model.StakingAvailability
import com.tangem.domain.staking.model.ethpool.*
import com.tangem.domain.staking.model.ethpool.P2PEthPoolAccount
import com.tangem.domain.staking.model.ethpool.P2PEthPoolBroadcastResult
import com.tangem.domain.staking.model.ethpool.P2PEthPoolNetwork
import com.tangem.domain.staking.model.ethpool.P2PEthPoolReward
import com.tangem.domain.staking.model.ethpool.P2PEthPoolUnsignedTx
import com.tangem.domain.staking.model.ethpool.P2PEthPoolVault
import com.tangem.domain.staking.model.ethpool.P2PStakingConfig
import com.tangem.domain.staking.model.stakekit.StakingError
import kotlinx.coroutines.flow.Flow
@ -13,7 +19,7 @@ interface P2PEthPoolRepository {
*
* @param network P2P network (MAINNET or TESTNET)
*/
suspend fun fetchVaults(network: P2PEthPoolNetwork = P2PEthPoolNetwork.MAINNET)
suspend fun fetchVaults(network: P2PEthPoolNetwork = P2PStakingConfig.activeNetwork)
/**
* Get list of available staking vaults
@ -22,7 +28,7 @@ interface P2PEthPoolRepository {
* @return Either error or list of vaults with APY, capacity, fees
*/
suspend fun getVaults(
network: P2PEthPoolNetwork = P2PEthPoolNetwork.MAINNET,
network: P2PEthPoolNetwork = P2PStakingConfig.activeNetwork,
): Either<StakingError, List<P2PEthPoolVault>>
/**

View file

@ -5,14 +5,14 @@ import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.staking.StakingID
/**
* Fetcher of yield balance
* Fetcher of staking balance
*
[REDACTED_AUTHOR]
*/
interface SingleYieldBalanceFetcher : FlowFetcher<SingleYieldBalanceFetcher.Params> {
interface SingleStakingBalanceFetcher : FlowFetcher<SingleStakingBalanceFetcher.Params> {
/**
* Params for fetching single yield balance
* Params for fetching single staking balance
*
* @property userWalletId user wallet ID
* @property stakingId staking ID

View file

@ -2,15 +2,15 @@ package com.tangem.domain.staking.single
import com.tangem.domain.core.flow.FlowProducer
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.staking.StakingBalance
import com.tangem.domain.models.staking.StakingID
import com.tangem.domain.models.staking.YieldBalance
/**
* Producer of yield balance for selected wallet [UserWalletId]
* Producer of staking balance for selected wallet [UserWalletId]
*
[REDACTED_AUTHOR]
*/
interface SingleYieldBalanceProducer : FlowProducer<YieldBalance> {
interface SingleStakingBalanceProducer : FlowProducer<StakingBalance> {
data class Params(
val userWalletId: UserWalletId,
@ -19,7 +19,7 @@ interface SingleYieldBalanceProducer : FlowProducer<YieldBalance> {
override fun toString(): String {
return """
SingleYieldBalanceProducer.Params(
SingleStakingBalanceProducer.Params(
userWalletId = $userWalletId,
stakingId = $stakingId,
)
@ -27,5 +27,5 @@ interface SingleYieldBalanceProducer : FlowProducer<YieldBalance> {
}
}
interface Factory : FlowProducer.Factory<Params, SingleYieldBalanceProducer>
interface Factory : FlowProducer.Factory<Params, SingleStakingBalanceProducer>
}

View file

@ -0,0 +1,18 @@
package com.tangem.domain.staking.single
import com.tangem.domain.core.flow.FlowCachingSupplier
import com.tangem.domain.core.flow.FlowProducer
import com.tangem.domain.models.staking.StakingBalance
/**
* Supplier of staking balance for selected wallet [SingleStakingBalanceProducer.Params]
*
* @property factory factory for creating [SingleStakingBalanceProducer]
* @property keyCreator key creator
*
[REDACTED_AUTHOR]
*/
abstract class SingleStakingBalanceSupplier(
override val factory: FlowProducer.Factory<SingleStakingBalanceProducer.Params, SingleStakingBalanceProducer>,
override val keyCreator: (SingleStakingBalanceProducer.Params) -> String,
) : FlowCachingSupplier<SingleStakingBalanceProducer, SingleStakingBalanceProducer.Params, StakingBalance>()

View file

@ -1,18 +0,0 @@
package com.tangem.domain.staking.single
import com.tangem.domain.core.flow.FlowCachingSupplier
import com.tangem.domain.core.flow.FlowProducer
import com.tangem.domain.models.staking.YieldBalance
/**
* Supplier of yield balance for selected wallet [SingleYieldBalanceProducer.Params]
*
* @property factory factory for creating [SingleYieldBalanceProducer]
* @property keyCreator key creator
*
[REDACTED_AUTHOR]
*/
abstract class SingleYieldBalanceSupplier(
override val factory: FlowProducer.Factory<SingleYieldBalanceProducer.Params, SingleYieldBalanceProducer>,
override val keyCreator: (SingleYieldBalanceProducer.Params) -> String,
) : FlowCachingSupplier<SingleYieldBalanceProducer, SingleYieldBalanceProducer.Params, YieldBalance>()

View file

@ -0,0 +1,89 @@
package com.tangem.domain.staking.utils
import com.tangem.domain.models.staking.BalanceType
import com.tangem.domain.models.staking.StakingBalance
import com.tangem.lib.crypto.BlockchainUtils
import java.math.BigDecimal
/**
* Provider-agnostic extension to get total balance including rewards.
* Works for both StakeKit and P2P providers.
*
* Returns sum of all staking-related balances including rewards
* (staked + unstaking + withdrawable + rewards).
*
* When [BlockchainUtils.isIncludeStakingTotalBalance] is false, the staked balance
* is already included in the main wallet balance, so we only return rewards.
*/
fun StakingBalance.Data.getTotalWithRewardsStakingBalance(blockchainId: String): BigDecimal {
return when (this) {
is StakingBalance.Data.StakeKit -> getTotalWithRewardsStakingBalanceStakeKit(blockchainId)
is StakingBalance.Data.P2P -> {
val rewards = totalRewards
if (BlockchainUtils.isIncludeStakingTotalBalance(blockchainId)) {
totalStaked + unstakingAmount + withdrawableAmount + rewards
} else {
rewards
}
}
}
}
/**
* Provider-agnostic extension to get total staking balance excluding rewards.
* Works for both StakeKit and P2P providers.
*
* Returns sum of all staking-related balances (staked + unstaking + withdrawable)
* excluding rewards.
*/
fun StakingBalance.Data.getTotalStakingBalance(blockchainId: String): BigDecimal {
return when (this) {
is StakingBalance.Data.StakeKit -> getTotalStakingBalanceStakeKit(blockchainId)
is StakingBalance.Data.P2P -> totalStaked + unstakingAmount + withdrawableAmount
}
}
/**
* StakeKit-specific extension to get total balance including rewards.
*/
private fun StakingBalance.Data.StakeKit.getTotalWithRewardsStakingBalanceStakeKit(blockchainId: String): BigDecimal {
return if (BlockchainUtils.isIncludeStakingTotalBalance(blockchainId = blockchainId)) {
balance.items.sumOf { it.amount }
} else {
getRewardStakingBalance()
}
}
/**
* StakeKit-specific extension to get total staked balance excluding rewards.
*/
private fun StakingBalance.Data.StakeKit.getTotalStakingBalanceStakeKit(blockchainId: String): BigDecimal {
return if (BlockchainUtils.isIncludeStakingTotalBalance(blockchainId = blockchainId)) {
balance.items
.filterNot { it.type == BalanceType.REWARDS }
.sumOf { it.amount }
} else {
balance.items
.filterNot { it.type == BalanceType.REWARDS }
.sumOf { it.amount } - getRewardStakingBalance()
}
}
/**
* StakeKit-specific extension to get reward balance.
*/
fun StakingBalance.Data.StakeKit.getRewardStakingBalance(): BigDecimal {
return balance.items
.filter { it.type == BalanceType.REWARDS }
.sumOf { it.amount }
}
/**
* StakeKit-specific extension to get validators count.
*/
fun StakingBalance.Data.StakeKit.getValidatorsCount(): Int {
return balance.items
.filterNot { it.validatorAddress.isNullOrBlank() }
.distinctBy { it.validatorAddress }
.size
}

View file

@ -1,39 +0,0 @@
package com.tangem.domain.staking.utils
import com.tangem.domain.models.staking.BalanceType
import com.tangem.domain.models.staking.YieldBalance
import com.tangem.lib.crypto.BlockchainUtils
import java.math.BigDecimal
fun YieldBalance.Data.getTotalWithRewardsStakingBalance(blockchainId: String): BigDecimal {
return if (BlockchainUtils.isIncludeStakingTotalBalance(blockchainId = blockchainId)) {
balance.items.sumOf { it.amount }
} else {
getRewardStakingBalance()
}
}
fun YieldBalance.Data.getTotalStakingBalance(blockchainId: String): BigDecimal {
return if (BlockchainUtils.isIncludeStakingTotalBalance(blockchainId = blockchainId)) {
balance.items
.filterNot { it.type == BalanceType.REWARDS }
.sumOf { it.amount }
} else {
balance.items
.filterNot { it.type == BalanceType.REWARDS }
.sumOf { it.amount } - getRewardStakingBalance()
}
}
fun YieldBalance.Data.getRewardStakingBalance(): BigDecimal {
return balance.items
.filter { it.type == BalanceType.REWARDS }
.sumOf { it.amount }
}
fun YieldBalance.Data.getValidatorsCount(): Int {
return balance.items
.filterNot { it.validatorAddress.isNullOrBlank() }
.distinctBy { it.validatorAddress }
.size
}

View file

@ -149,7 +149,7 @@ internal class StakingIdFactoryTest {
expected = createStakingId(integrationId = StakingIntegrationID.StakeKit.Coin.Cardano),
),
CreateModel(
currencyId = createCurrencyId(blockchain = Blockchain.Ethereum),
currencyId = createCurrencyId(blockchain = StakingIntegrationID.P2P.EthereumPooled.blockchain),
expected = createStakingId(integrationId = StakingIntegrationID.P2P.EthereumPooled),
),
CreateModel(

View file

@ -151,7 +151,7 @@ class StakingIntegrationIDTest {
expected = StakingIntegrationID.StakeKit.Coin.Cardano,
),
CreateModel(
currencyId = createCurrencyId(blockchain = Blockchain.Ethereum),
currencyId = createCurrencyId(blockchain = StakingIntegrationID.P2P.EthereumPooled.blockchain),
expected = StakingIntegrationID.P2P.EthereumPooled,
),
CreateModel(