Updated on 2026-08-14
This commit is contained in:
parent
daf2a6b636
commit
81a7b760ae
104 changed files with 1197 additions and 941 deletions
|
|
@ -6,7 +6,7 @@ import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
|||
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.derivations.DerivationsRepository
|
||||
|
|
@ -74,7 +74,7 @@ internal object ManageTokensDomainModule {
|
|||
derivationsRepository: DerivationsRepository,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): SaveManagedTokensUseCase {
|
||||
|
|
@ -85,7 +85,7 @@ internal object ManageTokensDomainModule {
|
|||
derivationsRepository = derivationsRepository,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher = multiStakingBalanceFetcher,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
|||
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.derivations.DerivationsRepository
|
||||
|
|
@ -70,7 +70,7 @@ object MarketsDomainModule {
|
|||
currenciesRepository: CurrenciesRepository,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): SaveMarketTokensUseCase {
|
||||
|
|
@ -81,7 +81,7 @@ object MarketsDomainModule {
|
|||
currenciesRepository = currenciesRepository,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher = multiStakingBalanceFetcher,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import com.tangem.domain.staking.repositories.StakingErrorResolver
|
|||
import com.tangem.domain.staking.repositories.StakeKitRepository
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.staking.repositories.StakeKitTransactionHashRepository
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.toggles.StakingFeatureToggles
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceFetcher
|
||||
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import dagger.Module
|
||||
|
|
@ -113,11 +113,11 @@ internal object StakingDomainModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideFetchStakingYieldBalanceUseCase(
|
||||
singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
|
||||
singleStakingBalanceFetcher: SingleStakingBalanceFetcher,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
): FetchStakingYieldBalanceUseCase {
|
||||
return FetchStakingYieldBalanceUseCase(
|
||||
singleYieldBalanceFetcher = singleYieldBalanceFetcher,
|
||||
singleStakingBalanceFetcher = singleStakingBalanceFetcher,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ import com.tangem.domain.quotes.QuotesRepository
|
|||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceSupplier
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceSupplier
|
||||
import com.tangem.domain.tokens.*
|
||||
import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
||||
import com.tangem.domain.tokens.operations.CachedCurrenciesStatusesOperations
|
||||
|
|
@ -46,7 +46,7 @@ internal object TokensDomainModule {
|
|||
walletManagersFacade: WalletManagersFacade,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
|
||||
singleStakingBalanceFetcher: SingleStakingBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
): AddCryptoCurrenciesUseCase {
|
||||
|
|
@ -55,7 +55,7 @@ internal object TokensDomainModule {
|
|||
walletManagersFacade = walletManagersFacade,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
singleYieldBalanceFetcher = singleYieldBalanceFetcher,
|
||||
singleStakingBalanceFetcher = singleStakingBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
)
|
||||
|
|
@ -153,7 +153,7 @@ internal object TokensDomainModule {
|
|||
currenciesRepository: CurrenciesRepository,
|
||||
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
|
||||
singleStakingBalanceFetcher: SingleStakingBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
): FetchCurrencyStatusUseCase {
|
||||
|
|
@ -161,7 +161,7 @@ internal object TokensDomainModule {
|
|||
currenciesRepository = currenciesRepository,
|
||||
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
singleYieldBalanceFetcher = singleYieldBalanceFetcher,
|
||||
singleStakingBalanceFetcher = singleStakingBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
)
|
||||
|
|
@ -344,8 +344,8 @@ internal object TokensDomainModule {
|
|||
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
|
||||
singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
|
||||
multiYieldBalanceSupplier: MultiYieldBalanceSupplier,
|
||||
singleStakingBalanceSupplier: SingleStakingBalanceSupplier,
|
||||
multiStakingBalanceSupplier: MultiStakingBalanceSupplier,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
): BaseCurrencyStatusOperations {
|
||||
|
|
@ -355,8 +355,8 @@ internal object TokensDomainModule {
|
|||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
singleQuoteStatusSupplier = singleQuoteStatusSupplier,
|
||||
singleYieldBalanceSupplier = singleYieldBalanceSupplier,
|
||||
multiYieldBalanceSupplier = multiYieldBalanceSupplier,
|
||||
singleStakingBalanceSupplier = singleStakingBalanceSupplier,
|
||||
multiStakingBalanceSupplier = multiStakingBalanceSupplier,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
)
|
||||
|
|
@ -376,7 +376,7 @@ internal object TokensDomainModule {
|
|||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): WalletBalanceFetcher {
|
||||
|
|
@ -386,7 +386,7 @@ internal object TokensDomainModule {
|
|||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher = multiStakingBalanceFetcher,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import com.tangem.domain.models.StatusSource
|
|||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.currency.yieldSupplyKey
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.staking.model.isStakingSupported
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.utils.getTotalWithRewardsStakingBalance
|
||||
|
|
@ -159,7 +159,7 @@ class TokenItemStateConverter(
|
|||
return totalAmount.format { crypto(currency) }
|
||||
}
|
||||
|
||||
private fun CryptoCurrencyStatus.getStakedBalance() = (value.yieldBalance as? YieldBalance.Data)
|
||||
private fun CryptoCurrencyStatus.getStakedBalance() = (value.stakingBalance as? StakingBalance.Data)
|
||||
?.getTotalWithRewardsStakingBalance(blockchainId = currency.network.rawId).orZero()
|
||||
|
||||
private fun createTitleState(
|
||||
|
|
@ -264,12 +264,13 @@ class TokenItemStateConverter(
|
|||
val validators = stakingApyMap[stakingKey]
|
||||
?: return StakingLocalInfo(rate = null, isActive = false, rewardType = null)
|
||||
|
||||
val yieldBalance = currencyStatus.value.yieldBalance
|
||||
val hasStakedBalance = yieldBalance is YieldBalance.Data
|
||||
val stakingBalance = currencyStatus.value.stakingBalance as? StakingBalance.Data
|
||||
val stakeKitBalance = stakingBalance as? StakingBalance.Data.StakeKit
|
||||
|
||||
val rateInfo: Pair<BigDecimal, Yield.RewardType?>? = if (hasStakedBalance) {
|
||||
val rateInfo: Pair<BigDecimal, Yield.RewardType?>? = if (stakeKitBalance != null) {
|
||||
// StakeKit-specific: try to find rate from validator address
|
||||
val validatorsByAddress = validators.associateBy { it.address }
|
||||
yieldBalance.balance.items
|
||||
stakeKitBalance.balance.items
|
||||
.mapNotNull { it.validatorAddress }
|
||||
.firstNotNullOfOrNull { address ->
|
||||
val validator = validatorsByAddress[address]
|
||||
|
|
@ -284,6 +285,8 @@ class TokenItemStateConverter(
|
|||
}
|
||||
.maxByOrNull { it.first }
|
||||
} else {
|
||||
// P2P or no balance: use preferred validators
|
||||
// TODO p2p
|
||||
validators
|
||||
.filter { it.preferred }
|
||||
.mapNotNull { validator ->
|
||||
|
|
@ -296,7 +299,7 @@ class TokenItemStateConverter(
|
|||
|
||||
return StakingLocalInfo(
|
||||
rate = rateInfo?.first,
|
||||
isActive = hasStakedBalance,
|
||||
isActive = stakingBalance != null,
|
||||
rewardType = rateInfo?.second,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,28 +4,32 @@ import com.tangem.datasource.api.stakekit.models.response.model.BalanceDTO
|
|||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.staking.BalanceItem
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.YieldBalanceItem
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.datetime.Instant
|
||||
|
||||
class YieldBalanceConverter(
|
||||
/**
|
||||
* Converts StakeKit DTO to [StakingBalance].
|
||||
* Returns [StakingBalance.Data.StakeKit] for non-empty balances, [StakingBalance.Empty] otherwise.
|
||||
*/
|
||||
class StakingBalanceConverter(
|
||||
private val source: StatusSource,
|
||||
) : Converter<YieldBalanceWrapperDTO, YieldBalance?> {
|
||||
) : Converter<YieldBalanceWrapperDTO, StakingBalance?> {
|
||||
|
||||
constructor(isCached: Boolean) : this(source = if (isCached) StatusSource.CACHE else StatusSource.ACTUAL)
|
||||
|
||||
override fun convert(value: YieldBalanceWrapperDTO): YieldBalance? {
|
||||
override fun convert(value: YieldBalanceWrapperDTO): StakingBalance? {
|
||||
val stakingId = StakingID(
|
||||
integrationId = value.integrationId ?: return null,
|
||||
address = value.addresses.address,
|
||||
)
|
||||
|
||||
return if (value.balances.isEmpty()) {
|
||||
YieldBalance.Empty(stakingId = stakingId, source = source)
|
||||
StakingBalance.Empty(stakingId = stakingId, source = source)
|
||||
} else {
|
||||
YieldBalance.Data(
|
||||
StakingBalance.Data.StakeKit(
|
||||
stakingId = stakingId,
|
||||
balance = YieldBalanceItem(
|
||||
items = value.balances
|
||||
|
|
@ -3,11 +3,11 @@ package com.tangem.data.staking
|
|||
import arrow.core.getOrElse
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.data.staking.store.YieldsBalancesStore
|
||||
import com.tangem.data.staking.store.StakingBalancesStore
|
||||
import com.tangem.domain.card.common.TapWorkarounds.isWallet2
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.staking.model.StakingAvailability
|
||||
|
|
@ -30,7 +30,7 @@ import kotlinx.coroutines.withContext
|
|||
internal class DefaultStakingRepository(
|
||||
private val stakeKitRepository: StakeKitRepository,
|
||||
private val p2pEthPoolRepository: P2PEthPoolRepository,
|
||||
private val stakingBalanceStoreV2: YieldsBalancesStore,
|
||||
private val stakingBalanceStoreV2: StakingBalancesStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val stakingFeatureToggles: StakingFeatureToggles,
|
||||
|
|
@ -106,13 +106,13 @@ internal class DefaultStakingRepository(
|
|||
return withContext(dispatchers.default) {
|
||||
val balances = stakingBalanceStoreV2.getAllSyncOrNull(userWalletId) ?: return@withContext false
|
||||
|
||||
val hasDataYieldBalance by lazy {
|
||||
balances.any { yieldBalance ->
|
||||
(yieldBalance as? YieldBalance.Data)?.balance?.items?.isNotEmpty() == true
|
||||
val hasDataStakingBalance by lazy {
|
||||
balances.any { stakingBalance ->
|
||||
stakingBalance is StakingBalance.Data
|
||||
}
|
||||
}
|
||||
|
||||
balances.isNotEmpty() && hasDataYieldBalance
|
||||
balances.isNotEmpty() && hasDataStakingBalance
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ internal class DefaultStakingRepository(
|
|||
address = address,
|
||||
),
|
||||
)
|
||||
if (balance != null && balance is YieldBalance.Data && balance.balance.items.isNotEmpty()) {
|
||||
if ((balance as? StakingBalance.Data.StakeKit)?.balance?.items?.isNotEmpty() == true) {
|
||||
return true
|
||||
} else {
|
||||
stakingFeatureToggles.isCardanoStakingEnabled
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
package com.tangem.data.staking.converters.ethpool
|
||||
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolAccountResponse
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolExitQueueDTO
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolExitRequestDTO
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolStakeDTO
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.staking.*
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
import kotlinx.datetime.Instant
|
||||
|
||||
/** Converts P2P ETH Pool API response to [StakingBalance.Data.P2P] */
|
||||
internal object P2PStakingBalanceConverter {
|
||||
|
||||
fun convert(response: P2PEthPoolAccountResponse, source: StatusSource): StakingBalance.Data.P2P {
|
||||
val stakingId = StakingID(
|
||||
integrationId = StakingIntegrationID.P2P.EthereumPooled.value,
|
||||
address = response.delegatorAddress,
|
||||
)
|
||||
|
||||
val account = P2PStakingAccount(
|
||||
delegatorAddress = response.delegatorAddress,
|
||||
vaultAddress = response.vaultAddress,
|
||||
stake = convertStake(response.stake),
|
||||
availableToUnstake = response.availableToUnstake,
|
||||
availableToWithdraw = response.availableToWithdraw,
|
||||
exitQueue = convertExitQueue(response.exitQueue),
|
||||
)
|
||||
|
||||
return StakingBalance.Data.P2P(
|
||||
stakingId = stakingId,
|
||||
source = source,
|
||||
account = account,
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertStake(dto: P2PEthPoolStakeDTO): P2PStake {
|
||||
return P2PStake(
|
||||
assets = dto.assets,
|
||||
totalEarnedAssets = dto.totalEarnedAssets,
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertExitQueue(dto: P2PEthPoolExitQueueDTO): P2PExitQueue {
|
||||
return P2PExitQueue(
|
||||
total = dto.total.toBigDecimal(),
|
||||
requests = dto.requests.map(::convertExitRequest),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertExitRequest(dto: P2PEthPoolExitRequestDTO): P2PExitRequest {
|
||||
return P2PExitRequest(
|
||||
ticket = dto.ticket,
|
||||
totalAssets = dto.totalAssets.toBigDecimal(),
|
||||
timestamp = Instant.fromEpochSeconds(dto.timestamp),
|
||||
withdrawalTimestamp = Instant.fromEpochSeconds(dto.withdrawalTimestamp),
|
||||
isClaimable = dto.isClaimable,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.data.staking.di
|
||||
|
||||
import com.tangem.data.staking.multi.DefaultMultiStakingBalanceFetcher
|
||||
import com.tangem.data.staking.single.DefaultSingleStakingBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceFetcher
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface StakingBalanceFetcherModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindSingleStakingBalanceFetcher(impl: DefaultSingleStakingBalanceFetcher): SingleStakingBalanceFetcher
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindMultiStakingBalanceFetcher(impl: DefaultMultiStakingBalanceFetcher): MultiStakingBalanceFetcher
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.data.staking.di
|
||||
|
||||
import com.tangem.data.staking.multi.DefaultMultiStakingBalanceProducer
|
||||
import com.tangem.data.staking.single.DefaultSingleStakingBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceProducer
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface StakingBalanceProducerFactoryModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindSingleStakingBalanceProducerFactory(
|
||||
impl: DefaultSingleStakingBalanceProducer.Factory,
|
||||
): SingleStakingBalanceProducer.Factory
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindMultiStakingBalanceProducerFactory(
|
||||
impl: DefaultMultiStakingBalanceProducer.Factory,
|
||||
): MultiStakingBalanceProducer.Factory
|
||||
}
|
||||
|
|
@ -2,19 +2,17 @@ package com.tangem.data.staking.di
|
|||
|
||||
import androidx.datastore.core.DataStore
|
||||
import com.tangem.data.staking.store.DefaultP2PBalancesStore
|
||||
import com.tangem.data.staking.store.DefaultYieldsBalancesStore
|
||||
import com.tangem.data.staking.store.DefaultStakingBalancesStore
|
||||
import com.tangem.data.staking.store.P2PBalancesStore
|
||||
import com.tangem.data.staking.store.YieldsBalancesStore
|
||||
import com.tangem.data.staking.store.StakingBalancesStore
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolAccountResponse
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import com.tangem.datasource.local.token.P2PEthPoolVaultsStore
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceSupplier
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.runSuspendCatching
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -23,15 +21,15 @@ import javax.inject.Singleton
|
|||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object YieldBalanceSupplierModule {
|
||||
internal object StakingBalanceSupplierModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideYieldsBalancesStore(
|
||||
fun provideStakingBalancesStore(
|
||||
persistenceStore: DataStore<Map<String, Set<YieldBalanceWrapperDTO>>>,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): YieldsBalancesStore {
|
||||
return DefaultYieldsBalancesStore(
|
||||
): StakingBalancesStore {
|
||||
return DefaultStakingBalancesStore(
|
||||
runtimeStore = RuntimeSharedStore(),
|
||||
persistenceStore = persistenceStore,
|
||||
dispatchers = dispatchers,
|
||||
|
|
@ -42,25 +40,25 @@ internal object YieldBalanceSupplierModule {
|
|||
@Singleton
|
||||
fun provideP2PBalancesStore(
|
||||
persistenceStore: DataStore<Map<String, Set<P2PEthPoolAccountResponse>>>,
|
||||
p2pVaultsStore: P2PEthPoolVaultsStore,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): P2PBalancesStore {
|
||||
return DefaultP2PBalancesStore(
|
||||
runtimeStore = RuntimeSharedStore(),
|
||||
persistenceStore = persistenceStore,
|
||||
vaultsProvider = { runSuspendCatching { p2pVaultsStore.getSync() }.getOrNull().orEmpty() },
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSingleYieldBalanceSupplier(factory: SingleYieldBalanceProducer.Factory): SingleYieldBalanceSupplier {
|
||||
return object : SingleYieldBalanceSupplier(
|
||||
fun provideSingleStakingBalanceSupplier(
|
||||
factory: SingleStakingBalanceProducer.Factory,
|
||||
): SingleStakingBalanceSupplier {
|
||||
return object : SingleStakingBalanceSupplier(
|
||||
factory = factory,
|
||||
keyCreator = { params ->
|
||||
listOf(
|
||||
"single_yield_balance",
|
||||
"single_staking_balance",
|
||||
params.userWalletId.stringValue,
|
||||
params.stakingId.integrationId,
|
||||
params.stakingId.address,
|
||||
|
|
@ -72,10 +70,10 @@ internal object YieldBalanceSupplierModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideMultiYieldBalanceSupplier(factory: MultiYieldBalanceProducer.Factory): MultiYieldBalanceSupplier {
|
||||
return object : MultiYieldBalanceSupplier(
|
||||
fun provideMultiStakingBalanceSupplier(factory: MultiStakingBalanceProducer.Factory): MultiStakingBalanceSupplier {
|
||||
return object : MultiStakingBalanceSupplier(
|
||||
factory = factory,
|
||||
keyCreator = { "multi_yields_balances_${it.userWalletId.stringValue}" },
|
||||
keyCreator = { "multi_staking_balances_${it.userWalletId.stringValue}" },
|
||||
) {}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
|
|||
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
|
||||
import com.tangem.data.staking.*
|
||||
import com.tangem.data.staking.converters.error.StakeKitErrorConverter
|
||||
import com.tangem.data.staking.store.YieldsBalancesStore
|
||||
import com.tangem.data.staking.store.StakingBalancesStore
|
||||
import com.tangem.data.staking.toggles.DefaultStakingFeatureToggles
|
||||
import com.tangem.data.staking.utils.DefaultStakingCleaner
|
||||
import com.tangem.datasource.api.ethpool.P2PEthPoolApi
|
||||
|
|
@ -55,7 +55,7 @@ internal object StakingDataModule {
|
|||
fun provideStakingRepository(
|
||||
stakeKitRepository: StakeKitRepository,
|
||||
p2pEthPoolRepository: P2PEthPoolRepository,
|
||||
yieldsBalancesStore: YieldsBalancesStore,
|
||||
stakingBalancesStore: StakingBalancesStore,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
getUserWalletUseCase: GetUserWalletUseCase,
|
||||
stakingFeatureToggles: StakingFeatureToggles,
|
||||
|
|
@ -64,7 +64,7 @@ internal object StakingDataModule {
|
|||
return DefaultStakingRepository(
|
||||
stakeKitRepository = stakeKitRepository,
|
||||
p2pEthPoolRepository = p2pEthPoolRepository,
|
||||
stakingBalanceStoreV2 = yieldsBalancesStore,
|
||||
stakingBalanceStoreV2 = stakingBalancesStore,
|
||||
dispatchers = dispatchers,
|
||||
getUserWalletUseCase = getUserWalletUseCase,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
|
|
@ -134,11 +134,11 @@ internal object StakingDataModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideStakingCleaner(
|
||||
yieldsBalancesStore: YieldsBalancesStore,
|
||||
stakingBalancesStore: StakingBalancesStore,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): StakingCleaner {
|
||||
return DefaultStakingCleaner(
|
||||
yieldsBalancesStore = yieldsBalancesStore,
|
||||
stakingBalancesStore = stakingBalancesStore,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
package com.tangem.data.staking.di
|
||||
|
||||
import com.tangem.data.staking.multi.DefaultMultiYieldBalanceFetcher
|
||||
import com.tangem.data.staking.single.DefaultSingleYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface YieldBalanceFetcherModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindSingleYieldBalanceFetcher(impl: DefaultSingleYieldBalanceFetcher): SingleYieldBalanceFetcher
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindMultiYieldBalanceFetcher(impl: DefaultMultiYieldBalanceFetcher): MultiYieldBalanceFetcher
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
package com.tangem.data.staking.di
|
||||
|
||||
import com.tangem.data.staking.multi.DefaultMultiYieldBalanceProducer
|
||||
import com.tangem.data.staking.single.DefaultSingleYieldBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceProducer
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface YieldBalanceProducerFactoryModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindSingleYieldBalanceProducerFactory(
|
||||
impl: DefaultSingleYieldBalanceProducer.Factory,
|
||||
): SingleYieldBalanceProducer.Factory
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindMultiYieldBalanceProducerFactory(
|
||||
impl: DefaultMultiYieldBalanceProducer.Factory,
|
||||
): MultiYieldBalanceProducer.Factory
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import arrow.core.right
|
|||
import arrow.core.toOption
|
||||
import com.tangem.data.common.api.safeApiCall
|
||||
import com.tangem.data.staking.store.P2PBalancesStore
|
||||
import com.tangem.data.staking.store.YieldsBalancesStore
|
||||
import com.tangem.data.staking.store.StakingBalancesStore
|
||||
import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory
|
||||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.ethpool.P2PEthPoolApi
|
||||
|
|
@ -25,7 +25,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
import com.tangem.domain.staking.model.ethpool.P2PEthPoolNetwork
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.runSuspendCatching
|
||||
import kotlinx.coroutines.async
|
||||
|
|
@ -36,13 +36,13 @@ import timber.log.Timber
|
|||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Default implementation of [MultiYieldBalanceFetcher]
|
||||
* Default implementation of [MultiStakingBalanceFetcher]
|
||||
*
|
||||
* Supports both StakeKit and P2P staking providers.
|
||||
*
|
||||
* @property userWalletsStore user wallets store
|
||||
* @property stakingYieldsStore staking yields store
|
||||
* @property yieldsBalancesStore yields balances store (StakeKit)
|
||||
* @property stakingBalancesStore staking balances store (StakeKit)
|
||||
* @property p2pBalancesStore P2P balances store
|
||||
* @property stakeKitApi stake kit API
|
||||
* @property p2pApi P2P ETH Pool API
|
||||
|
|
@ -52,19 +52,19 @@ import javax.inject.Inject
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
internal class DefaultMultiYieldBalanceFetcher @Inject constructor(
|
||||
internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
|
||||
private val userWalletsStore: UserWalletsStore,
|
||||
private val stakingYieldsStore: StakingYieldsStore,
|
||||
private val yieldsBalancesStore: YieldsBalancesStore,
|
||||
private val stakingBalancesStore: StakingBalancesStore,
|
||||
private val p2pBalancesStore: P2PBalancesStore,
|
||||
private val stakeKitApi: StakeKitApi,
|
||||
private val p2pApi: P2PEthPoolApi,
|
||||
private val p2pVaultsStore: P2PEthPoolVaultsStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : MultiYieldBalanceFetcher {
|
||||
) : MultiStakingBalanceFetcher {
|
||||
|
||||
override suspend fun invoke(params: MultiYieldBalanceFetcher.Params): Either<Throwable, Unit> {
|
||||
Timber.i("Start fetching yield balances for params:\n$params")
|
||||
override suspend fun invoke(params: MultiStakingBalanceFetcher.Params): Either<Throwable, Unit> {
|
||||
Timber.i("Start fetching staking balances for params:\n$params")
|
||||
|
||||
val stakingIds = params.stakingIds.ifEmpty {
|
||||
Timber.i("Nothing to fetch, empty stakingIds for ${params.userWalletId}")
|
||||
|
|
@ -102,10 +102,13 @@ internal class DefaultMultiYieldBalanceFetcher @Inject constructor(
|
|||
}
|
||||
}
|
||||
.onLeft { throwable ->
|
||||
Timber.e(throwable, "Unable to fetch yield balances $params")
|
||||
Timber.e(throwable, "Unable to fetch staking balances $params")
|
||||
|
||||
if (stakeKitIds.isNotEmpty()) {
|
||||
yieldsBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = stakeKitIds.toSet())
|
||||
stakingBalancesStore.storeError(
|
||||
userWalletId = params.userWalletId,
|
||||
stakingIds = stakeKitIds.toSet(),
|
||||
)
|
||||
}
|
||||
if (p2pIds.isNotEmpty()) {
|
||||
p2pBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = p2pIds.toSet())
|
||||
|
|
@ -114,7 +117,7 @@ internal class DefaultMultiYieldBalanceFetcher @Inject constructor(
|
|||
}
|
||||
|
||||
private suspend fun fetchStakeKitBalances(userWalletId: UserWalletId, stakingIds: Set<StakingID>) {
|
||||
yieldsBalancesStore.refresh(userWalletId = userWalletId, stakingIds = stakingIds)
|
||||
stakingBalancesStore.refresh(userWalletId = userWalletId, stakingIds = stakingIds)
|
||||
|
||||
val availableStakingIds = getAvailableStakingIds(
|
||||
userWalletId = userWalletId,
|
||||
|
|
@ -252,7 +255,7 @@ internal class DefaultMultiYieldBalanceFetcher @Inject constructor(
|
|||
)
|
||||
|
||||
if (unavailableStakingIds.isNotEmpty()) {
|
||||
yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = unavailableStakingIds.toSet())
|
||||
stakingBalancesStore.storeError(userWalletId = userWalletId, stakingIds = unavailableStakingIds.toSet())
|
||||
}
|
||||
|
||||
return availableStakingIds.toSet().ifEmpty {
|
||||
|
|
@ -301,8 +304,10 @@ internal class DefaultMultiYieldBalanceFetcher @Inject constructor(
|
|||
.toSet()
|
||||
}
|
||||
|
||||
Timber.i("Successfully fetched yield balances for $userWalletId:\n${yieldBalances.joinToString("\n")}")
|
||||
yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = yieldBalances)
|
||||
Timber.i(
|
||||
"Successfully fetched staking balances for $userWalletId:\n${yieldBalances.joinToString("\n")}",
|
||||
)
|
||||
stakingBalancesStore.storeActual(userWalletId = userWalletId, values = yieldBalances)
|
||||
|
||||
if (!allResponsesReceived(requests, yieldBalances)) {
|
||||
val values = stakingIds.filter { stakingId ->
|
||||
|
|
@ -312,13 +317,13 @@ internal class DefaultMultiYieldBalanceFetcher @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = values.toSet())
|
||||
stakingBalancesStore.storeError(userWalletId = userWalletId, stakingIds = values.toSet())
|
||||
}
|
||||
},
|
||||
onError = { throwable ->
|
||||
Timber.e(throwable, "Unable to fetch yield balances $userWalletId")
|
||||
Timber.e(throwable, "Unable to fetch staking balances $userWalletId")
|
||||
|
||||
yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = stakingIds)
|
||||
stakingBalancesStore.storeError(userWalletId = userWalletId, stakingIds = stakingIds)
|
||||
|
||||
throw throwable
|
||||
},
|
||||
|
|
@ -3,9 +3,9 @@ package com.tangem.data.staking.multi
|
|||
import arrow.core.Option
|
||||
import arrow.core.some
|
||||
import com.tangem.data.staking.store.P2PBalancesStore
|
||||
import com.tangem.data.staking.store.YieldsBalancesStore
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceProducer
|
||||
import com.tangem.data.staking.store.StakingBalancesStore
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceProducer
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
|
|
@ -17,28 +17,28 @@ import kotlinx.coroutines.flow.flowOn
|
|||
import kotlinx.coroutines.flow.onEmpty
|
||||
|
||||
/**
|
||||
* Default implementation of [MultiYieldBalanceProducer]
|
||||
* Default implementation of [MultiStakingBalanceProducer]
|
||||
*
|
||||
* Combines yield balances from both StakeKit and P2P providers.
|
||||
* Combines staking balances from both StakeKit and P2P providers.
|
||||
*
|
||||
* @property params params
|
||||
* @property yieldsBalancesStore StakeKit yields balances store
|
||||
* @property stakingBalancesStore StakeKit staking balances store
|
||||
* @property p2pBalancesStore P2P balances store
|
||||
* @property dispatchers dispatchers
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultMultiYieldBalanceProducer @AssistedInject constructor(
|
||||
@Assisted val params: MultiYieldBalanceProducer.Params,
|
||||
private val yieldsBalancesStore: YieldsBalancesStore,
|
||||
internal class DefaultMultiStakingBalanceProducer @AssistedInject constructor(
|
||||
@Assisted val params: MultiStakingBalanceProducer.Params,
|
||||
private val stakingBalancesStore: StakingBalancesStore,
|
||||
private val p2pBalancesStore: P2PBalancesStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : MultiYieldBalanceProducer {
|
||||
) : MultiStakingBalanceProducer {
|
||||
|
||||
override val fallback: Option<Set<YieldBalance>> = emptySet<YieldBalance>().some()
|
||||
override val fallback: Option<Set<StakingBalance>> = emptySet<StakingBalance>().some()
|
||||
|
||||
override fun produce(): Flow<Set<YieldBalance>> {
|
||||
val stakeKitFlow = yieldsBalancesStore.get(userWalletId = params.userWalletId)
|
||||
override fun produce(): Flow<Set<StakingBalance>> {
|
||||
val stakeKitFlow = stakingBalancesStore.get(userWalletId = params.userWalletId)
|
||||
val p2pFlow = p2pBalancesStore.get(userWalletId = params.userWalletId)
|
||||
|
||||
return combine(stakeKitFlow, p2pFlow) { stakeKitBalances, p2pBalances ->
|
||||
|
|
@ -50,7 +50,7 @@ internal class DefaultMultiYieldBalanceProducer @AssistedInject constructor(
|
|||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : MultiYieldBalanceProducer.Factory {
|
||||
override fun create(params: MultiYieldBalanceProducer.Params): DefaultMultiYieldBalanceProducer
|
||||
interface Factory : MultiStakingBalanceProducer.Factory {
|
||||
override fun create(params: MultiStakingBalanceProducer.Params): DefaultMultiStakingBalanceProducer
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.data.staking.single
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceFetcher
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Default implementation of [SingleStakingBalanceFetcher]
|
||||
*
|
||||
* @property multiStakingBalanceFetcher multi staking balance fetcher
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultSingleStakingBalanceFetcher @Inject constructor(
|
||||
private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
) : SingleStakingBalanceFetcher {
|
||||
|
||||
override suspend fun invoke(params: SingleStakingBalanceFetcher.Params): Either<Throwable, Unit> {
|
||||
return multiStakingBalanceFetcher(
|
||||
params = MultiStakingBalanceFetcher.Params(
|
||||
userWalletId = params.userWalletId,
|
||||
stakingIds = setOf(params.stakingId),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,10 @@ import arrow.core.Option
|
|||
import arrow.core.some
|
||||
import com.tangem.core.analytics.api.AnalyticsExceptionHandler
|
||||
import com.tangem.core.analytics.models.ExceptionAnalyticsEvent
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceProducer
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceProducer
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.indexOfFirstOrNull
|
||||
import dagger.assisted.Assisted
|
||||
|
|
@ -20,29 +20,29 @@ import kotlinx.coroutines.flow.mapNotNull
|
|||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Default implementation of [SingleYieldBalanceProducer]
|
||||
* Default implementation of [SingleStakingBalanceProducer]
|
||||
*
|
||||
* @property params params
|
||||
* @property multiYieldBalanceSupplier multi yield balance supplier
|
||||
* @property analyticsExceptionHandler analytics exception handler
|
||||
* @property dispatchers dispatchers
|
||||
* @property params params
|
||||
* @property multiStakingBalanceSupplier multi staking balance supplier
|
||||
* @property analyticsExceptionHandler analytics exception handler
|
||||
* @property dispatchers dispatchers
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultSingleYieldBalanceProducer @AssistedInject constructor(
|
||||
@Assisted private val params: SingleYieldBalanceProducer.Params,
|
||||
private val multiYieldBalanceSupplier: MultiYieldBalanceSupplier,
|
||||
internal class DefaultSingleStakingBalanceProducer @AssistedInject constructor(
|
||||
@Assisted private val params: SingleStakingBalanceProducer.Params,
|
||||
private val multiStakingBalanceSupplier: MultiStakingBalanceSupplier,
|
||||
private val analyticsExceptionHandler: AnalyticsExceptionHandler,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : SingleYieldBalanceProducer {
|
||||
) : SingleStakingBalanceProducer {
|
||||
|
||||
override val fallback: Option<YieldBalance> = YieldBalance.Error(stakingId = params.stakingId).some()
|
||||
override val fallback: Option<StakingBalance> = StakingBalance.Error(stakingId = params.stakingId).some()
|
||||
|
||||
override fun produce(): Flow<YieldBalance> {
|
||||
Timber.i("Producing yield balance for params:\n$params")
|
||||
override fun produce(): Flow<StakingBalance> {
|
||||
Timber.i("Producing staking balance for params:\n$params")
|
||||
|
||||
return multiYieldBalanceSupplier(
|
||||
params = MultiYieldBalanceProducer.Params(userWalletId = params.userWalletId),
|
||||
return multiStakingBalanceSupplier(
|
||||
params = MultiStakingBalanceProducer.Params(userWalletId = params.userWalletId),
|
||||
)
|
||||
.mapNotNull { balances ->
|
||||
val currentStakingId = params.stakingId
|
||||
|
|
@ -65,7 +65,7 @@ internal class DefaultSingleYieldBalanceProducer @AssistedInject constructor(
|
|||
currentBalances.joinToString("\n"),
|
||||
)
|
||||
|
||||
val dataIndex = currentBalances.indexOfFirstOrNull { it is YieldBalance.Data }
|
||||
val dataIndex = currentBalances.indexOfFirstOrNull { it is StakingBalance.Data }
|
||||
|
||||
if (dataIndex != null) {
|
||||
currentBalances[dataIndex]
|
||||
|
|
@ -75,7 +75,7 @@ internal class DefaultSingleYieldBalanceProducer @AssistedInject constructor(
|
|||
} else {
|
||||
val balance = currentBalances.firstOrNull() ?: return@mapNotNull null
|
||||
|
||||
Timber.i("Yield balance found for $currentStakingId:\n$balance")
|
||||
Timber.i("Staking balance found for $currentStakingId:\n$balance")
|
||||
balance
|
||||
}
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ internal class DefaultSingleYieldBalanceProducer @AssistedInject constructor(
|
|||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : SingleYieldBalanceProducer.Factory {
|
||||
override fun create(params: SingleYieldBalanceProducer.Params): DefaultSingleYieldBalanceProducer
|
||||
interface Factory : SingleStakingBalanceProducer.Factory {
|
||||
override fun create(params: SingleStakingBalanceProducer.Params): DefaultSingleStakingBalanceProducer
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
package com.tangem.data.staking.single
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Default implementation of [MultiYieldBalanceFetcher]
|
||||
*
|
||||
* @property multiYieldBalanceFetcher multi yield balance fetcher
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultSingleYieldBalanceFetcher @Inject constructor(
|
||||
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
) : SingleYieldBalanceFetcher {
|
||||
|
||||
override suspend fun invoke(params: SingleYieldBalanceFetcher.Params): Either<Throwable, Unit> {
|
||||
return multiYieldBalanceFetcher(
|
||||
params = MultiYieldBalanceFetcher.Params(
|
||||
userWalletId = params.userWalletId,
|
||||
stakingIds = setOf(params.stakingId),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,14 @@
|
|||
package com.tangem.data.staking.store
|
||||
|
||||
import androidx.datastore.core.DataStore
|
||||
import com.tangem.data.staking.converters.ethpool.P2PEthPoolAccountConverter
|
||||
import com.tangem.data.staking.converters.ethpool.P2PYieldBalanceConverter
|
||||
import com.tangem.data.staking.converters.ethpool.P2PStakingBalanceConverter
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolAccountResponse
|
||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.staking.model.ethpool.P2PEthPoolVault
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.addOrReplace
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -19,25 +18,22 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
internal typealias WalletIdWithP2PBalances = Map<UserWalletId, Set<YieldBalance>>
|
||||
internal typealias WalletIdWithP2PStakingBalances = Map<UserWalletId, Set<StakingBalance>>
|
||||
internal typealias WalletIdWithP2PResponses = Map<String, Set<P2PEthPoolAccountResponse>>
|
||||
|
||||
/**
|
||||
* Default implementation of [P2PBalancesStore]
|
||||
*
|
||||
* Stores P2P ETH Pool staking balances with persistence support.
|
||||
* Stores P2P ETH Pool staking balances.
|
||||
*
|
||||
* @property runtimeStore runtime store
|
||||
* @property persistenceStore persistence store
|
||||
* @property vaultsProvider provider for vaults
|
||||
* @param dispatchers coroutine dispatchers
|
||||
*/
|
||||
internal class DefaultP2PBalancesStore(
|
||||
private val runtimeStore: RuntimeSharedStore<WalletIdWithP2PBalances>,
|
||||
private val runtimeStore: RuntimeSharedStore<WalletIdWithP2PStakingBalances>,
|
||||
private val persistenceStore: DataStore<WalletIdWithP2PResponses>,
|
||||
private val vaultsProvider: suspend () -> List<P2PEthPoolVault>,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
) : P2PBalancesStore {
|
||||
|
||||
|
|
@ -46,19 +42,13 @@ internal class DefaultP2PBalancesStore(
|
|||
init {
|
||||
scope.launch {
|
||||
val cachedData = persistenceStore.data.firstOrNull() ?: return@launch
|
||||
val vaults = vaultsProvider()
|
||||
|
||||
runtimeStore.store(
|
||||
value = cachedData.map { (stringWalletId, responses) ->
|
||||
val key = UserWalletId(stringWalletId)
|
||||
val value = responses.mapNotNull { response ->
|
||||
val vault = vaults.firstOrNull { it.vaultAddress == response.vaultAddress }
|
||||
?: return@mapNotNull null
|
||||
val account = P2PEthPoolAccountConverter.convert(response)
|
||||
P2PYieldBalanceConverter.convert(
|
||||
account = account,
|
||||
vault = vault,
|
||||
address = account.delegatorAddress,
|
||||
val value = responses.map { response ->
|
||||
P2PStakingBalanceConverter.convert(
|
||||
response = response,
|
||||
source = StatusSource.CACHE,
|
||||
)
|
||||
}.toSet()
|
||||
|
|
@ -69,17 +59,17 @@ internal class DefaultP2PBalancesStore(
|
|||
}
|
||||
}
|
||||
|
||||
override fun get(userWalletId: UserWalletId): Flow<Set<YieldBalance>> {
|
||||
override fun get(userWalletId: UserWalletId): Flow<Set<StakingBalance>> {
|
||||
return runtimeStore.get().map { it[userWalletId].orEmpty() }
|
||||
}
|
||||
|
||||
override suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): YieldBalance? {
|
||||
override suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): StakingBalance? {
|
||||
return runtimeStore.getSyncOrNull()
|
||||
?.get(userWalletId)
|
||||
?.firstOrNull { it.stakingId == stakingId }
|
||||
}
|
||||
|
||||
override suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<YieldBalance>? {
|
||||
override suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<StakingBalance>? {
|
||||
return runtimeStore.getSyncOrNull()?.get(userWalletId)
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +94,7 @@ internal class DefaultP2PBalancesStore(
|
|||
updateInRuntime(
|
||||
userWalletId = userWalletId,
|
||||
stakingIds = stakingIds,
|
||||
ifNotFound = ::createErrorYieldBalance,
|
||||
ifNotFound = ::createErrorStakingBalance,
|
||||
update = { it.copySealed(source = StatusSource.ONLY_CACHE) },
|
||||
)
|
||||
}
|
||||
|
|
@ -117,20 +107,9 @@ internal class DefaultP2PBalancesStore(
|
|||
}
|
||||
|
||||
private suspend fun storeInRuntime(userWalletId: UserWalletId, values: Set<P2PEthPoolAccountResponse>) {
|
||||
val vaults = vaultsProvider()
|
||||
|
||||
val newBalances = values.mapNotNull { response ->
|
||||
val vault = vaults.firstOrNull { it.vaultAddress == response.vaultAddress }
|
||||
if (vault == null) {
|
||||
Timber.w("Vault not found for ${response.vaultAddress}")
|
||||
return@mapNotNull null
|
||||
}
|
||||
|
||||
val account = P2PEthPoolAccountConverter.convert(response)
|
||||
P2PYieldBalanceConverter.convert(
|
||||
account = account,
|
||||
vault = vault,
|
||||
address = account.delegatorAddress,
|
||||
val newBalances = values.map { response ->
|
||||
P2PStakingBalanceConverter.convert(
|
||||
response = response,
|
||||
source = StatusSource.ACTUAL,
|
||||
)
|
||||
}.toSet()
|
||||
|
|
@ -173,8 +152,7 @@ internal class DefaultP2PBalancesStore(
|
|||
current.toMutableMap().apply {
|
||||
this[userWalletId.stringValue] = this[userWalletId.stringValue].orEmpty()
|
||||
.filterNot { response ->
|
||||
val responseIntegrationId = "p2p-ethereum-pooled:${response.vaultAddress}"
|
||||
responseIntegrationId in integrationIds
|
||||
StakingIntegrationID.P2P.EthereumPooled.value in integrationIds
|
||||
}
|
||||
.toSet()
|
||||
}
|
||||
|
|
@ -184,8 +162,8 @@ internal class DefaultP2PBalancesStore(
|
|||
private suspend fun updateInRuntime(
|
||||
userWalletId: UserWalletId,
|
||||
stakingIds: Set<StakingID>,
|
||||
ifNotFound: (StakingID) -> YieldBalance? = { null },
|
||||
update: (YieldBalance) -> YieldBalance,
|
||||
ifNotFound: (StakingID) -> StakingBalance? = { null },
|
||||
update: (StakingBalance) -> StakingBalance,
|
||||
) {
|
||||
runtimeStore.update(default = emptyMap()) { stored ->
|
||||
stored.toMutableMap().apply {
|
||||
|
|
@ -209,5 +187,5 @@ internal class DefaultP2PBalancesStore(
|
|||
}
|
||||
}
|
||||
|
||||
private fun createErrorYieldBalance(id: StakingID): YieldBalance = YieldBalance.Error(stakingId = id)
|
||||
private fun createErrorStakingBalance(id: StakingID): StakingBalance = StakingBalance.Error(stakingId = id)
|
||||
}
|
||||
|
|
@ -3,10 +3,10 @@ package com.tangem.data.staking.store
|
|||
import androidx.datastore.core.DataStore
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import com.tangem.datasource.local.token.converter.YieldBalanceConverter
|
||||
import com.tangem.datasource.local.token.converter.StakingBalanceConverter
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.addOrReplace
|
||||
|
|
@ -19,10 +19,10 @@ import kotlinx.coroutines.flow.map
|
|||
import kotlinx.coroutines.launch
|
||||
|
||||
internal typealias WalletIdWithWrappers = Map<String, Set<YieldBalanceWrapperDTO>>
|
||||
internal typealias WalletIdWithBalances = Map<UserWalletId, Set<YieldBalance>>
|
||||
internal typealias WalletIdWithStakingBalances = Map<UserWalletId, Set<StakingBalance>>
|
||||
|
||||
/**
|
||||
* Default implementation of [YieldsBalancesStore]
|
||||
* Default implementation of [StakingBalancesStore]
|
||||
*
|
||||
* @property runtimeStore runtime store
|
||||
* @property persistenceStore persistence store
|
||||
|
|
@ -30,11 +30,11 @@ internal typealias WalletIdWithBalances = Map<UserWalletId, Set<YieldBalance>>
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultYieldsBalancesStore(
|
||||
private val runtimeStore: RuntimeSharedStore<WalletIdWithBalances>,
|
||||
internal class DefaultStakingBalancesStore(
|
||||
private val runtimeStore: RuntimeSharedStore<WalletIdWithStakingBalances>,
|
||||
private val persistenceStore: DataStore<WalletIdWithWrappers>,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
) : YieldsBalancesStore {
|
||||
) : StakingBalancesStore {
|
||||
|
||||
private val scope = CoroutineScope(context = SupervisorJob() + dispatchers.io)
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ internal class DefaultYieldsBalancesStore(
|
|||
runtimeStore.store(
|
||||
value = cachedStatuses.map { (stringWalletId, wrappers) ->
|
||||
val key = UserWalletId(stringWalletId)
|
||||
val value = YieldBalanceConverter(isCached = true).convertSet(input = wrappers)
|
||||
val value = StakingBalanceConverter(isCached = true).convertSet(input = wrappers)
|
||||
.filterNotNull()
|
||||
.toSet()
|
||||
|
||||
|
|
@ -56,17 +56,17 @@ internal class DefaultYieldsBalancesStore(
|
|||
}
|
||||
}
|
||||
|
||||
override fun get(userWalletId: UserWalletId): Flow<Set<YieldBalance>> {
|
||||
override fun get(userWalletId: UserWalletId): Flow<Set<StakingBalance>> {
|
||||
return runtimeStore.get().map { it[userWalletId].orEmpty() }
|
||||
}
|
||||
|
||||
override suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): YieldBalance? {
|
||||
override suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): StakingBalance? {
|
||||
return runtimeStore.getSyncOrNull()
|
||||
?.get(userWalletId)
|
||||
?.firstOrNull { it.stakingId == stakingId }
|
||||
}
|
||||
|
||||
override suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<YieldBalance>? {
|
||||
override suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<StakingBalance>? {
|
||||
return runtimeStore.getSyncOrNull()?.get(userWalletId)
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ internal class DefaultYieldsBalancesStore(
|
|||
updateInRuntime(
|
||||
userWalletId = userWalletId,
|
||||
stakingIds = stakingIds,
|
||||
ifNotFound = ::createErrorYieldBalance,
|
||||
ifNotFound = ::createErrorStakingBalance,
|
||||
update = { it.copySealed(source = StatusSource.ONLY_CACHE) },
|
||||
)
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ internal class DefaultYieldsBalancesStore(
|
|||
}
|
||||
|
||||
private suspend fun storeInRuntime(userWalletId: UserWalletId, values: Set<YieldBalanceWrapperDTO>) {
|
||||
val newBalances = YieldBalanceConverter(isCached = false).convertSet(input = values)
|
||||
val newBalances = StakingBalanceConverter(isCached = false).convertSet(input = values)
|
||||
.filterNotNull()
|
||||
.toSet()
|
||||
|
||||
|
|
@ -140,8 +140,8 @@ internal class DefaultYieldsBalancesStore(
|
|||
private suspend fun updateInRuntime(
|
||||
userWalletId: UserWalletId,
|
||||
stakingIds: Set<StakingID>,
|
||||
ifNotFound: (StakingID) -> YieldBalance? = { null },
|
||||
update: (YieldBalance) -> YieldBalance,
|
||||
ifNotFound: (StakingID) -> StakingBalance? = { null },
|
||||
update: (StakingBalance) -> StakingBalance,
|
||||
) {
|
||||
runtimeStore.update(default = emptyMap()) { stored ->
|
||||
stored.toMutableMap().apply {
|
||||
|
|
@ -165,7 +165,7 @@ internal class DefaultYieldsBalancesStore(
|
|||
}
|
||||
}
|
||||
|
||||
private fun createErrorYieldBalance(id: StakingID): YieldBalance = YieldBalance.Error(stakingId = id)
|
||||
private fun createErrorStakingBalance(id: StakingID): StakingBalance = StakingBalance.Error(stakingId = id)
|
||||
|
||||
private fun YieldBalanceWrapperDTO.getStakingId(): StakingID? {
|
||||
val integrationId = integrationId
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.data.staking.store
|
||||
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolAccountResponse
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
|
|
@ -11,11 +11,11 @@ import kotlinx.coroutines.flow.Flow
|
|||
*/
|
||||
interface P2PBalancesStore {
|
||||
|
||||
fun get(userWalletId: UserWalletId): Flow<Set<YieldBalance>>
|
||||
fun get(userWalletId: UserWalletId): Flow<Set<StakingBalance>>
|
||||
|
||||
suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): YieldBalance?
|
||||
suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): StakingBalance?
|
||||
|
||||
suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<YieldBalance>?
|
||||
suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<StakingBalance>?
|
||||
|
||||
suspend fun refresh(userWalletId: UserWalletId, stakingId: StakingID)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,39 +1,27 @@
|
|||
package com.tangem.data.staking.store
|
||||
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Store of [YieldBalance]'s set
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface YieldsBalancesStore {
|
||||
/** Store of StakeKit [StakingBalance] */
|
||||
interface StakingBalancesStore {
|
||||
|
||||
/** Get flow of [YieldBalance]'s set by [userWalletId] */
|
||||
fun get(userWalletId: UserWalletId): Flow<Set<YieldBalance>>
|
||||
fun get(userWalletId: UserWalletId): Flow<Set<StakingBalance>>
|
||||
|
||||
/** Get [YieldBalance] by [userWalletId] and [stakingId] synchronously or null */
|
||||
suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): YieldBalance?
|
||||
suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): StakingBalance?
|
||||
|
||||
/** Get all [YieldBalance] by [userWalletId] synchronously or null */
|
||||
suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<YieldBalance>?
|
||||
suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<StakingBalance>?
|
||||
|
||||
/** Refresh balance of [stakingId] by [userWalletId] */
|
||||
suspend fun refresh(userWalletId: UserWalletId, stakingId: StakingID)
|
||||
|
||||
/** Refresh balances of [stakingIds] by [userWalletId] */
|
||||
suspend fun refresh(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
|
||||
/** Store actual [values] by [userWalletId] */
|
||||
suspend fun storeActual(userWalletId: UserWalletId, values: Set<YieldBalanceWrapperDTO>)
|
||||
|
||||
/** Store error by [userWalletId] and [stakingIds] */
|
||||
suspend fun storeError(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
|
||||
/** Clear balances of [stakingIds] by [userWalletId] */
|
||||
suspend fun clear(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.data.staking.utils
|
||||
|
||||
import com.tangem.data.staking.store.YieldsBalancesStore
|
||||
import com.tangem.data.staking.store.StakingBalancesStore
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.staking.utils.StakingCleaner
|
||||
|
|
@ -9,13 +9,13 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
|||
/**
|
||||
* Default implementation of [StakingCleaner].
|
||||
*
|
||||
* @property yieldsBalancesStore Store to manage yields balances.
|
||||
* @property stakingBalancesStore Store to manage staking balances.
|
||||
* @property dispatchers Coroutine dispatchers provider.
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultStakingCleaner(
|
||||
private val yieldsBalancesStore: YieldsBalancesStore,
|
||||
private val stakingBalancesStore: StakingBalancesStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : StakingCleaner {
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ internal class DefaultStakingCleaner(
|
|||
if (stakingIds.isEmpty()) return
|
||||
|
||||
with(dispatchers.default) {
|
||||
yieldsBalancesStore.clear(userWalletId, stakingIds)
|
||||
stakingBalancesStore.clear(userWalletId, stakingIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,19 @@
|
|||
package com.tangem.data.staking
|
||||
|
||||
import com.tangem.common.test.data.staking.MockP2PEthPoolAccountResponseFactory
|
||||
import com.tangem.data.staking.converters.ethpool.P2PEthPoolAccountConverter
|
||||
import com.tangem.data.staking.converters.ethpool.P2PYieldBalanceConverter
|
||||
import com.tangem.data.staking.converters.ethpool.P2PStakingBalanceConverter
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolAccountResponse
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||
import com.tangem.datasource.local.token.converter.YieldBalanceConverter
|
||||
import com.tangem.datasource.local.token.converter.StakingBalanceConverter
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.staking.model.ethpool.P2PEthPoolVault
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
|
||||
internal fun YieldBalanceWrapperDTO.toDomain(source: StatusSource = StatusSource.CACHE): YieldBalance {
|
||||
return YieldBalanceConverter(source = source).convert(this)!!
|
||||
internal fun YieldBalanceWrapperDTO.toDomain(source: StatusSource = StatusSource.CACHE): StakingBalance {
|
||||
return StakingBalanceConverter(isCached = source == StatusSource.CACHE).convert(this)!!
|
||||
}
|
||||
|
||||
internal fun P2PEthPoolAccountResponse.toDomain(
|
||||
vault: P2PEthPoolVault = MockP2PEthPoolAccountResponseFactory.createMockVault(vaultAddress = vaultAddress),
|
||||
source: StatusSource = StatusSource.CACHE,
|
||||
): YieldBalance {
|
||||
val account = P2PEthPoolAccountConverter.convert(this)
|
||||
return P2PYieldBalanceConverter.convert(
|
||||
account = account,
|
||||
vault = vault,
|
||||
address = account.delegatorAddress,
|
||||
internal fun P2PEthPoolAccountResponse.toDomain(source: StatusSource = StatusSource.CACHE): StakingBalance.Data.P2P {
|
||||
return P2PStakingBalanceConverter.convert(
|
||||
response = this,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory
|
|||
import com.tangem.common.test.data.staking.MockYieldDTOFactory
|
||||
import com.tangem.common.test.domain.wallet.MockUserWalletFactory
|
||||
import com.tangem.data.staking.store.P2PBalancesStore
|
||||
import com.tangem.data.staking.store.YieldsBalancesStore
|
||||
import com.tangem.data.staking.store.StakingBalancesStore
|
||||
import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory
|
||||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.common.response.ApiResponseError
|
||||
|
|
@ -17,7 +17,7 @@ import com.tangem.datasource.local.token.StakingYieldsStore
|
|||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.test.core.assertEitherLeft
|
||||
import com.tangem.test.core.assertEitherRight
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
|
|
@ -31,20 +31,20 @@ import org.junit.jupiter.api.TestInstance
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class DefaultMultiYieldBalanceFetcherTest {
|
||||
internal class DefaultMultiStakingBalanceFetcherTest {
|
||||
|
||||
private val userWalletsStore: UserWalletsStore = mockk()
|
||||
private val stakingYieldsStore: StakingYieldsStore = mockk()
|
||||
private val yieldsBalancesStore: YieldsBalancesStore = mockk(relaxUnitFun = true)
|
||||
private val stakingBalancesStore: StakingBalancesStore = mockk(relaxUnitFun = true)
|
||||
private val p2pBalancesStore: P2PBalancesStore = mockk(relaxUnitFun = true)
|
||||
private val stakeKitApi: StakeKitApi = mockk()
|
||||
private val p2pApi: P2PEthPoolApi = mockk()
|
||||
private val p2pVaultsStore: P2PEthPoolVaultsStore = mockk()
|
||||
|
||||
private val fetcher = DefaultMultiYieldBalanceFetcher(
|
||||
private val fetcher = DefaultMultiStakingBalanceFetcher(
|
||||
userWalletsStore = userWalletsStore,
|
||||
stakingYieldsStore = stakingYieldsStore,
|
||||
yieldsBalancesStore = yieldsBalancesStore,
|
||||
stakingBalancesStore = stakingBalancesStore,
|
||||
p2pBalancesStore = p2pBalancesStore,
|
||||
stakeKitApi = stakeKitApi,
|
||||
p2pApi = p2pApi,
|
||||
|
|
@ -54,13 +54,13 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(userWalletsStore, stakingYieldsStore, yieldsBalancesStore, stakeKitApi)
|
||||
clearMocks(userWalletsStore, stakingYieldsStore, stakingBalancesStore, stakeKitApi)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yields balances successfully`() = runTest {
|
||||
fun `fetch staking balances successfully`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
val params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
|
||||
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
|
||||
|
||||
|
|
@ -81,21 +81,21 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
// Assert
|
||||
coVerifyOrder {
|
||||
userWalletsStore.getSyncOrNull(params.userWalletId)
|
||||
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingYieldsStore.getSyncWithTimeout()
|
||||
stakeKitApi.getMultipleYieldBalances(requests)
|
||||
yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = result)
|
||||
stakingBalancesStore.storeActual(userWalletId = userWalletId, values = result)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) { yieldsBalancesStore.storeError(any(), any()) }
|
||||
coVerify(inverse = true) { stakingBalancesStore.storeError(any(), any()) }
|
||||
|
||||
assertEitherRight(actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yields balances successfully if one of stakingIds is unavailable`() = runTest {
|
||||
fun `fetch staking balances successfully if one of stakingIds is unavailable`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
val params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
|
||||
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
|
||||
|
||||
|
|
@ -113,20 +113,20 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
// Assert
|
||||
coVerifyOrder {
|
||||
userWalletsStore.getSyncOrNull(params.userWalletId)
|
||||
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingYieldsStore.getSyncWithTimeout()
|
||||
yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = setOf(solanaId))
|
||||
stakingBalancesStore.storeError(userWalletId = userWalletId, stakingIds = setOf(solanaId))
|
||||
stakeKitApi.getMultipleYieldBalances(requests)
|
||||
yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = result)
|
||||
stakingBalancesStore.storeActual(userWalletId = userWalletId, values = result)
|
||||
}
|
||||
|
||||
assertEitherRight(actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yields balances failure if user wallet is not supported`() = runTest {
|
||||
fun `fetch staking balances failure if user wallet is not supported`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
val params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
|
||||
val userWallet = MockUserWalletFactory.create().copy(isMultiCurrency = false)
|
||||
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
|
||||
|
|
@ -138,11 +138,11 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
coVerifyOrder { userWalletsStore.getSyncOrNull(params.userWalletId) }
|
||||
|
||||
coVerify(inverse = true) {
|
||||
yieldsBalancesStore.refresh(userWalletId = any(), stakingIds = any())
|
||||
stakingBalancesStore.refresh(userWalletId = any(), stakingIds = any())
|
||||
stakingYieldsStore.getSyncWithTimeout()
|
||||
stakeKitApi.getSingleYieldBalance(integrationId = any(), body = any())
|
||||
yieldsBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
yieldsBalancesStore.storeError(userWalletId = any(), stakingIds = any())
|
||||
stakingBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
stakingBalancesStore.storeError(userWalletId = any(), stakingIds = any())
|
||||
}
|
||||
|
||||
val expected = IllegalStateException("Wallet ${params.userWalletId} is not supported: ${userWallet.toOption()}")
|
||||
|
|
@ -151,9 +151,9 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yields balances failure if userWalletsStore returns null`() = runTest {
|
||||
fun `fetch staking balances failure if userWalletsStore returns null`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
val params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
|
||||
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns null
|
||||
|
||||
|
|
@ -164,11 +164,11 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
coVerifyOrder { userWalletsStore.getSyncOrNull(params.userWalletId) }
|
||||
|
||||
coVerify(inverse = true) {
|
||||
yieldsBalancesStore.refresh(userWalletId = any(), stakingIds = any())
|
||||
stakingBalancesStore.refresh(userWalletId = any(), stakingIds = any())
|
||||
stakingYieldsStore.getSyncWithTimeout()
|
||||
stakeKitApi.getSingleYieldBalance(integrationId = any(), body = any())
|
||||
yieldsBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
yieldsBalancesStore.storeError(userWalletId = any(), stakingIds = any())
|
||||
stakingBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
stakingBalancesStore.storeError(userWalletId = any(), stakingIds = any())
|
||||
}
|
||||
|
||||
val expected = IllegalStateException("Wallet ${params.userWalletId} is not supported: ${null.toOption()}")
|
||||
|
|
@ -177,9 +177,9 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yields balances failure if stakingYieldsStore getSyncWithTimeout returns null`() = runTest {
|
||||
fun `fetch staking balances failure if stakingYieldsStore getSyncWithTimeout returns null`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
val params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
|
||||
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
|
||||
coEvery { stakingYieldsStore.getSyncWithTimeout() } returns null
|
||||
|
|
@ -190,14 +190,14 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
// Assert
|
||||
coVerifyOrder {
|
||||
userWalletsStore.getSyncOrNull(params.userWalletId)
|
||||
yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds)
|
||||
stakingBalancesStore.refresh(params.userWalletId, tonAndSolanaIds)
|
||||
stakingYieldsStore.getSyncWithTimeout()
|
||||
yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds)
|
||||
stakingBalancesStore.storeError(userWalletId, tonAndSolanaIds)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
stakeKitApi.getMultipleYieldBalances(any())
|
||||
yieldsBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
stakingBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
}
|
||||
|
||||
val expected = IllegalStateException("No enabled yields for ${params.userWalletId}")
|
||||
|
|
@ -206,9 +206,9 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yields balances failure if stakingYieldsStore getSyncWithTimeout returns empty list`() = runTest {
|
||||
fun `fetch staking balances failure if stakingYieldsStore getSyncWithTimeout returns empty list`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
val params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
|
||||
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
|
||||
coEvery { stakingYieldsStore.getSyncWithTimeout() } returns emptyList()
|
||||
|
|
@ -219,14 +219,14 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
// Assert
|
||||
coVerifyOrder {
|
||||
userWalletsStore.getSyncOrNull(params.userWalletId)
|
||||
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingYieldsStore.getSyncWithTimeout()
|
||||
yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds)
|
||||
stakingBalancesStore.storeError(userWalletId, tonAndSolanaIds)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
stakeKitApi.getMultipleYieldBalances(any())
|
||||
yieldsBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
stakingBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
}
|
||||
|
||||
val expected = IllegalStateException("No enabled yields for ${params.userWalletId}")
|
||||
|
|
@ -235,9 +235,9 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yields balances failure if yields converting is failed`() = runTest {
|
||||
fun `fetch staking balances failure if yields converting is failed`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
val params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
|
||||
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
|
||||
|
||||
|
|
@ -253,14 +253,14 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
// Assert
|
||||
coVerifyOrder {
|
||||
userWalletsStore.getSyncOrNull(params.userWalletId)
|
||||
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingYieldsStore.getSyncWithTimeout()
|
||||
yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds)
|
||||
stakingBalancesStore.storeError(userWalletId, tonAndSolanaIds)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
stakeKitApi.getMultipleYieldBalances(any())
|
||||
yieldsBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
stakingBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
}
|
||||
|
||||
val expected = IllegalStateException("No enabled yields for ${params.userWalletId}")
|
||||
|
|
@ -269,9 +269,9 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yields balances failure if available yields does not contain ids from params`() = runTest {
|
||||
fun `fetch staking balances failure if available yields does not contain ids from params`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
val params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
|
||||
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
|
||||
|
||||
|
|
@ -284,14 +284,14 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
// Assert
|
||||
coVerifyOrder {
|
||||
userWalletsStore.getSyncOrNull(params.userWalletId)
|
||||
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingYieldsStore.getSyncWithTimeout()
|
||||
yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds)
|
||||
stakingBalancesStore.storeError(userWalletId, tonAndSolanaIds)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
stakeKitApi.getMultipleYieldBalances(any())
|
||||
yieldsBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
stakingBalancesStore.storeActual(userWalletId = any(), values = any())
|
||||
}
|
||||
|
||||
val expected = IllegalStateException(
|
||||
|
|
@ -306,9 +306,9 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yields balances failure if stakeKitApi getMultipleYieldBalances is failed`() = runTest {
|
||||
fun `fetch staking balances failure if stakeKitApi getMultipleYieldBalances is failed`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
val params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
|
||||
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
|
||||
|
||||
|
|
@ -329,13 +329,13 @@ internal class DefaultMultiYieldBalanceFetcherTest {
|
|||
// Assert
|
||||
coVerifyOrder {
|
||||
userWalletsStore.getSyncOrNull(params.userWalletId)
|
||||
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingYieldsStore.getSyncWithTimeout()
|
||||
stakeKitApi.getMultipleYieldBalances(requests)
|
||||
yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
stakingBalancesStore.storeError(userWalletId = userWalletId, stakingIds = tonAndSolanaIds)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) { yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) }
|
||||
coVerify(inverse = true) { stakingBalancesStore.storeActual(userWalletId = any(), values = any()) }
|
||||
|
||||
val expected = ApiResponseError.NetworkException()
|
||||
|
||||
|
|
@ -4,12 +4,13 @@ import com.google.common.truth.Truth
|
|||
import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory
|
||||
import com.tangem.common.test.data.staking.MockP2PEthPoolAccountResponseFactory
|
||||
import com.tangem.data.staking.store.P2PBalancesStore
|
||||
import com.tangem.data.staking.store.YieldsBalancesStore
|
||||
import com.tangem.data.staking.store.StakingBalancesStore
|
||||
import com.tangem.data.staking.toDomain
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.staking.*
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceProducer
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceProducer
|
||||
import com.tangem.test.core.getEmittedValues
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.every
|
||||
|
|
@ -22,17 +23,17 @@ import org.junit.Test
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultMultiYieldBalanceProducerTest {
|
||||
internal class DefaultMultiStakingBalanceProducerTest {
|
||||
|
||||
private val params = MultiYieldBalanceProducer.Params(userWalletId = UserWalletId("011"))
|
||||
private val params = MultiStakingBalanceProducer.Params(userWalletId = UserWalletId("011"))
|
||||
|
||||
private val yieldsBalancesStore = mockk<YieldsBalancesStore>()
|
||||
private val stakingBalancesStore = mockk<StakingBalancesStore>()
|
||||
private val p2pBalancesStore = mockk<P2PBalancesStore>()
|
||||
private val dispatchers = TestingCoroutineDispatcherProvider()
|
||||
|
||||
private val producer = DefaultMultiYieldBalanceProducer(
|
||||
private val producer = DefaultMultiStakingBalanceProducer(
|
||||
params = params,
|
||||
yieldsBalancesStore = yieldsBalancesStore,
|
||||
stakingBalancesStore = stakingBalancesStore,
|
||||
p2pBalancesStore = p2pBalancesStore,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
|
|
@ -46,13 +47,13 @@ internal class DefaultMultiYieldBalanceProducerTest {
|
|||
|
||||
val networksStatusesFlow = flowOf(balances)
|
||||
|
||||
every { yieldsBalancesStore.get(params.userWalletId) } returns networksStatusesFlow
|
||||
every { stakingBalancesStore.get(params.userWalletId) } returns networksStatusesFlow
|
||||
every { p2pBalancesStore.get(params.userWalletId) } returns flowOf(emptySet())
|
||||
|
||||
val actual = producer.produce()
|
||||
|
||||
// check after producer.produce()
|
||||
verify { yieldsBalancesStore.get(params.userWalletId) }
|
||||
verify { stakingBalancesStore.get(params.userWalletId) }
|
||||
verify { p2pBalancesStore.get(params.userWalletId) }
|
||||
|
||||
val values = getEmittedValues(flow = actual)
|
||||
|
|
@ -63,15 +64,15 @@ internal class DefaultMultiYieldBalanceProducerTest {
|
|||
|
||||
@Test
|
||||
fun `test that flow is updated if balances are updated`() = runTest {
|
||||
val networksStatusesFlow = MutableSharedFlow<Set<YieldBalance>>(replay = 2)
|
||||
val networksStatusesFlow = MutableSharedFlow<Set<StakingBalance>>(replay = 2)
|
||||
|
||||
every { yieldsBalancesStore.get(params.userWalletId) } returns networksStatusesFlow
|
||||
every { stakingBalancesStore.get(params.userWalletId) } returns networksStatusesFlow
|
||||
every { p2pBalancesStore.get(params.userWalletId) } returns flowOf(emptySet())
|
||||
|
||||
val actual = producer.produce()
|
||||
|
||||
// check after producer.produce()
|
||||
verify { yieldsBalancesStore.get(params.userWalletId) }
|
||||
verify { stakingBalancesStore.get(params.userWalletId) }
|
||||
verify { p2pBalancesStore.get(params.userWalletId) }
|
||||
|
||||
// first emit
|
||||
|
|
@ -104,15 +105,15 @@ internal class DefaultMultiYieldBalanceProducerTest {
|
|||
|
||||
@Test
|
||||
fun `test that flow is filtered the same balance`() = runTest {
|
||||
val networksStatusesFlow = MutableSharedFlow<Set<YieldBalance>>(replay = 2)
|
||||
val networksStatusesFlow = MutableSharedFlow<Set<StakingBalance>>(replay = 2)
|
||||
|
||||
every { yieldsBalancesStore.get(params.userWalletId) } returns networksStatusesFlow
|
||||
every { stakingBalancesStore.get(params.userWalletId) } returns networksStatusesFlow
|
||||
every { p2pBalancesStore.get(params.userWalletId) } returns flowOf(emptySet())
|
||||
|
||||
val actual = producer.produce()
|
||||
|
||||
// check after producer.produce()
|
||||
verify { yieldsBalancesStore.get(params.userWalletId) }
|
||||
verify { stakingBalancesStore.get(params.userWalletId) }
|
||||
verify { p2pBalancesStore.get(params.userWalletId) }
|
||||
|
||||
// first emit
|
||||
|
|
@ -155,19 +156,19 @@ internal class DefaultMultiYieldBalanceProducerTest {
|
|||
}
|
||||
.buffer(capacity = 5)
|
||||
|
||||
every { yieldsBalancesStore.get(params.userWalletId) } returns networksStatusesFlow
|
||||
every { stakingBalancesStore.get(params.userWalletId) } returns networksStatusesFlow
|
||||
every { p2pBalancesStore.get(params.userWalletId) } returns flowOf(emptySet())
|
||||
|
||||
val actual = producer.produceWithFallback()
|
||||
|
||||
// check after producer.produce()
|
||||
verify { yieldsBalancesStore.get(params.userWalletId) }
|
||||
verify { stakingBalancesStore.get(params.userWalletId) }
|
||||
verify { p2pBalancesStore.get(params.userWalletId) }
|
||||
|
||||
val values1 = getEmittedValues(flow = actual)
|
||||
|
||||
Truth.assertThat(values1.size).isEqualTo(1)
|
||||
Truth.assertThat(values1).isEqualTo(listOf(emptySet<YieldBalance>()))
|
||||
Truth.assertThat(values1).isEqualTo(listOf(emptySet<StakingBalance>()))
|
||||
|
||||
innerFlow.emit(value = true)
|
||||
|
||||
|
|
@ -179,19 +180,19 @@ internal class DefaultMultiYieldBalanceProducerTest {
|
|||
|
||||
@Test
|
||||
fun `test that flow is empty`() = runTest {
|
||||
every { yieldsBalancesStore.get(params.userWalletId) } returns emptyFlow()
|
||||
every { stakingBalancesStore.get(params.userWalletId) } returns emptyFlow()
|
||||
every { p2pBalancesStore.get(params.userWalletId) } returns emptyFlow()
|
||||
|
||||
val actual = producer.produce()
|
||||
|
||||
// check after producer.produce()
|
||||
verify { yieldsBalancesStore.get(params.userWalletId) }
|
||||
verify { stakingBalancesStore.get(params.userWalletId) }
|
||||
verify { p2pBalancesStore.get(params.userWalletId) }
|
||||
|
||||
val values = getEmittedValues(flow = actual)
|
||||
|
||||
Truth.assertThat(values.size).isEqualTo(1)
|
||||
Truth.assertThat(values).isEqualTo(listOf(emptySet<YieldBalance>()))
|
||||
Truth.assertThat(values).isEqualTo(listOf(emptySet<StakingBalance>()))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -199,13 +200,13 @@ internal class DefaultMultiYieldBalanceProducerTest {
|
|||
val stakeKitBalances = createStakeKitBalances()
|
||||
val p2pBalances = createP2PBalances()
|
||||
|
||||
every { yieldsBalancesStore.get(params.userWalletId) } returns flowOf(stakeKitBalances)
|
||||
every { stakingBalancesStore.get(params.userWalletId) } returns flowOf(stakeKitBalances)
|
||||
every { p2pBalancesStore.get(params.userWalletId) } returns flowOf(p2pBalances)
|
||||
|
||||
val actual = producer.produce()
|
||||
|
||||
// check after producer.produce()
|
||||
verify { yieldsBalancesStore.get(params.userWalletId) }
|
||||
verify { stakingBalancesStore.get(params.userWalletId) }
|
||||
verify { p2pBalancesStore.get(params.userWalletId) }
|
||||
|
||||
val values = getEmittedValues(flow = actual)
|
||||
|
|
@ -217,15 +218,15 @@ internal class DefaultMultiYieldBalanceProducerTest {
|
|||
@Test
|
||||
fun `test that P2P balances are updated independently from StakeKit`() = runTest {
|
||||
val stakeKitBalances = createStakeKitBalancesWithTonOnly()
|
||||
val p2pFlow = MutableSharedFlow<Set<YieldBalance>>(replay = 2)
|
||||
val p2pFlow = MutableSharedFlow<Set<StakingBalance>>(replay = 2)
|
||||
|
||||
every { yieldsBalancesStore.get(params.userWalletId) } returns flowOf(stakeKitBalances)
|
||||
every { stakingBalancesStore.get(params.userWalletId) } returns flowOf(stakeKitBalances)
|
||||
every { p2pBalancesStore.get(params.userWalletId) } returns p2pFlow
|
||||
|
||||
val actual = producer.produce()
|
||||
|
||||
// check after producer.produce()
|
||||
verify { yieldsBalancesStore.get(params.userWalletId) }
|
||||
verify { stakingBalancesStore.get(params.userWalletId) }
|
||||
verify { p2pBalancesStore.get(params.userWalletId) }
|
||||
|
||||
// first emit - empty P2P
|
||||
|
|
@ -254,24 +255,24 @@ internal class DefaultMultiYieldBalanceProducerTest {
|
|||
address = "0x1",
|
||||
)
|
||||
val p2pEthereumId = StakingID(
|
||||
integrationId = "p2p-ethereum-pooled",
|
||||
integrationId = StakingIntegrationID.P2P.EthereumPooled.value,
|
||||
address = "0x5aa711F440Eb6d4361148bBD89d03464628ace84",
|
||||
)
|
||||
|
||||
fun createStakeKitBalances(): Set<YieldBalance> {
|
||||
fun createStakeKitBalances(): Set<StakingBalance> {
|
||||
return setOf(
|
||||
MockYieldBalanceWrapperDTOFactory.createWithBalance(tonId).toDomain(),
|
||||
MockYieldBalanceWrapperDTOFactory.createWithBalance(solanaId).toDomain(),
|
||||
)
|
||||
}
|
||||
|
||||
fun createStakeKitBalancesWithTonOnly(): Set<YieldBalance> {
|
||||
fun createStakeKitBalancesWithTonOnly(): Set<StakingBalance> {
|
||||
return setOf(
|
||||
MockYieldBalanceWrapperDTOFactory.createWithBalance(tonId).toDomain(),
|
||||
)
|
||||
}
|
||||
|
||||
fun createP2PBalances(): Set<YieldBalance> {
|
||||
fun createP2PBalances(): Set<StakingBalance> {
|
||||
return setOf(
|
||||
MockP2PEthPoolAccountResponseFactory.createWithBalance(stakingId = p2pEthereumId).toDomain(
|
||||
source = StatusSource.ACTUAL,
|
||||
|
|
@ -5,8 +5,8 @@ import arrow.core.right
|
|||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceFetcher
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
|
|
@ -20,32 +20,32 @@ import org.junit.jupiter.api.TestInstance
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class DefaultSingleYieldBalanceFetcherTest {
|
||||
internal class DefaultSingleStakingBalanceFetcherTest {
|
||||
|
||||
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher = mockk()
|
||||
private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher = mockk()
|
||||
|
||||
private val fetcher = DefaultSingleYieldBalanceFetcher(
|
||||
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
|
||||
private val fetcher = DefaultSingleStakingBalanceFetcher(
|
||||
multiStakingBalanceFetcher = multiStakingBalanceFetcher,
|
||||
)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(multiYieldBalanceFetcher)
|
||||
clearMocks(multiStakingBalanceFetcher)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yield balance successfully`() = runTest {
|
||||
fun `fetch staking balance successfully`() = runTest {
|
||||
// Arrange
|
||||
val params = SingleYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingId = tonId)
|
||||
val params = SingleStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingId = tonId)
|
||||
|
||||
val multiParams = MultiYieldBalanceFetcher.Params(
|
||||
val multiParams = MultiStakingBalanceFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
stakingIds = setOf(tonId),
|
||||
)
|
||||
|
||||
val multiResult = Unit.right()
|
||||
|
||||
coEvery { multiYieldBalanceFetcher(params = multiParams) } returns multiResult
|
||||
coEvery { multiStakingBalanceFetcher(params = multiParams) } returns multiResult
|
||||
|
||||
// Act
|
||||
val actual = fetcher.invoke(params).isRight()
|
||||
|
|
@ -53,26 +53,26 @@ internal class DefaultSingleYieldBalanceFetcherTest {
|
|||
// Assert
|
||||
Truth.assertThat(actual).isTrue()
|
||||
|
||||
coVerify { multiYieldBalanceFetcher(params = multiParams) }
|
||||
coVerify { multiStakingBalanceFetcher(params = multiParams) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch yield balance failure`() = runTest {
|
||||
fun `fetch staking balance failure`() = runTest {
|
||||
// Arrange
|
||||
val params = SingleYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingId = tonId)
|
||||
val params = SingleStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingId = tonId)
|
||||
|
||||
val multiParams = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = setOf(tonId))
|
||||
val multiParams = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = setOf(tonId))
|
||||
|
||||
val multiResult = IllegalStateException().left()
|
||||
|
||||
coEvery { multiYieldBalanceFetcher(params = multiParams) } returns multiResult
|
||||
coEvery { multiStakingBalanceFetcher(params = multiParams) } returns multiResult
|
||||
|
||||
// Act
|
||||
val actual = fetcher.invoke(params)
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isEqualTo(multiResult)
|
||||
coVerify { multiYieldBalanceFetcher(params = multiParams) }
|
||||
coVerify { multiStakingBalanceFetcher(params = multiParams) }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
|
@ -4,12 +4,12 @@ import com.google.common.truth.Truth
|
|||
import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory
|
||||
import com.tangem.core.analytics.api.AnalyticsExceptionHandler
|
||||
import com.tangem.data.staking.toDomain
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceProducer
|
||||
import com.tangem.test.core.getEmittedValues
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.clearMocks
|
||||
|
|
@ -26,20 +26,20 @@ import org.junit.jupiter.api.TestInstance
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class DefaultSingleYieldBalanceProducerTest {
|
||||
internal class DefaultSingleStakingBalanceProducerTest {
|
||||
|
||||
private val params = SingleYieldBalanceProducer.Params(
|
||||
private val params = SingleStakingBalanceProducer.Params(
|
||||
userWalletId = UserWalletId(stringValue = "011"),
|
||||
stakingId = tonId,
|
||||
)
|
||||
|
||||
private val multiNetworkStatusSupplier = mockk<MultiYieldBalanceSupplier>()
|
||||
private val multiNetworkStatusSupplier = mockk<MultiStakingBalanceSupplier>()
|
||||
private val analyticsExceptionHandler = mockk<AnalyticsExceptionHandler>(relaxUnitFun = true)
|
||||
private val dispatchers = TestingCoroutineDispatcherProvider()
|
||||
|
||||
private val producer = DefaultSingleYieldBalanceProducer(
|
||||
private val producer = DefaultSingleStakingBalanceProducer(
|
||||
params = params,
|
||||
multiYieldBalanceSupplier = multiNetworkStatusSupplier,
|
||||
multiStakingBalanceSupplier = multiNetworkStatusSupplier,
|
||||
analyticsExceptionHandler = analyticsExceptionHandler,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
|
|
@ -61,7 +61,7 @@ internal class DefaultSingleYieldBalanceProducerTest {
|
|||
),
|
||||
)
|
||||
|
||||
val multiParams = MultiYieldBalanceProducer.Params(userWalletId = params.userWalletId)
|
||||
val multiParams = MultiStakingBalanceProducer.Params(userWalletId = params.userWalletId)
|
||||
every { multiNetworkStatusSupplier(multiParams) } returns multiFlow
|
||||
|
||||
// Act
|
||||
|
|
@ -74,17 +74,17 @@ internal class DefaultSingleYieldBalanceProducerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `flow is updated if yield balance is updated`() = runTest {
|
||||
fun `flow is updated if staking balance is updated`() = runTest {
|
||||
// Arrange
|
||||
val multiFlow = MutableSharedFlow<Set<YieldBalance>>(replay = 2, extraBufferCapacity = 1)
|
||||
val multiFlow = MutableSharedFlow<Set<StakingBalance>>(replay = 2, extraBufferCapacity = 1)
|
||||
|
||||
val multiParams = MultiYieldBalanceProducer.Params(userWalletId = params.userWalletId)
|
||||
val multiParams = MultiStakingBalanceProducer.Params(userWalletId = params.userWalletId)
|
||||
every { multiNetworkStatusSupplier(multiParams) } returns multiFlow
|
||||
|
||||
val producerFlow = producer.produceWithFallback()
|
||||
|
||||
val balance = MockYieldBalanceWrapperDTOFactory.createWithBalance(tonId).toDomain()
|
||||
val updatedBalance = YieldBalance.Error(stakingId = tonId)
|
||||
val updatedBalance = StakingBalance.Error(stakingId = tonId)
|
||||
|
||||
// Act (first emit)
|
||||
multiFlow.emit(value = setOf(balance))
|
||||
|
|
@ -108,9 +108,9 @@ internal class DefaultSingleYieldBalanceProducerTest {
|
|||
@Test
|
||||
fun `flow is filtered the same status`() = runTest {
|
||||
// Arrange
|
||||
val multiFlow = MutableSharedFlow<Set<YieldBalance>>(replay = 2, extraBufferCapacity = 1)
|
||||
val multiFlow = MutableSharedFlow<Set<StakingBalance>>(replay = 2, extraBufferCapacity = 1)
|
||||
|
||||
val multiParams = MultiYieldBalanceProducer.Params(userWalletId = params.userWalletId)
|
||||
val multiParams = MultiStakingBalanceProducer.Params(userWalletId = params.userWalletId)
|
||||
every { multiNetworkStatusSupplier(multiParams) } returns multiFlow
|
||||
|
||||
val producerFlow = producer.produceWithFallback()
|
||||
|
|
@ -153,7 +153,7 @@ internal class DefaultSingleYieldBalanceProducerTest {
|
|||
}
|
||||
.buffer(capacity = 5)
|
||||
|
||||
val multiParams = MultiYieldBalanceProducer.Params(userWalletId = params.userWalletId)
|
||||
val multiParams = MultiStakingBalanceProducer.Params(userWalletId = params.userWalletId)
|
||||
every { multiNetworkStatusSupplier(multiParams) } returns multiFlow
|
||||
|
||||
val producerFlow = producer.produceWithFallback()
|
||||
|
|
@ -162,7 +162,7 @@ internal class DefaultSingleYieldBalanceProducerTest {
|
|||
val actual1 = getEmittedValues(flow = producerFlow)
|
||||
|
||||
// Assert (first emit)
|
||||
val fallbackStatus = YieldBalance.Error(stakingId = tonId.copy(address = "0x1"))
|
||||
val fallbackStatus = StakingBalance.Error(stakingId = tonId.copy(address = "0x1"))
|
||||
|
||||
Truth.assertThat(actual1).hasSize(1)
|
||||
Truth.assertThat(actual1).containsExactly(fallbackStatus)
|
||||
|
|
@ -184,7 +184,7 @@ internal class DefaultSingleYieldBalanceProducerTest {
|
|||
|
||||
val multiFlow = flowOf(setOf(balance))
|
||||
|
||||
val multiParams = MultiYieldBalanceProducer.Params(userWalletId = params.userWalletId)
|
||||
val multiParams = MultiStakingBalanceProducer.Params(userWalletId = params.userWalletId)
|
||||
every { multiNetworkStatusSupplier(multiParams) } returns multiFlow
|
||||
|
||||
val producerFlow = producer.produce()
|
||||
|
|
@ -5,7 +5,7 @@ import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory
|
|||
import com.tangem.common.test.datastore.MockStateDataStore
|
||||
import com.tangem.data.staking.toDomain
|
||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.test.core.getEmittedValues
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
|
|
@ -15,12 +15,12 @@ import org.junit.Test
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class YieldsBalancesStoreGetMethodTest {
|
||||
internal class StakingBalancesStoreGetMethodTest {
|
||||
|
||||
private val runtimeStore = RuntimeSharedStore<WalletIdWithBalances>()
|
||||
private val runtimeStore = RuntimeSharedStore<WalletIdWithStakingBalances>()
|
||||
private val persistenceStore = MockStateDataStore<WalletIdWithWrappers>(default = emptyMap())
|
||||
|
||||
private val store = DefaultYieldsBalancesStore(
|
||||
private val store = DefaultStakingBalancesStore(
|
||||
runtimeStore = runtimeStore,
|
||||
persistenceStore = persistenceStore,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
|
|
@ -32,7 +32,7 @@ internal class YieldsBalancesStoreGetMethodTest {
|
|||
|
||||
val values = getEmittedValues(flow = actual)
|
||||
|
||||
val expected = listOf(emptySet<YieldBalance>())
|
||||
val expected = listOf(emptySet<StakingBalance>())
|
||||
Truth.assertThat(values).isEqualTo(expected)
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ internal class YieldsBalancesStoreGetMethodTest {
|
|||
|
||||
val values = getEmittedValues(flow = actual)
|
||||
|
||||
val expected = listOf(emptySet<YieldBalance>())
|
||||
val expected = listOf(emptySet<StakingBalance>())
|
||||
Truth.assertThat(values).isEqualTo(expected)
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ internal class YieldsBalancesStoreGetMethodTest {
|
|||
val values = getEmittedValues(flow = actual)
|
||||
|
||||
Truth.assertThat(values.size).isEqualTo(1)
|
||||
Truth.assertThat(values).isEqualTo(listOf(emptySet<YieldBalance>()))
|
||||
Truth.assertThat(values).isEqualTo(listOf(emptySet<StakingBalance>()))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -6,7 +6,7 @@ import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory
|
|||
import com.tangem.common.test.datastore.MockStateDataStore
|
||||
import com.tangem.data.staking.toDomain
|
||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.every
|
||||
|
|
@ -18,16 +18,16 @@ import org.junit.Test
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class YieldsBalancesStoreInitializationTest {
|
||||
internal class StakingBalancesStoreInitializationTest {
|
||||
|
||||
@Test
|
||||
fun `test initialization if cache store is empty`() = runTest {
|
||||
val runtimeStore = RuntimeSharedStore<WalletIdWithBalances>()
|
||||
val runtimeStore = RuntimeSharedStore<WalletIdWithStakingBalances>()
|
||||
val persistenceStore: DataStore<WalletIdWithWrappers> = mockk()
|
||||
|
||||
every { persistenceStore.data } returns emptyFlow()
|
||||
|
||||
DefaultYieldsBalancesStore(
|
||||
DefaultStakingBalancesStore(
|
||||
runtimeStore = runtimeStore,
|
||||
persistenceStore = persistenceStore,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
|
|
@ -38,21 +38,21 @@ internal class YieldsBalancesStoreInitializationTest {
|
|||
|
||||
@Test
|
||||
fun `test initialization if cache store contains empty map`() = runTest {
|
||||
val runtimeStore = RuntimeSharedStore<WalletIdWithBalances>()
|
||||
val runtimeStore = RuntimeSharedStore<WalletIdWithStakingBalances>()
|
||||
val persistenceStore = MockStateDataStore<WalletIdWithWrappers>(default = emptyMap())
|
||||
|
||||
DefaultYieldsBalancesStore(
|
||||
DefaultStakingBalancesStore(
|
||||
runtimeStore = runtimeStore,
|
||||
persistenceStore = persistenceStore,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
||||
Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(emptyMap<String, Set<YieldBalance>>())
|
||||
Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(emptyMap<String, Set<StakingBalance>>())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test initialization if cache store is not empty`() = runTest {
|
||||
val runtimeStore = RuntimeSharedStore<WalletIdWithBalances>()
|
||||
val runtimeStore = RuntimeSharedStore<WalletIdWithStakingBalances>()
|
||||
val persistenceStore = MockStateDataStore<WalletIdWithWrappers>(default = emptyMap())
|
||||
|
||||
val wrapper = MockYieldBalanceWrapperDTOFactory.createWithBalance()
|
||||
|
|
@ -63,7 +63,7 @@ internal class YieldsBalancesStoreInitializationTest {
|
|||
}
|
||||
}
|
||||
|
||||
DefaultYieldsBalancesStore(
|
||||
DefaultStakingBalancesStore(
|
||||
runtimeStore = runtimeStore,
|
||||
persistenceStore = persistenceStore,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
|
|
@ -7,8 +7,8 @@ import com.tangem.data.staking.toDomain
|
|||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
|
|
@ -18,12 +18,12 @@ import org.junit.Test
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class YieldsBalancesStoreUpdateMethodsTest {
|
||||
internal class StakingBalancesStoreUpdateMethodsTest {
|
||||
|
||||
private val runtimeStore = RuntimeSharedStore<WalletIdWithBalances>()
|
||||
private val runtimeStore = RuntimeSharedStore<WalletIdWithStakingBalances>()
|
||||
private val persistenceStore = MockStateDataStore<WalletIdWithWrappers>(default = emptyMap())
|
||||
|
||||
private val store = DefaultYieldsBalancesStore(
|
||||
private val store = DefaultStakingBalancesStore(
|
||||
runtimeStore = runtimeStore,
|
||||
persistenceStore = persistenceStore,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
|
|
@ -33,7 +33,7 @@ internal class YieldsBalancesStoreUpdateMethodsTest {
|
|||
fun `refresh the single id if runtime store is empty`() = runTest {
|
||||
store.refresh(userWalletId = userWalletId, stakingId = stakingId)
|
||||
|
||||
val runtimeExpected = mapOf(userWalletId to emptySet<YieldBalance>())
|
||||
val runtimeExpected = mapOf(userWalletId to emptySet<StakingBalance>())
|
||||
|
||||
Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected)
|
||||
Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(emptyMap<String, Set<YieldBalanceWrapperDTO>>())
|
||||
|
|
@ -63,7 +63,7 @@ internal class YieldsBalancesStoreUpdateMethodsTest {
|
|||
fun `refresh the multi ids if runtime store is empty`() = runTest {
|
||||
store.refresh(userWalletId = userWalletId, stakingIds = stakingIds)
|
||||
|
||||
val runtimeExpected = mapOf(userWalletId to emptySet<YieldBalance>())
|
||||
val runtimeExpected = mapOf(userWalletId to emptySet<StakingBalance>())
|
||||
|
||||
Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected)
|
||||
Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(emptyMap<String, Set<YieldBalanceWrapperDTO>>())
|
||||
|
|
@ -129,7 +129,7 @@ internal class YieldsBalancesStoreUpdateMethodsTest {
|
|||
store.storeError(userWalletId = userWalletId, stakingIds = setOf(stakingId))
|
||||
|
||||
val runtimeExpected = mapOf(
|
||||
userWalletId to setOf(YieldBalance.Error(stakingId)),
|
||||
userWalletId to setOf(StakingBalance.Error(stakingId)),
|
||||
)
|
||||
|
||||
Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected)
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.data.staking.utils
|
||||
|
||||
import com.tangem.data.staking.store.YieldsBalancesStore
|
||||
import com.tangem.data.staking.store.StakingBalancesStore
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
|
|
@ -16,9 +16,9 @@ import org.junit.jupiter.api.TestInstance
|
|||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class DefaultStakingCleanerTest {
|
||||
|
||||
private val yieldsBalancesStore = mockk<YieldsBalancesStore>(relaxed = true)
|
||||
private val stakingBalancesStore = mockk<StakingBalancesStore>(relaxed = true)
|
||||
private val cleaner = DefaultStakingCleaner(
|
||||
yieldsBalancesStore = yieldsBalancesStore,
|
||||
stakingBalancesStore = stakingBalancesStore,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
private val userWalletId = UserWalletId("011")
|
||||
|
|
@ -28,7 +28,7 @@ class DefaultStakingCleanerTest {
|
|||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
clearMocks(yieldsBalancesStore)
|
||||
clearMocks(stakingBalancesStore)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -38,7 +38,7 @@ class DefaultStakingCleanerTest {
|
|||
|
||||
// Assert
|
||||
coVerifyOrder {
|
||||
yieldsBalancesStore.clear(userWalletId = userWalletId, stakingIds = stakingIds)
|
||||
stakingBalancesStore.clear(userWalletId = userWalletId, stakingIds = stakingIds)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ class DefaultStakingCleanerTest {
|
|||
|
||||
// Assert
|
||||
coVerifyOrder(inverse = true) {
|
||||
yieldsBalancesStore.clear(userWalletId = any(), stakingIds = any())
|
||||
stakingBalancesStore.clear(userWalletId = any(), stakingIds = any())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -403,7 +403,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
|
|||
value = NetworkStatus.MissedDerivation, // Caution!!! Do not change this status
|
||||
).some(),
|
||||
maybeQuoteStatus = quoteStatus.toOption(),
|
||||
maybeYieldBalance = none(),
|
||||
maybeStakingBalance = none(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import com.tangem.data.tokens.converters.UtxoConverter
|
|||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.staking.utils.getTotalStakingBalance
|
||||
import com.tangem.domain.tokens.model.CurrencyAmount
|
||||
|
|
@ -136,7 +136,7 @@ internal class DefaultCurrencyChecksRepository(
|
|||
|
||||
val rentData = walletManagersFacade.getRentInfo(userWalletId, currencyStatus.currency.network) ?: return null
|
||||
val balanceValue = currencyStatus.value as? CryptoCurrencyStatus.Loaded ?: return null
|
||||
val stakingBalance = balanceValue.yieldBalance as? YieldBalance.Data
|
||||
val stakingBalance = balanceValue.stakingBalance as? StakingBalance.Data
|
||||
val stakingTotalBalance = stakingBalance?.getTotalStakingBalance(
|
||||
blockchainId = currencyStatus.currency.network.rawId,
|
||||
).orZero()
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ internal class DefaultGetTangemPayCurrencyStatusUseCase @Inject constructor(
|
|||
),
|
||||
sources = CryptoCurrencyStatus.Sources(),
|
||||
pendingTransactions = emptySet(),
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
==========================================
|
||||
Detekt Baseline Updater & Issue Counter
|
||||
==========================================
|
||||
Date: 2025-12-03 22:08:49
|
||||
Date: 2025-12-04 17:37:53
|
||||
|
||||
Step 1: Running detekt to check for new issues...
|
||||
|
||||
|
|
@ -17,13 +17,13 @@ Counting issues in baseline files...
|
|||
==========================================
|
||||
|
||||
Summary:
|
||||
Total Issues: 1385
|
||||
Total Issues: 1380
|
||||
Modules with Issues: 50
|
||||
Average Issues per Module: 27
|
||||
|
||||
Progress:
|
||||
Fixed: 417 out of 1802 (23%)
|
||||
Remaining: 1385
|
||||
Fixed: 422 out of 1802 (23%)
|
||||
Remaining: 1380
|
||||
|
||||
==========================================
|
||||
All Modules with Issues (sorted by count)
|
||||
|
|
@ -38,18 +38,18 @@ features/swap/impl 67
|
|||
features/send-v2/impl 57
|
||||
data/wallet-connect 55
|
||||
features/hot-wallet/impl 53
|
||||
features/tokendetails/impl 48
|
||||
features/staking/impl 48
|
||||
features/walletconnect/impl 47
|
||||
features/tokendetails/impl 46
|
||||
features/staking/impl 46
|
||||
features/manage-tokens/impl 45
|
||||
features/swap-v2/impl 40
|
||||
domain/wallets 37
|
||||
features/nft/impl 34
|
||||
features/tester/impl 30
|
||||
core/ui 27
|
||||
domain/tokens 26
|
||||
common/ui 26
|
||||
features/swap/domain 25
|
||||
domain/tokens 25
|
||||
data/visa 22
|
||||
features/yield-supply/impl 21
|
||||
features/tangempay/details/impl 21
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
|
|||
import com.tangem.domain.networks.utils.NetworksCleaner
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.staking.utils.StakingCleaner
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
|
|
@ -125,14 +125,14 @@ internal object AccountStatusUseCaseModule {
|
|||
fun provideCryptoCurrencyBalanceFetcher(
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): CryptoCurrencyBalanceFetcher {
|
||||
return CryptoCurrencyBalanceFetcher(
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher = multiStakingBalanceFetcher,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.wallet.FetchingSource
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
|
|
@ -19,7 +19,7 @@ import timber.log.Timber
|
|||
*
|
||||
* @property multiNetworkStatusFetcher Fetcher for updating network statuses.
|
||||
* @property multiQuoteStatusFetcher Fetcher for updating quote statuses.
|
||||
* @property multiYieldBalanceFetcher Fetcher for updating yield balances.
|
||||
* @property multiStakingBalanceFetcher Fetcher for updating staking balances.
|
||||
* @property stakingIdFactory Factory for creating staking IDs.
|
||||
* @property parallelUpdatingScope Coroutine scope for parallel balance updates.
|
||||
*
|
||||
|
|
@ -28,7 +28,7 @@ import timber.log.Timber
|
|||
class CryptoCurrencyBalanceFetcher(
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
private val parallelUpdatingScope: CoroutineScope,
|
||||
) {
|
||||
|
|
@ -52,7 +52,10 @@ class CryptoCurrencyBalanceFetcher(
|
|||
FetchingSource.NETWORK to refreshNetworks(userWalletId = userWalletId, currencies = currencies)
|
||||
},
|
||||
async {
|
||||
FetchingSource.STAKING to refreshYieldBalances(userWalletId = userWalletId, currencies = currencies)
|
||||
FetchingSource.STAKING to refreshStakingBalances(
|
||||
userWalletId = userWalletId,
|
||||
currencies = currencies,
|
||||
)
|
||||
},
|
||||
async { FetchingSource.QUOTE to refreshQuotes(currencies = currencies) },
|
||||
)
|
||||
|
|
@ -85,7 +88,7 @@ class CryptoCurrencyBalanceFetcher(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshYieldBalances(
|
||||
private suspend fun refreshStakingBalances(
|
||||
userWalletId: UserWalletId,
|
||||
currencies: List<CryptoCurrency>,
|
||||
): Either<Throwable, Unit> {
|
||||
|
|
@ -93,8 +96,8 @@ class CryptoCurrencyBalanceFetcher(
|
|||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it).getOrNull()
|
||||
}
|
||||
|
||||
return multiYieldBalanceFetcher(
|
||||
params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds),
|
||||
return multiStakingBalanceFetcher(
|
||||
params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.tangem.domain.models.network.Network
|
|||
import com.tangem.domain.models.network.NetworkStatus
|
||||
import com.tangem.domain.models.network.getAddress
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
|
|
@ -16,8 +16,8 @@ import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
|
|||
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceSupplier
|
||||
import com.tangem.domain.tokens.operations.CryptoCurrencyStatusFactory
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
|
@ -28,7 +28,7 @@ import javax.inject.Inject
|
|||
*
|
||||
* @property singleNetworkStatusSupplier Supplier for obtaining network status.
|
||||
* @property singleQuoteStatusSupplier Supplier for obtaining quote status.
|
||||
* @property singleYieldBalanceSupplier Supplier for obtaining yield balance.
|
||||
* @property singleStakingBalanceSupplier Supplier for obtaining staking balance.
|
||||
* @property stakingIdFactory Factory for creating staking IDs.
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -36,7 +36,7 @@ import javax.inject.Inject
|
|||
internal class CryptoCurrencyStatusesFlowFactory @Inject constructor(
|
||||
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
private val singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
|
||||
private val singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
|
||||
private val singleStakingBalanceSupplier: SingleStakingBalanceSupplier,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
) {
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ internal class CryptoCurrencyStatusesFlowFactory @Inject constructor(
|
|||
currency = currency,
|
||||
maybeNetworkStatus = statusSources.networkStatus.toOption(),
|
||||
maybeQuoteStatus = statusSources.quoteStatus.toOption(),
|
||||
maybeYieldBalance = statusSources.yieldBalance.toOption(),
|
||||
maybeStakingBalance = statusSources.stakingBalance.toOption(),
|
||||
)
|
||||
}
|
||||
.onEmpty {
|
||||
|
|
@ -71,10 +71,10 @@ internal class CryptoCurrencyStatusesFlowFactory @Inject constructor(
|
|||
): Flow<CryptoCurrencyStatusSources> {
|
||||
val networkStatusFlow = getNetworkStatusFlow(userWalletId = userWallet.walletId, network = currency.network)
|
||||
|
||||
val yieldBalanceFlow = if (userWallet.isMultiCurrency) {
|
||||
val stakingBalanceFlow = if (userWallet.isMultiCurrency) {
|
||||
networkStatusFlow.flatMapLatest { networkStatus ->
|
||||
if (networkStatus != null) {
|
||||
getYieldBalanceFlow(
|
||||
getStakingBalanceFlow(
|
||||
userWalletId = userWallet.walletId,
|
||||
currencyId = currency.id,
|
||||
networkStatus = networkStatus,
|
||||
|
|
@ -89,26 +89,26 @@ internal class CryptoCurrencyStatusesFlowFactory @Inject constructor(
|
|||
|
||||
val quoteStatusFlow = currency.id.rawCurrencyId?.let(::getQuoteStatusFlow)
|
||||
|
||||
return combine(networkStatusFlow, yieldBalanceFlow, quoteStatusFlow)
|
||||
return combine(networkStatusFlow, stakingBalanceFlow, quoteStatusFlow)
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
private fun combine(
|
||||
networkStatusFlow: Flow<NetworkStatus?>,
|
||||
yieldBalanceFlow: Flow<YieldBalance?>?,
|
||||
stakingBalanceFlow: Flow<StakingBalance?>?,
|
||||
quoteStatusFlow: Flow<QuoteStatus>?,
|
||||
): Flow<CryptoCurrencyStatusSources> {
|
||||
return when {
|
||||
yieldBalanceFlow != null && quoteStatusFlow != null -> {
|
||||
stakingBalanceFlow != null && quoteStatusFlow != null -> {
|
||||
combine(
|
||||
flow = networkStatusFlow,
|
||||
flow2 = yieldBalanceFlow,
|
||||
flow2 = stakingBalanceFlow,
|
||||
flow3 = quoteStatusFlow,
|
||||
transform = ::CryptoCurrencyStatusSources,
|
||||
)
|
||||
}
|
||||
yieldBalanceFlow != null -> {
|
||||
combine(flow = networkStatusFlow, flow2 = yieldBalanceFlow, transform = ::CryptoCurrencyStatusSources)
|
||||
stakingBalanceFlow != null -> {
|
||||
combine(flow = networkStatusFlow, flow2 = stakingBalanceFlow, transform = ::CryptoCurrencyStatusSources)
|
||||
}
|
||||
quoteStatusFlow != null -> {
|
||||
combine(flow = networkStatusFlow, flow2 = quoteStatusFlow) { networkStatus, quoteStatus ->
|
||||
|
|
@ -136,11 +136,11 @@ internal class CryptoCurrencyStatusesFlowFactory @Inject constructor(
|
|||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
private fun getYieldBalanceFlow(
|
||||
private fun getStakingBalanceFlow(
|
||||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
networkStatus: NetworkStatus,
|
||||
): Flow<YieldBalance?> {
|
||||
): Flow<StakingBalance?> {
|
||||
val stakingId = stakingIdFactory.create(
|
||||
currencyId = currencyId,
|
||||
defaultAddress = networkStatus.getAddress(),
|
||||
|
|
@ -148,8 +148,8 @@ internal class CryptoCurrencyStatusesFlowFactory @Inject constructor(
|
|||
.getOrNull()
|
||||
|
||||
return if (stakingId != null) {
|
||||
singleYieldBalanceSupplier(
|
||||
params = SingleYieldBalanceProducer.Params(userWalletId = userWalletId, stakingId = stakingId),
|
||||
singleStakingBalanceSupplier(
|
||||
params = SingleStakingBalanceProducer.Params(userWalletId = userWalletId, stakingId = stakingId),
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
} else {
|
||||
|
|
@ -159,7 +159,7 @@ internal class CryptoCurrencyStatusesFlowFactory @Inject constructor(
|
|||
|
||||
private data class CryptoCurrencyStatusSources(
|
||||
val networkStatus: NetworkStatus? = null,
|
||||
val yieldBalance: YieldBalance? = null,
|
||||
val stakingBalance: StakingBalance? = null,
|
||||
val quoteStatus: QuoteStatus? = null,
|
||||
)
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import com.tangem.domain.models.network.NetworkAddress
|
|||
import com.tangem.domain.models.network.NetworkStatus
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
|
|
@ -20,8 +20,8 @@ import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
|
|||
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceSupplier
|
||||
import com.tangem.test.core.getEmittedValues
|
||||
import io.mockk.*
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
|
|
@ -41,13 +41,13 @@ class CryptoCurrencyStatusesFlowFactoryTest {
|
|||
|
||||
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier = mockk()
|
||||
private val singleQuoteStatusSupplier: SingleQuoteStatusSupplier = mockk()
|
||||
private val singleYieldBalanceSupplier: SingleYieldBalanceSupplier = mockk()
|
||||
private val singleStakingBalanceSupplier: SingleStakingBalanceSupplier = mockk()
|
||||
private val stakingIdFactory: StakingIdFactory = mockk()
|
||||
|
||||
private val factory = CryptoCurrencyStatusesFlowFactory(
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
singleQuoteStatusSupplier = singleQuoteStatusSupplier,
|
||||
singleYieldBalanceSupplier = singleYieldBalanceSupplier,
|
||||
singleStakingBalanceSupplier = singleStakingBalanceSupplier,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
)
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ class CryptoCurrencyStatusesFlowFactoryTest {
|
|||
clearMocks(
|
||||
singleNetworkStatusSupplier,
|
||||
singleQuoteStatusSupplier,
|
||||
singleYieldBalanceSupplier,
|
||||
singleStakingBalanceSupplier,
|
||||
stakingIdFactory,
|
||||
)
|
||||
}
|
||||
|
|
@ -96,13 +96,13 @@ class CryptoCurrencyStatusesFlowFactoryTest {
|
|||
stakingIdFactory.create(currencyId = currency.id, defaultAddress = networkAddress.defaultAddress.value)
|
||||
} returns stakingId.right()
|
||||
|
||||
val yieldBalance = YieldBalance.Empty(stakingId = stakingId, source = StatusSource.ACTUAL)
|
||||
val yieldBalanceFlow = flowOf(yieldBalance)
|
||||
val stakingBalance = StakingBalance.Empty(stakingId = stakingId, source = StatusSource.ACTUAL)
|
||||
val stakingBalanceFlow = flowOf(stakingBalance)
|
||||
every {
|
||||
singleYieldBalanceSupplier(
|
||||
params = SingleYieldBalanceProducer.Params(userWalletId = userWalletId, stakingId = stakingId),
|
||||
singleStakingBalanceSupplier(
|
||||
params = SingleStakingBalanceProducer.Params(userWalletId = userWalletId, stakingId = stakingId),
|
||||
)
|
||||
} returns yieldBalanceFlow
|
||||
} returns stakingBalanceFlow
|
||||
|
||||
// Act
|
||||
val actual = factory.create(userWallet = userWallet, currency = currency).let(::getEmittedValues)
|
||||
|
|
@ -121,7 +121,7 @@ class CryptoCurrencyStatusesFlowFactoryTest {
|
|||
coVerify(ordering = Ordering.SEQUENCE) {
|
||||
singleNetworkStatusSupplier(params = SingleNetworkStatusProducer.Params(userWalletId, currency.network))
|
||||
stakingIdFactory.create(currencyId = currency.id, defaultAddress = networkAddress.defaultAddress.value)
|
||||
singleYieldBalanceSupplier(params = SingleYieldBalanceProducer.Params(userWalletId, stakingId))
|
||||
singleStakingBalanceSupplier(params = SingleStakingBalanceProducer.Params(userWalletId, stakingId))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ internal fun createStatus(currency: CryptoCurrency, fiatAmount: BigDecimal): Cry
|
|||
fiatRate = BigDecimal.ONE,
|
||||
fiatAmount = fiatAmount,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
yieldSupplyStatus = null,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.derivations.DerivationsRepository
|
||||
|
|
@ -28,7 +28,7 @@ class SaveManagedTokensUseCase(
|
|||
private val derivationsRepository: DerivationsRepository,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
private val parallelUpdatingScope: CoroutineScope,
|
||||
) {
|
||||
|
|
@ -70,7 +70,7 @@ class SaveManagedTokensUseCase(
|
|||
)
|
||||
}
|
||||
launch {
|
||||
refreshUpdatedYieldBalances(
|
||||
refreshUpdatedStakingBalances(
|
||||
userWalletId = userWalletId,
|
||||
addedCurrencies = savedCurrencies,
|
||||
)
|
||||
|
|
@ -127,7 +127,7 @@ class SaveManagedTokensUseCase(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedYieldBalances(
|
||||
private suspend fun refreshUpdatedStakingBalances(
|
||||
userWalletId: UserWalletId,
|
||||
addedCurrencies: List<CryptoCurrency>,
|
||||
) {
|
||||
|
|
@ -135,8 +135,8 @@ class SaveManagedTokensUseCase(
|
|||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it).getOrNull()
|
||||
}
|
||||
|
||||
multiYieldBalanceFetcher(
|
||||
params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds),
|
||||
multiStakingBalanceFetcher(
|
||||
params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.derivations.DerivationsRepository
|
||||
|
|
@ -36,7 +36,7 @@ class SaveMarketTokensUseCase(
|
|||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
private val parallelUpdatingScope: CoroutineScope,
|
||||
) {
|
||||
|
|
@ -85,7 +85,7 @@ class SaveMarketTokensUseCase(
|
|||
syncTokens(userWalletId, savedCurrencies)
|
||||
|
||||
launch { refreshUpdatedNetworks(userWalletId, savedCurrencies) }
|
||||
launch { refreshUpdatedYieldBalances(userWalletId, savedCurrencies) }
|
||||
launch { refreshUpdatedStakingBalances(userWalletId, savedCurrencies) }
|
||||
launch { refreshUpdatedQuotes(savedCurrencies) }
|
||||
}
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ class SaveMarketTokensUseCase(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedYieldBalances(
|
||||
private suspend fun refreshUpdatedStakingBalances(
|
||||
userWalletId: UserWalletId,
|
||||
existingCurrencies: List<CryptoCurrency>,
|
||||
) {
|
||||
|
|
@ -129,8 +129,8 @@ class SaveMarketTokensUseCase(
|
|||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it).getOrNull()
|
||||
}
|
||||
|
||||
multiYieldBalanceFetcher(
|
||||
params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds),
|
||||
multiStakingBalanceFetcher(
|
||||
params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import com.tangem.domain.models.getResultStatusSource
|
|||
import com.tangem.domain.models.network.NetworkAddress
|
||||
import com.tangem.domain.models.network.TxInfo
|
||||
import com.tangem.domain.models.serialization.SerializedBigDecimal
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.yield.supply.YieldSupplyStatus
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
|
@ -56,13 +56,10 @@ data class CryptoCurrencyStatus(
|
|||
/** The network address */
|
||||
val networkAddress: NetworkAddress? get() = null
|
||||
|
||||
/** Staking yield balance */
|
||||
val yieldBalance: YieldBalance? get() = null
|
||||
/** Staking balance */
|
||||
val stakingBalance: StakingBalance? get() = null
|
||||
|
||||
/**
|
||||
* !!! DO NOT CONFUSE with STAKING YIELD BALANCE
|
||||
* Yield supply status
|
||||
*/
|
||||
/** Yield supply status */
|
||||
val yieldSupplyStatus: YieldSupplyStatus? get() = null
|
||||
|
||||
/** Sources */
|
||||
|
|
@ -73,11 +70,11 @@ data class CryptoCurrencyStatus(
|
|||
data class Sources(
|
||||
val networkSource: StatusSource = StatusSource.ACTUAL,
|
||||
val quoteSource: StatusSource = StatusSource.ACTUAL,
|
||||
val yieldBalanceSource: StatusSource = StatusSource.ACTUAL,
|
||||
val stakingBalanceSource: StatusSource = StatusSource.ACTUAL,
|
||||
) {
|
||||
|
||||
val total: StatusSource by lazy {
|
||||
listOf(networkSource, quoteSource, yieldBalanceSource).getResultStatusSource()
|
||||
listOf(networkSource, quoteSource, stakingBalanceSource).getResultStatusSource()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +160,7 @@ data class CryptoCurrencyStatus(
|
|||
override val fiatAmount: SerializedBigDecimal,
|
||||
override val fiatRate: SerializedBigDecimal,
|
||||
override val priceChange: SerializedBigDecimal,
|
||||
override val yieldBalance: YieldBalance?,
|
||||
override val stakingBalance: StakingBalance?,
|
||||
override val yieldSupplyStatus: YieldSupplyStatus?,
|
||||
override val hasCurrentNetworkTransactions: Boolean,
|
||||
override val pendingTransactions: Set<TxInfo>,
|
||||
|
|
@ -191,7 +188,7 @@ data class CryptoCurrencyStatus(
|
|||
override val fiatAmount: SerializedBigDecimal?,
|
||||
override val fiatRate: SerializedBigDecimal?,
|
||||
override val priceChange: SerializedBigDecimal?,
|
||||
override val yieldBalance: YieldBalance?,
|
||||
override val stakingBalance: StakingBalance?,
|
||||
override val yieldSupplyStatus: YieldSupplyStatus?,
|
||||
override val hasCurrentNetworkTransactions: Boolean,
|
||||
override val pendingTransactions: Set<TxInfo>,
|
||||
|
|
@ -213,7 +210,7 @@ data class CryptoCurrencyStatus(
|
|||
@Serializable
|
||||
data class NoQuote(
|
||||
override val amount: SerializedBigDecimal,
|
||||
override val yieldBalance: YieldBalance?,
|
||||
override val stakingBalance: StakingBalance?,
|
||||
override val yieldSupplyStatus: YieldSupplyStatus?,
|
||||
override val hasCurrentNetworkTransactions: Boolean,
|
||||
override val pendingTransactions: Set<TxInfo>,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
package com.tangem.domain.models.staking
|
||||
|
||||
import com.tangem.domain.models.serialization.SerializedBigDecimal
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/** P2P.org staking account */
|
||||
@Serializable
|
||||
data class P2PStakingAccount(
|
||||
val delegatorAddress: String,
|
||||
val vaultAddress: String,
|
||||
val stake: P2PStake,
|
||||
val availableToUnstake: SerializedBigDecimal,
|
||||
val availableToWithdraw: SerializedBigDecimal,
|
||||
val exitQueue: P2PExitQueue,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class P2PStake(
|
||||
val assets: SerializedBigDecimal,
|
||||
val totalEarnedAssets: SerializedBigDecimal,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class P2PExitQueue(
|
||||
val total: SerializedBigDecimal,
|
||||
val requests: List<P2PExitRequest>,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class P2PExitRequest(
|
||||
val ticket: String,
|
||||
val totalAssets: SerializedBigDecimal,
|
||||
val timestamp: Instant,
|
||||
val withdrawalTimestamp: Instant,
|
||||
val isClaimable: Boolean,
|
||||
)
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
package com.tangem.domain.models.staking
|
||||
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Staking balance facade covering StakeKit and P2P balances
|
||||
*/
|
||||
@Serializable
|
||||
sealed interface StakingBalance {
|
||||
|
||||
val stakingId: StakingID
|
||||
val source: StatusSource
|
||||
|
||||
val totalStaked: BigDecimal
|
||||
val totalRewards: BigDecimal?
|
||||
val unstakingAmount: BigDecimal?
|
||||
val withdrawableAmount: BigDecimal?
|
||||
|
||||
@Serializable
|
||||
sealed interface Data : StakingBalance {
|
||||
|
||||
@Serializable
|
||||
data class StakeKit(
|
||||
override val stakingId: StakingID,
|
||||
override val source: StatusSource,
|
||||
val balance: YieldBalanceItem,
|
||||
) : Data {
|
||||
|
||||
override val totalStaked: BigDecimal
|
||||
get() = balance.items
|
||||
.filter { it.type == BalanceType.STAKED }
|
||||
.sumOf { it.amount }
|
||||
|
||||
override val totalRewards: BigDecimal
|
||||
get() = balance.items
|
||||
.filter { it.type == BalanceType.REWARDS }
|
||||
.sumOf { it.amount }
|
||||
|
||||
override val unstakingAmount: BigDecimal
|
||||
get() = balance.items
|
||||
.filter { it.type == BalanceType.UNSTAKING || it.type == BalanceType.UNLOCKING }
|
||||
.sumOf { it.amount }
|
||||
|
||||
override val withdrawableAmount: BigDecimal
|
||||
get() = balance.items
|
||||
.filter { it.type == BalanceType.UNSTAKED }
|
||||
.sumOf { it.amount }
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class P2P(
|
||||
override val stakingId: StakingID,
|
||||
override val source: StatusSource,
|
||||
val account: P2PStakingAccount,
|
||||
) : Data {
|
||||
|
||||
override val totalStaked: BigDecimal
|
||||
get() = account.stake.assets
|
||||
|
||||
override val totalRewards: BigDecimal
|
||||
get() = account.stake.totalEarnedAssets
|
||||
|
||||
override val unstakingAmount: BigDecimal
|
||||
get() = account.exitQueue.total
|
||||
|
||||
override val withdrawableAmount: BigDecimal
|
||||
get() = account.availableToWithdraw
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class Empty(
|
||||
override val stakingId: StakingID,
|
||||
override val source: StatusSource,
|
||||
) : StakingBalance {
|
||||
override val totalStaked: BigDecimal get() = BigDecimal.ZERO
|
||||
override val totalRewards: BigDecimal? get() = null
|
||||
override val unstakingAmount: BigDecimal? get() = null
|
||||
override val withdrawableAmount: BigDecimal? get() = null
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class Error(override val stakingId: StakingID) : StakingBalance {
|
||||
override val source: StatusSource get() = StatusSource.ACTUAL
|
||||
override val totalStaked: BigDecimal get() = BigDecimal.ZERO
|
||||
override val totalRewards: BigDecimal? get() = null
|
||||
override val unstakingAmount: BigDecimal? get() = null
|
||||
override val withdrawableAmount: BigDecimal? get() = null
|
||||
}
|
||||
|
||||
fun copySealed(source: StatusSource): StakingBalance {
|
||||
return when (this) {
|
||||
is Data.StakeKit -> copy(source = source)
|
||||
is Data.P2P -> copy(source = source)
|
||||
is Empty -> copy(source = source)
|
||||
is Error -> this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,8 @@
|
|||
<ID>MultilineLambdaItParameter:InvalidatePendingTransactionsUseCase.kt$InvalidatePendingTransactionsUseCase${ !it.isPending && action.amount < it.amount && it.type == BalanceType.STAKED && 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>
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ sealed interface StakingOption {
|
|||
* Wraps P2P ETH Pool vault information
|
||||
*/
|
||||
data class P2P(val vault: P2PEthPoolVault) : StakingOption {
|
||||
override val integrationId: String =
|
||||
"p2p-ethereum-pooled"
|
||||
override val integrationId: String = "p2p-ethereum-pooled"
|
||||
override val apy: SerializedBigDecimal = vault.apy
|
||||
override val token: YieldToken = createEthToken()
|
||||
override val isAvailable: Boolean = !vault.isPrivate
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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()}
|
||||
)
|
||||
|
|
@ -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>
|
||||
}
|
||||
|
|
@ -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>>()
|
||||
|
|
@ -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>
|
||||
}
|
||||
|
|
@ -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>>()
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
}
|
||||
|
|
@ -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>()
|
||||
|
|
@ -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>()
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
<ID>MultilineLambdaItParameter:PriceChangeCalculator.kt$PriceChangeCalculator${ val weight = it.value.fiatAmount.orZero().divide(balance, 2, RoundingMode.HALF_UP) val priceChange = it.value.priceChange.orZero() weight * priceChange }</ID>
|
||||
<ID>MultilineLambdaItParameter:WalletBalanceFetcher.kt$WalletBalanceFetcher${ val stakingId = stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it) if (stakingId.isLeft { it is StakingIdFactory.Error.UnableToGetAddress }) { Timber.e("Unable to get staking ID for user wallet $userWalletId and currency ${it.id}") } stakingId }</ID>
|
||||
<ID>NamedArguments:ApplyTokenListSortingUseCase.kt$ApplyTokenListSortingUseCase$saveTokens(userWalletId, currencies, isGrouped, isSortedByBalance)</ID>
|
||||
<ID>NamedArguments:CryptoCurrencyStatusFactory.kt$CryptoCurrencyStatusFactory$createStatus(currency, status, quoteStatus, maybeYieldBalance)</ID>
|
||||
<ID>NamedArguments:GetCurrencyWarningsUseCase.kt$GetCurrencyWarningsUseCase$combine( getCoinRelatedWarnings( userWalletId = userWalletId, networkId = currency.network.id, currencyId = currency.id, derivationPath = derivationPath, isSingleWalletWithTokens = isSingleWalletWithTokens, ), flowOf(currencyChecksRepository.getRentInfoWarning(userWalletId, currencyStatus)), flowOf(currencyChecksRepository.getExistentialDeposit(userWalletId, currency.network)), flowOf(currencyChecksRepository.getFeeResourceAmount(userWalletId, currency.network)), ) { coinRelatedWarnings, maybeRentWarning, maybeEdWarning, maybeFeeResource -> setOfNotNull( maybeRentWarning, maybeEdWarning?.let { getExistentialDepositWarning(currency, it) }, maybeFeeResource?.let { getFeeResourceWarning(it) }, * coinRelatedWarnings.toTypedArray(), getNetworkUnavailableWarning(currencyStatus), getNetworkNoAccountWarning(currencyStatus), getBeaconChainShutdownWarning(rawId = currency.network.id.rawId), getAssetRequirementsWarning(userWalletId = userWalletId, currency = currency), getMigrationFromMaticToPolWarning(currency), ) }</ID>
|
||||
<ID>NoNameShadowing:WalletBalanceFetcher.kt$WalletBalanceFetcher${ it is StakingIdFactory.Error.UnableToGetAddress }</ID>
|
||||
<ID>NullableBooleanCheck:GetCurrencyCheckUseCase.kt$GetCurrencyCheckUseCase$recipientAddress?.let { currencyChecksRepository.checkIfAccountFunded( userWalletId, network, recipientAddress, ) } ?: false</ID>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import kotlinx.coroutines.async
|
||||
|
|
@ -32,7 +32,7 @@ class AddCryptoCurrenciesUseCase(
|
|||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
private val singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
|
||||
private val singleStakingBalanceFetcher: SingleStakingBalanceFetcher,
|
||||
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
) {
|
||||
|
|
@ -82,7 +82,7 @@ class AddCryptoCurrenciesUseCase(
|
|||
|
||||
awaitAll(
|
||||
async { refreshUpdatedNetworks(userWalletId, currencyToAdd, existingCurrencies) },
|
||||
async { refreshUpdatedYieldBalances(userWalletId, currencyToAdd) },
|
||||
async { refreshUpdatedStakingBalances(userWalletId, currencyToAdd) },
|
||||
async { refreshUpdatedQuotes(currencyToAdd) },
|
||||
)
|
||||
}
|
||||
|
|
@ -122,7 +122,7 @@ class AddCryptoCurrenciesUseCase(
|
|||
|
||||
awaitAll(
|
||||
async { refreshUpdatedNetworks(userWalletId, tokenToAdd, existingCurrencies) },
|
||||
async { refreshUpdatedYieldBalances(userWalletId, tokenToAdd) },
|
||||
async { refreshUpdatedStakingBalances(userWalletId, tokenToAdd) },
|
||||
async { refreshUpdatedQuotes(tokenToAdd) },
|
||||
)
|
||||
}
|
||||
|
|
@ -177,7 +177,7 @@ class AddCryptoCurrenciesUseCase(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedYieldBalances(
|
||||
private suspend fun refreshUpdatedStakingBalances(
|
||||
userWalletId: UserWalletId,
|
||||
addedCurrency: CryptoCurrency,
|
||||
): Either<Throwable, Unit> = either {
|
||||
|
|
@ -195,8 +195,8 @@ class AddCryptoCurrenciesUseCase(
|
|||
return@either
|
||||
}
|
||||
|
||||
singleYieldBalanceFetcher(
|
||||
params = SingleYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingId = stakingId),
|
||||
singleStakingBalanceFetcher(
|
||||
params = SingleStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingId = stakingId),
|
||||
)
|
||||
.bind()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import kotlinx.coroutines.async
|
||||
|
|
@ -32,7 +32,7 @@ class FetchCurrencyStatusUseCase(
|
|||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
private val singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
|
||||
private val singleStakingBalanceFetcher: SingleStakingBalanceFetcher,
|
||||
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
) {
|
||||
|
|
@ -149,8 +149,8 @@ class FetchCurrencyStatusUseCase(
|
|||
return@either
|
||||
}
|
||||
|
||||
singleYieldBalanceFetcher(
|
||||
params = SingleYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingId = stakingId),
|
||||
singleStakingBalanceFetcher(
|
||||
params = SingleStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingId = stakingId),
|
||||
)
|
||||
.bind()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
|||
internal fun CurrenciesStatusesOperations.Error.mapToCurrencyError(): CurrencyStatusError {
|
||||
return when (this) {
|
||||
is CurrenciesStatusesOperations.Error.DataError -> CurrencyStatusError.DataError(this.cause)
|
||||
is CurrenciesStatusesOperations.Error.EmptyYieldBalances,
|
||||
is CurrenciesStatusesOperations.Error.EmptyStakingBalances,
|
||||
is CurrenciesStatusesOperations.Error.EmptyNetworksStatuses,
|
||||
is CurrenciesStatusesOperations.Error.EmptyQuotes,
|
||||
is CurrenciesStatusesOperations.Error.EmptyCurrencies,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ internal fun CurrenciesStatusesOperations.Error.mapToTokenListError(): TokenList
|
|||
is CurrenciesStatusesOperations.Error.EmptyCurrencies,
|
||||
is CurrenciesStatusesOperations.Error.EmptyAddresses,
|
||||
is CurrenciesStatusesOperations.Error.UnableToCreateCurrencyStatus,
|
||||
is CurrenciesStatusesOperations.Error.EmptyYieldBalances,
|
||||
is CurrenciesStatusesOperations.Error.EmptyStakingBalances,
|
||||
-> TokenListError.EmptyTokens
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
|||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.network.NetworkStatus
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusProducer
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
|
||||
|
|
@ -22,10 +22,10 @@ import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
|
|||
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.model.isStakingSupported
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceProducer
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceSupplier
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
|
|
@ -48,8 +48,8 @@ abstract class BaseCurrencyStatusOperations(
|
|||
private val multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
private val singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
|
||||
private val singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
|
||||
private val multiYieldBalanceSupplier: MultiYieldBalanceSupplier,
|
||||
private val singleStakingBalanceSupplier: SingleStakingBalanceSupplier,
|
||||
private val multiStakingBalanceSupplier: MultiStakingBalanceSupplier,
|
||||
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
) {
|
||||
|
|
@ -83,7 +83,7 @@ abstract class BaseCurrencyStatusOperations(
|
|||
userWalletId: UserWalletId,
|
||||
currency: CryptoCurrency,
|
||||
includeQuotes: Boolean = true,
|
||||
subscribeOnYieldBalance: Boolean = true,
|
||||
subscribeOnStakingBalance: Boolean = true,
|
||||
): Flow<Either<Error, CryptoCurrencyStatus>> {
|
||||
val rawCurrencyId = currency.id.rawCurrencyId
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ abstract class BaseCurrencyStatusOperations(
|
|||
|
||||
val isStakingSupported = currency.network.toBlockchain().isStakingSupported
|
||||
|
||||
val yieldBalanceFlow = if (isStakingSupported) {
|
||||
val stakingBalanceFlow = if (isStakingSupported) {
|
||||
val stakingId = stakingIdFactory.create(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = currency.id,
|
||||
|
|
@ -113,19 +113,19 @@ abstract class BaseCurrencyStatusOperations(
|
|||
.getOrNull()
|
||||
|
||||
stakingId?.let {
|
||||
getYieldBalance(userWalletId = userWalletId, stakingId = it)
|
||||
getStakingBalance(userWalletId = userWalletId, stakingId = it)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
return if (subscribeOnYieldBalance && yieldBalanceFlow != null) {
|
||||
combine(quoteFlow, statusFlow, yieldBalanceFlow) { maybeQuote, maybeNetworkStatus, maybeYieldBalance ->
|
||||
return if (subscribeOnStakingBalance && stakingBalanceFlow != null) {
|
||||
combine(quoteFlow, statusFlow, stakingBalanceFlow) { maybeQuote, maybeNetworkStatus, maybeStakingBalance ->
|
||||
currencyStatusProxyCreator.createCurrencyStatus(
|
||||
currency = currency,
|
||||
maybeQuoteStatus = maybeQuote,
|
||||
maybeNetworkStatus = maybeNetworkStatus,
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -134,7 +134,7 @@ abstract class BaseCurrencyStatusOperations(
|
|||
currency = currency,
|
||||
maybeQuoteStatus = maybeQuote,
|
||||
maybeNetworkStatus = maybeNetworkStatus,
|
||||
maybeYieldBalance = null,
|
||||
maybeStakingBalance = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -209,13 +209,13 @@ abstract class BaseCurrencyStatusOperations(
|
|||
.firstOrNull()
|
||||
.right()
|
||||
|
||||
val yieldBalances = getYieldBalanceSync(userWalletId, currency)
|
||||
val stakingBalances = getStakingBalanceSync(userWalletId, currency)
|
||||
|
||||
return currencyStatusProxyCreator.createCurrencyStatus(
|
||||
currency = currency,
|
||||
maybeQuoteStatus = quote,
|
||||
maybeNetworkStatus = networkStatuses,
|
||||
maybeYieldBalance = yieldBalances,
|
||||
maybeStakingBalance = stakingBalances,
|
||||
)
|
||||
},
|
||||
catch = { raise(Error.DataError(it)) },
|
||||
|
|
@ -245,7 +245,7 @@ abstract class BaseCurrencyStatusOperations(
|
|||
userWalletId = userWalletId,
|
||||
currency = currency,
|
||||
includeQuotes = includeQuotes,
|
||||
subscribeOnYieldBalance = false,
|
||||
subscribeOnStakingBalance = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -271,13 +271,13 @@ abstract class BaseCurrencyStatusOperations(
|
|||
.orEmpty()
|
||||
.right()
|
||||
|
||||
val yieldBalances = getYieldBalancesSync(userWalletId, nonEmptyCurrencies)
|
||||
val stakingBalances = getStakingBalancesSync(userWalletId, nonEmptyCurrencies)
|
||||
|
||||
return currencyStatusProxyCreator.createCurrenciesStatuses(
|
||||
currencies = nonEmptyCurrencies,
|
||||
maybeQuotes = quotes,
|
||||
maybeNetworkStatuses = networkStatuses,
|
||||
maybeYieldBalances = yieldBalances,
|
||||
maybeStakingBalances = stakingBalances,
|
||||
)
|
||||
},
|
||||
catch = { raise(Error.DataError(it)) },
|
||||
|
|
@ -304,13 +304,13 @@ abstract class BaseCurrencyStatusOperations(
|
|||
.firstOrNull()
|
||||
.right()
|
||||
|
||||
val yieldBalances = getYieldBalanceSync(userWalletId, currency)
|
||||
val stakingBalances = getStakingBalanceSync(userWalletId, currency)
|
||||
|
||||
return currencyStatusProxyCreator.createCurrencyStatus(
|
||||
currency = currency,
|
||||
maybeQuoteStatus = quotes,
|
||||
maybeNetworkStatus = networkStatus,
|
||||
maybeYieldBalance = yieldBalances,
|
||||
maybeStakingBalance = stakingBalances,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -338,16 +338,16 @@ abstract class BaseCurrencyStatusOperations(
|
|||
.bind()
|
||||
}
|
||||
|
||||
private fun getYieldBalance(userWalletId: UserWalletId, stakingId: StakingID): EitherFlow<Error, YieldBalance> {
|
||||
return singleYieldBalanceSupplier(
|
||||
params = SingleYieldBalanceProducer.Params(
|
||||
private fun getStakingBalance(userWalletId: UserWalletId, stakingId: StakingID): EitherFlow<Error, StakingBalance> {
|
||||
return singleStakingBalanceSupplier(
|
||||
params = SingleStakingBalanceProducer.Params(
|
||||
userWalletId = userWalletId,
|
||||
stakingId = stakingId,
|
||||
),
|
||||
)
|
||||
.map<YieldBalance, Either<Error, YieldBalance>> { it.right() }
|
||||
.map<StakingBalance, Either<Error, StakingBalance>> { it.right() }
|
||||
.catch { emit(Error.DataError(it).left()) }
|
||||
.onEmpty { emit(Error.EmptyYieldBalances.left()) }
|
||||
.onEmpty { emit(Error.EmptyStakingBalances.left()) }
|
||||
}
|
||||
|
||||
private fun getNetworkStatus(userWalletId: UserWalletId, network: Network): EitherFlow<Error, NetworkStatus> {
|
||||
|
|
@ -389,32 +389,32 @@ abstract class BaseCurrencyStatusOperations(
|
|||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun getYieldBalancesSync(
|
||||
private suspend fun getStakingBalancesSync(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencies: List<CryptoCurrency>,
|
||||
): Either<Error.EmptyYieldBalances, List<YieldBalance>> = either {
|
||||
): Either<Error.EmptyStakingBalances, List<StakingBalance>> = either {
|
||||
val stakingIds = cryptoCurrencies.mapNotNull { cryptoCurrency ->
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrency)
|
||||
.getOrNull()
|
||||
}
|
||||
|
||||
ensure(stakingIds.isNotEmpty()) { Error.EmptyYieldBalances }
|
||||
ensure(stakingIds.isNotEmpty()) { Error.EmptyStakingBalances }
|
||||
|
||||
val balances = multiYieldBalanceSupplier.getSyncOrNull(
|
||||
params = MultiYieldBalanceProducer.Params(userWalletId = userWalletId),
|
||||
val balances = multiStakingBalanceSupplier.getSyncOrNull(
|
||||
params = MultiStakingBalanceProducer.Params(userWalletId = userWalletId),
|
||||
)
|
||||
.orEmpty()
|
||||
.filter { it.stakingId in stakingIds }
|
||||
|
||||
ensure(balances.isNotEmpty()) { Error.EmptyYieldBalances }
|
||||
ensure(balances.isNotEmpty()) { Error.EmptyStakingBalances }
|
||||
|
||||
balances
|
||||
}
|
||||
|
||||
private suspend fun getYieldBalanceSync(
|
||||
private suspend fun getStakingBalanceSync(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
): Either<Error, YieldBalance> = either {
|
||||
): Either<Error, StakingBalance> = either {
|
||||
val stakingId = stakingIdFactory.create(userWalletId, cryptoCurrency)
|
||||
.mapLeft {
|
||||
val exception = IllegalStateException("$it")
|
||||
|
|
@ -422,14 +422,14 @@ abstract class BaseCurrencyStatusOperations(
|
|||
}
|
||||
.bind()
|
||||
|
||||
val yieldBalance = singleYieldBalanceSupplier.getSyncOrNull(
|
||||
params = SingleYieldBalanceProducer.Params(
|
||||
val yieldBalance = singleStakingBalanceSupplier.getSyncOrNull(
|
||||
params = SingleStakingBalanceProducer.Params(
|
||||
userWalletId = userWalletId,
|
||||
stakingId = stakingId,
|
||||
),
|
||||
)
|
||||
|
||||
ensureNotNull(yieldBalance) { Error.EmptyYieldBalances }
|
||||
ensureNotNull(yieldBalance) { Error.EmptyStakingBalances }
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import com.tangem.domain.models.network.NetworkStatus
|
|||
import com.tangem.domain.models.network.getAddress
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
|
||||
import com.tangem.domain.networks.single.SingleNetworkStatusProducer
|
||||
|
|
@ -26,9 +26,9 @@ import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
|
|||
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceSupplier
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceSupplier
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceProducer
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceSupplier
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error
|
||||
|
|
@ -46,8 +46,8 @@ class CachedCurrenciesStatusesOperations(
|
|||
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
private val singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
|
||||
private val singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
|
||||
multiYieldBalanceSupplier: MultiYieldBalanceSupplier,
|
||||
private val singleStakingBalanceSupplier: SingleStakingBalanceSupplier,
|
||||
multiStakingBalanceSupplier: MultiStakingBalanceSupplier,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
) : BaseCurrencyStatusOperations(
|
||||
|
|
@ -56,8 +56,8 @@ class CachedCurrenciesStatusesOperations(
|
|||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
singleQuoteStatusSupplier = singleQuoteStatusSupplier,
|
||||
singleYieldBalanceSupplier = singleYieldBalanceSupplier,
|
||||
multiYieldBalanceSupplier = multiYieldBalanceSupplier,
|
||||
singleStakingBalanceSupplier = singleStakingBalanceSupplier,
|
||||
multiStakingBalanceSupplier = multiStakingBalanceSupplier,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
) {
|
||||
|
|
@ -95,7 +95,7 @@ class CachedCurrenciesStatusesOperations(
|
|||
currencies = currencies,
|
||||
maybeNetworkStatuses = null,
|
||||
maybeQuotes = null,
|
||||
maybeYieldBalances = null,
|
||||
maybeStakingBalances = null,
|
||||
isUpdating = true,
|
||||
)
|
||||
|
||||
|
|
@ -109,13 +109,13 @@ class CachedCurrenciesStatusesOperations(
|
|||
fun createCurrenciesStatuses(
|
||||
maybeQuotes: Either<TokenListError, Set<QuoteStatus>>,
|
||||
maybeNetworkStatuses: Either<TokenListError, Set<NetworkStatus>>,
|
||||
maybeYieldBalances: Either<TokenListError, List<YieldBalance>>,
|
||||
maybeStakingBalances: Either<TokenListError, List<StakingBalance>>,
|
||||
isUpdating: Boolean,
|
||||
) = createCurrenciesStatuses(
|
||||
currencies = currencies,
|
||||
maybeQuotes = maybeQuotes,
|
||||
maybeNetworkStatuses = maybeNetworkStatuses,
|
||||
maybeYieldBalances = maybeYieldBalances,
|
||||
maybeStakingBalances = maybeStakingBalances,
|
||||
isUpdating = isUpdating,
|
||||
)
|
||||
|
||||
|
|
@ -166,13 +166,13 @@ class CachedCurrenciesStatusesOperations(
|
|||
currencies: NonEmptyList<CryptoCurrency>,
|
||||
maybeQuotes: Either<TokenListError, Set<QuoteStatus>>?,
|
||||
maybeNetworkStatuses: Either<TokenListError, Set<NetworkStatus>>?,
|
||||
maybeYieldBalances: Either<TokenListError, List<YieldBalance>>?,
|
||||
maybeStakingBalances: Either<TokenListError, List<StakingBalance>>?,
|
||||
isUpdating: Boolean,
|
||||
): Lce<TokenListError, List<CryptoCurrencyStatus>> = lce {
|
||||
isLoading.set(isUpdating)
|
||||
|
||||
val networksStatuses = maybeNetworkStatuses?.bindEither()?.toNonEmptySetOrNull()
|
||||
val yieldBalances = maybeYieldBalances?.bindEither()
|
||||
val stakingBalances = maybeStakingBalances?.bindEither()
|
||||
val quotes = recover({ maybeQuotes?.bind()?.toNonEmptySetOrNull() }) {
|
||||
null
|
||||
}
|
||||
|
|
@ -180,25 +180,25 @@ class CachedCurrenciesStatusesOperations(
|
|||
currencies.map { currency ->
|
||||
val quote = quotes?.firstOrNull { it.rawCurrencyId == currency.id.rawCurrencyId }
|
||||
val networkStatus = networksStatuses?.firstOrNull { it.network == currency.network }
|
||||
val yieldBalance = findYieldBalanceOrNull(yieldBalances, currency, networkStatus)
|
||||
val stakingBalance = findStakingBalanceOrNull(stakingBalances, currency, networkStatus)
|
||||
|
||||
val currencyStatus = CryptoCurrencyStatusFactory.create(
|
||||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.toOption(),
|
||||
maybeQuoteStatus = quote.toOption(),
|
||||
maybeYieldBalance = yieldBalance.toOption(),
|
||||
maybeStakingBalance = stakingBalance.toOption(),
|
||||
)
|
||||
|
||||
currencyStatus
|
||||
}
|
||||
}
|
||||
|
||||
private fun findYieldBalanceOrNull(
|
||||
yieldBalances: List<YieldBalance>?,
|
||||
private fun findStakingBalanceOrNull(
|
||||
stakingBalances: List<StakingBalance>?,
|
||||
currency: CryptoCurrency,
|
||||
networkStatus: NetworkStatus?,
|
||||
): YieldBalance? {
|
||||
if (yieldBalances.isNullOrEmpty()) return null
|
||||
): StakingBalance? {
|
||||
if (stakingBalances.isNullOrEmpty()) return null
|
||||
|
||||
val supportedIntegration = StakingIntegrationID.create(currencyId = currency.id)?.value
|
||||
val address = networkStatus.getAddress()
|
||||
|
|
@ -206,8 +206,8 @@ class CachedCurrenciesStatusesOperations(
|
|||
return if (supportedIntegration != null && address != null) {
|
||||
val stakingId = StakingID(integrationId = supportedIntegration, address = address)
|
||||
|
||||
yieldBalances.firstOrNull { it.stakingId == stakingId }
|
||||
?: YieldBalance.Error(stakingId = stakingId)
|
||||
stakingBalances.firstOrNull { it.stakingId == stakingId }
|
||||
?: StakingBalance.Error(stakingId = stakingId)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
|
@ -302,9 +302,9 @@ class CachedCurrenciesStatusesOperations(
|
|||
private fun getYieldsBalancesUpdates(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencies: Map<CryptoCurrency.ID, String?>,
|
||||
): EitherFlow<TokenListError, List<YieldBalance>> {
|
||||
): EitherFlow<TokenListError, List<StakingBalance>> {
|
||||
return channelFlow {
|
||||
val state = MutableStateFlow(emptyList<YieldBalance>())
|
||||
val state = MutableStateFlow(emptyList<StakingBalance>())
|
||||
|
||||
val stakingIds = cryptoCurrencies.mapNotNullTo(hashSetOf()) { currencyWithAddress ->
|
||||
stakingIdFactory.create(
|
||||
|
|
@ -316,8 +316,11 @@ class CachedCurrenciesStatusesOperations(
|
|||
|
||||
stakingIds.onEach { stakingId ->
|
||||
launch {
|
||||
singleYieldBalanceSupplier(
|
||||
params = SingleYieldBalanceProducer.Params(userWalletId = userWalletId, stakingId = stakingId),
|
||||
singleStakingBalanceSupplier(
|
||||
params = SingleStakingBalanceProducer.Params(
|
||||
userWalletId = userWalletId,
|
||||
stakingId = stakingId,
|
||||
),
|
||||
)
|
||||
.onEach { balance ->
|
||||
state.update { loadedBalances ->
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import com.tangem.domain.models.network.NetworkAddress
|
|||
import com.tangem.domain.models.network.NetworkStatus
|
||||
import com.tangem.domain.models.network.TxInfo
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.yield.supply.YieldSupplyStatus
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Factory to create [CryptoCurrencyStatus] from [NetworkStatus], [QuoteStatus] and [YieldBalance].
|
||||
* Factory to create [CryptoCurrencyStatus] from [NetworkStatus], [QuoteStatus] and [StakingBalance].
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
@ -26,25 +26,25 @@ object CryptoCurrencyStatusFactory {
|
|||
get() = (this?.value as? QuoteStatus.Data)?.priceChange
|
||||
|
||||
/**
|
||||
* Creates [CryptoCurrencyStatus] from [NetworkStatus], [QuoteStatus] and [YieldBalance].
|
||||
* Creates [CryptoCurrencyStatus] from [NetworkStatus], [QuoteStatus] and [StakingBalance].
|
||||
*
|
||||
|
||||
* @param maybeNetworkStatus An optional network status containing blockchain information.
|
||||
* @param maybeQuoteStatus An optional quote status containing price information.
|
||||
* @param maybeYieldBalance An optional yield balance containing staking information.
|
||||
* @param maybeStakingBalance An optional staking balance containing staking information.
|
||||
*/
|
||||
fun create(
|
||||
currency: CryptoCurrency,
|
||||
maybeNetworkStatus: Option<NetworkStatus>,
|
||||
maybeQuoteStatus: Option<QuoteStatus>,
|
||||
maybeYieldBalance: Option<YieldBalance>,
|
||||
maybeStakingBalance: Option<StakingBalance>,
|
||||
): CryptoCurrencyStatus {
|
||||
return CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = createStatus(
|
||||
currency = currency,
|
||||
maybeNetworkStatus = maybeNetworkStatus,
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
maybeQuoteStatus = maybeQuoteStatus,
|
||||
),
|
||||
)
|
||||
|
|
@ -54,7 +54,7 @@ object CryptoCurrencyStatusFactory {
|
|||
currency: CryptoCurrency,
|
||||
maybeNetworkStatus: Option<NetworkStatus>,
|
||||
maybeQuoteStatus: Option<QuoteStatus>,
|
||||
maybeYieldBalance: Option<YieldBalance>,
|
||||
maybeStakingBalance: Option<StakingBalance>,
|
||||
): CryptoCurrencyStatus.Value {
|
||||
val quoteStatus = maybeQuoteStatus.getOrNull()
|
||||
|
||||
|
|
@ -62,7 +62,12 @@ object CryptoCurrencyStatusFactory {
|
|||
is NetworkStatus.MissedDerivation -> createMissedDerivation(quoteStatus)
|
||||
is NetworkStatus.Unreachable -> createUnreachable(status, quoteStatus)
|
||||
is NetworkStatus.NoAccount -> createNoAccount(status, quoteStatus)
|
||||
is NetworkStatus.Verified -> createStatus(currency, status, quoteStatus, maybeYieldBalance)
|
||||
is NetworkStatus.Verified -> createStatus(
|
||||
currency = currency,
|
||||
status = status,
|
||||
quoteStatus = quoteStatus,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
null -> CryptoCurrencyStatus.Loading
|
||||
}
|
||||
}
|
||||
|
|
@ -106,7 +111,7 @@ object CryptoCurrencyStatusFactory {
|
|||
currency: CryptoCurrency,
|
||||
status: NetworkStatus.Verified,
|
||||
quoteStatus: QuoteStatus?,
|
||||
maybeYieldBalance: Option<YieldBalance>,
|
||||
maybeStakingBalance: Option<StakingBalance>,
|
||||
): CryptoCurrencyStatus.Value {
|
||||
val amount = when (val amount = status.amounts[currency.id]) {
|
||||
is NetworkStatus.Amount.Loaded -> amount.value
|
||||
|
|
@ -118,7 +123,7 @@ object CryptoCurrencyStatusFactory {
|
|||
}
|
||||
}
|
||||
|
||||
val yieldBalance = maybeYieldBalance.getOrNull(id = currency.id, address = status.address)
|
||||
val stakingBalance = maybeStakingBalance.getOrNull(id = currency.id, address = status.address)
|
||||
|
||||
if (currency is CryptoCurrency.Token && currency.isCustom) {
|
||||
return createCustom(
|
||||
|
|
@ -126,7 +131,7 @@ object CryptoCurrencyStatusFactory {
|
|||
status = status,
|
||||
amount = amount,
|
||||
quoteStatus = quoteStatus,
|
||||
yieldBalance = yieldBalance,
|
||||
stakingBalance = stakingBalance,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +143,7 @@ object CryptoCurrencyStatusFactory {
|
|||
status = status,
|
||||
amount = amount,
|
||||
quoteStatus = quoteStatus,
|
||||
yieldBalance = yieldBalance,
|
||||
stakingBalance = stakingBalance,
|
||||
)
|
||||
}
|
||||
is QuoteStatus.Data -> {
|
||||
|
|
@ -147,7 +152,7 @@ object CryptoCurrencyStatusFactory {
|
|||
status = status,
|
||||
amount = amount,
|
||||
quoteStatus = quoteValue,
|
||||
yieldBalance = yieldBalance,
|
||||
stakingBalance = stakingBalance,
|
||||
)
|
||||
}
|
||||
null -> CryptoCurrencyStatus.Loading
|
||||
|
|
@ -166,7 +171,7 @@ object CryptoCurrencyStatusFactory {
|
|||
status: NetworkStatus.Verified,
|
||||
amount: BigDecimal,
|
||||
quoteStatus: QuoteStatus?,
|
||||
yieldBalance: YieldBalance.Data?,
|
||||
stakingBalance: StakingBalance.Data?,
|
||||
): CryptoCurrencyStatus.Custom {
|
||||
return CryptoCurrencyStatus.Custom(
|
||||
amount = amount,
|
||||
|
|
@ -176,11 +181,11 @@ object CryptoCurrencyStatusFactory {
|
|||
hasCurrentNetworkTransactions = status.hasCurrentNetworkTransactions(),
|
||||
pendingTransactions = status.getCurrentTransactions(id),
|
||||
networkAddress = status.address,
|
||||
yieldBalance = yieldBalance,
|
||||
stakingBalance = stakingBalance,
|
||||
yieldSupplyStatus = status.getYieldSupplyStatus(id),
|
||||
sources = CryptoCurrencyStatus.Sources(
|
||||
networkSource = status.source,
|
||||
yieldBalanceSource = yieldBalance?.source ?: StatusSource.ACTUAL,
|
||||
stakingBalanceSource = stakingBalance?.source ?: StatusSource.ACTUAL,
|
||||
quoteSource = quoteStatus?.value?.source ?: StatusSource.ACTUAL,
|
||||
),
|
||||
)
|
||||
|
|
@ -191,18 +196,18 @@ object CryptoCurrencyStatusFactory {
|
|||
status: NetworkStatus.Verified,
|
||||
amount: BigDecimal,
|
||||
quoteStatus: QuoteStatus?,
|
||||
yieldBalance: YieldBalance.Data?,
|
||||
stakingBalance: StakingBalance.Data?,
|
||||
): CryptoCurrencyStatus.NoQuote {
|
||||
return CryptoCurrencyStatus.NoQuote(
|
||||
amount = amount,
|
||||
hasCurrentNetworkTransactions = status.hasCurrentNetworkTransactions(),
|
||||
pendingTransactions = status.getCurrentTransactions(id),
|
||||
networkAddress = status.address,
|
||||
yieldBalance = yieldBalance,
|
||||
stakingBalance = stakingBalance,
|
||||
yieldSupplyStatus = status.getYieldSupplyStatus(id),
|
||||
sources = CryptoCurrencyStatus.Sources(
|
||||
networkSource = status.source,
|
||||
yieldBalanceSource = yieldBalance?.source ?: StatusSource.ACTUAL,
|
||||
stakingBalanceSource = stakingBalance?.source ?: StatusSource.ACTUAL,
|
||||
quoteSource = quoteStatus?.value?.source ?: StatusSource.ACTUAL,
|
||||
),
|
||||
)
|
||||
|
|
@ -213,7 +218,7 @@ object CryptoCurrencyStatusFactory {
|
|||
status: NetworkStatus.Verified,
|
||||
amount: BigDecimal,
|
||||
quoteStatus: QuoteStatus.Data,
|
||||
yieldBalance: YieldBalance.Data?,
|
||||
stakingBalance: StakingBalance.Data?,
|
||||
): CryptoCurrencyStatus.Loaded {
|
||||
return CryptoCurrencyStatus.Loaded(
|
||||
amount = amount,
|
||||
|
|
@ -223,11 +228,11 @@ object CryptoCurrencyStatusFactory {
|
|||
hasCurrentNetworkTransactions = status.hasCurrentNetworkTransactions(),
|
||||
pendingTransactions = status.getCurrentTransactions(id),
|
||||
networkAddress = status.address,
|
||||
yieldBalance = yieldBalance,
|
||||
stakingBalance = stakingBalance,
|
||||
yieldSupplyStatus = status.getYieldSupplyStatus(id),
|
||||
sources = CryptoCurrencyStatus.Sources(
|
||||
networkSource = status.source,
|
||||
yieldBalanceSource = yieldBalance?.source ?: StatusSource.ACTUAL,
|
||||
stakingBalanceSource = stakingBalance?.source ?: StatusSource.ACTUAL,
|
||||
quoteSource = quoteStatus.source,
|
||||
),
|
||||
)
|
||||
|
|
@ -243,20 +248,34 @@ object CryptoCurrencyStatusFactory {
|
|||
return yieldSupplyStatuses[id]
|
||||
}
|
||||
|
||||
private fun Option<YieldBalance>.getOrNull(id: CryptoCurrency.ID, address: NetworkAddress): YieldBalance.Data? {
|
||||
val yieldBalance = this.getOrNull() as? YieldBalance.Data ?: return null
|
||||
private fun Option<StakingBalance>.getOrNull(
|
||||
id: CryptoCurrency.ID,
|
||||
address: NetworkAddress,
|
||||
): StakingBalance.Data? {
|
||||
return when (val stakingBalance = this.getOrNull()) {
|
||||
is StakingBalance.Data.StakeKit -> {
|
||||
val isCurrentAddressStaking = stakingBalance.stakingId.address == address.defaultAddress.value
|
||||
val filteredTokenBalances = stakingBalance.balance.items.filter {
|
||||
it.token.coinGeckoId == id.rawCurrencyId?.value
|
||||
}
|
||||
|
||||
val isCurrentAddressStaking = yieldBalance.stakingId.address == address.defaultAddress.value
|
||||
val filteredTokenBalances = yieldBalance.balance.items.filter {
|
||||
it.token.coinGeckoId == id.rawCurrencyId?.value
|
||||
}
|
||||
|
||||
return if (isCurrentAddressStaking && filteredTokenBalances.isNotEmpty()) {
|
||||
yieldBalance.copy(
|
||||
balance = yieldBalance.balance.copy(items = filteredTokenBalances),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
if (isCurrentAddressStaking && filteredTokenBalances.isNotEmpty()) {
|
||||
stakingBalance.copy(
|
||||
balance = stakingBalance.balance.copy(items = filteredTokenBalances),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
is StakingBalance.Data.P2P -> {
|
||||
// TODO p2p
|
||||
val isCurrentAddressStaking = stakingBalance.stakingId.address == address.defaultAddress.value
|
||||
if (isCurrentAddressStaking) stakingBalance else null
|
||||
}
|
||||
is StakingBalance.Empty,
|
||||
is StakingBalance.Error,
|
||||
null,
|
||||
-> null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ class CurrenciesStatusesOperations {
|
|||
|
||||
data class DataError(val cause: Throwable) : Error()
|
||||
|
||||
data object EmptyYieldBalances : Error()
|
||||
data object EmptyStakingBalances : Error()
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import com.tangem.domain.models.TokensGroupType
|
|||
import com.tangem.domain.models.TokensSortType
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.domain.models.tokenlist.TokenList.GroupedByNetwork.NetworkGroup
|
||||
import com.tangem.domain.staking.utils.getTotalWithRewardsStakingBalance
|
||||
|
|
@ -123,10 +123,10 @@ object TokenListFactory {
|
|||
}
|
||||
|
||||
private fun CryptoCurrencyStatus.calculateBalance(): BigDecimal {
|
||||
val yieldBalance = value.yieldBalance as? YieldBalance.Data
|
||||
val totalYieldBalance = yieldBalance?.getTotalWithRewardsStakingBalance(currency.network.rawId).orZero()
|
||||
val totalFiatYieldBalance = totalYieldBalance.multiply(value.fiatRate.orZero())
|
||||
val stakingBalance = value.stakingBalance as? StakingBalance.Data
|
||||
val totalStakingBalance = stakingBalance?.getTotalWithRewardsStakingBalance(currency.network.rawId).orZero()
|
||||
val totalFiatStakingBalance = totalStakingBalance.multiply(value.fiatRate.orZero())
|
||||
|
||||
return value.fiatAmount?.plus(totalFiatYieldBalance).orZero()
|
||||
return value.fiatAmount?.plus(totalFiatStakingBalance).orZero()
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import com.tangem.domain.models.StatusSource
|
|||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.getResultStatusSource
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.domain.staking.utils.getTotalWithRewardsStakingBalance
|
||||
import com.tangem.lib.crypto.BlockchainUtils
|
||||
|
|
@ -153,17 +153,17 @@ object TotalFiatBalanceCalculator {
|
|||
}
|
||||
|
||||
private fun CryptoCurrencyStatus.Loaded.getFiatStakingBalance(blockchainId: String): BigDecimal {
|
||||
val yieldBalance = yieldBalance as? YieldBalance.Data
|
||||
val stakingBalance = yieldBalance?.getTotalWithRewardsStakingBalance(blockchainId).orZero()
|
||||
val stakingBalanceData = stakingBalance as? StakingBalance.Data
|
||||
val totalStakingBalance = stakingBalanceData?.getTotalWithRewardsStakingBalance(blockchainId).orZero()
|
||||
|
||||
return fiatRate.times(stakingBalance)
|
||||
return fiatRate.times(totalStakingBalance)
|
||||
}
|
||||
|
||||
private fun CryptoCurrencyStatus.Custom.getFiatStakingBalance(blockchainId: String): BigDecimal {
|
||||
val yieldBalance = yieldBalance as? YieldBalance.Data
|
||||
val stakingBalance = yieldBalance?.getTotalWithRewardsStakingBalance(blockchainId).orZero()
|
||||
val stakingBalanceData = stakingBalance as? StakingBalance.Data
|
||||
val totalStakingBalance = stakingBalanceData?.getTotalWithRewardsStakingBalance(blockchainId).orZero()
|
||||
|
||||
return fiatRate?.times(stakingBalance).orZero()
|
||||
return fiatRate?.times(totalStakingBalance).orZero()
|
||||
}
|
||||
|
||||
private inline fun TotalFiatBalance.fold(
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
|||
import com.tangem.domain.models.network.NetworkStatus
|
||||
import com.tangem.domain.models.network.getAddress
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
import com.tangem.domain.tokens.operations.CryptoCurrencyStatusFactory
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error
|
||||
|
|
@ -28,20 +28,20 @@ class CurrencyStatusProxyCreator {
|
|||
currency: CryptoCurrency,
|
||||
maybeQuoteStatus: Either<Error, QuoteStatus?>,
|
||||
maybeNetworkStatus: Either<Error, NetworkStatus?>,
|
||||
maybeYieldBalance: Either<Error, YieldBalance>?,
|
||||
maybeStakingBalance: Either<Error, StakingBalance>?,
|
||||
): Either<Error, CryptoCurrencyStatus> = either {
|
||||
val networkStatus = maybeNetworkStatus.bind()
|
||||
val quote = recover(
|
||||
block = { maybeQuoteStatus.bind() },
|
||||
recover = { null },
|
||||
)
|
||||
val yieldBalance = maybeYieldBalance?.getOrNull()
|
||||
val stakingBalance = maybeStakingBalance?.getOrNull()
|
||||
|
||||
createCurrencyStatus(
|
||||
currency = currency,
|
||||
quoteStatus = quote,
|
||||
networkStatus = networkStatus,
|
||||
yieldBalance = yieldBalance,
|
||||
stakingBalance = stakingBalance,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -49,12 +49,12 @@ class CurrencyStatusProxyCreator {
|
|||
currencies: NonEmptyList<CryptoCurrency>,
|
||||
maybeQuotes: Either<Error, Set<QuoteStatus>>?,
|
||||
maybeNetworkStatuses: Either<Error, Set<NetworkStatus>>,
|
||||
maybeYieldBalances: Either<Error, List<YieldBalance>>,
|
||||
maybeStakingBalances: Either<Error, List<StakingBalance>>,
|
||||
): Either<Error, List<CryptoCurrencyStatus>> = either {
|
||||
val networksStatuses = maybeNetworkStatuses.bind().toNonEmptySetOrNull()
|
||||
val quoteStatuses: Set<QuoteStatus>? = maybeQuotes?.getOrNull()?.ifEmpty { null }
|
||||
|
||||
val yieldBalances = maybeYieldBalances.getOrNull()
|
||||
val stakingBalances = maybeStakingBalances.getOrNull()
|
||||
|
||||
currencies.map { currency ->
|
||||
val quote = quoteStatuses?.firstOrNull { it.rawCurrencyId == currency.id.rawCurrencyId }
|
||||
|
|
@ -63,11 +63,11 @@ class CurrencyStatusProxyCreator {
|
|||
|
||||
val supportedIntegration = StakingIntegrationID.create(currencyId = currency.id)?.value
|
||||
|
||||
val yieldBalance = if (supportedIntegration != null && address != null) {
|
||||
val stakingBalance = if (supportedIntegration != null && address != null) {
|
||||
val stakingId = StakingID(integrationId = supportedIntegration, address = address)
|
||||
|
||||
yieldBalances?.firstOrNull { it.stakingId == stakingId }
|
||||
?: YieldBalance.Error(stakingId = stakingId)
|
||||
stakingBalances?.firstOrNull { it.stakingId == stakingId }
|
||||
?: StakingBalance.Error(stakingId = stakingId)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ class CurrencyStatusProxyCreator {
|
|||
currency = currency,
|
||||
quoteStatus = quote,
|
||||
networkStatus = networkStatus,
|
||||
yieldBalance = yieldBalance,
|
||||
stakingBalance = stakingBalance,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -85,13 +85,13 @@ class CurrencyStatusProxyCreator {
|
|||
currency: CryptoCurrency,
|
||||
quoteStatus: QuoteStatus?,
|
||||
networkStatus: NetworkStatus?,
|
||||
yieldBalance: YieldBalance?,
|
||||
stakingBalance: StakingBalance?,
|
||||
): CryptoCurrencyStatus {
|
||||
return CryptoCurrencyStatusFactory.create(
|
||||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.toOption(),
|
||||
maybeQuoteStatus = quoteStatus.toOption(),
|
||||
maybeYieldBalance = yieldBalance.toOption(),
|
||||
maybeStakingBalance = stakingBalance.toOption(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
|
|
@ -31,7 +31,7 @@ import timber.log.Timber
|
|||
* @property singleWalletBalanceFetcher balance fetcher of single-currency wallet
|
||||
* @property multiNetworkStatusFetcher networks statuses fetcher
|
||||
* @property multiQuoteStatusFetcher quotes statuses fetcher
|
||||
* @property multiYieldBalanceFetcher yields balances fetcher
|
||||
* @property multiStakingBalanceFetcher yields balances fetcher
|
||||
* @property dispatchers dispatchers
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -44,7 +44,7 @@ class WalletBalanceFetcher internal constructor(
|
|||
private val singleWalletBalanceFetcher: BaseWalletBalanceFetcher,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : FlowFetcher<WalletBalanceFetcher.Params> {
|
||||
|
|
@ -56,7 +56,7 @@ class WalletBalanceFetcher internal constructor(
|
|||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
) : this(
|
||||
|
|
@ -71,7 +71,7 @@ class WalletBalanceFetcher internal constructor(
|
|||
singleWalletBalanceFetcher = SingleWalletBalanceFetcher(currenciesRepository = currenciesRepository),
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher = multiStakingBalanceFetcher,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
|
|
@ -164,8 +164,8 @@ class WalletBalanceFetcher internal constructor(
|
|||
val stakingIds = maybeStakingIds.mapNotNullTo(hashSetOf()) { it.getOrNull() }
|
||||
|
||||
if (stakingIds.isNotEmpty()) {
|
||||
multiYieldBalanceFetcher(
|
||||
params = MultiYieldBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds),
|
||||
multiStakingBalanceFetcher(
|
||||
params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds),
|
||||
)
|
||||
.bind()
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ internal object MockTokensStates {
|
|||
networkAddress = requireNotNull(
|
||||
value = MockNetworks.verifiedNetworksStatuses.first { it.network == status.currency.network }.value as? NetworkStatus.Verified,
|
||||
).address,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
sources = CryptoCurrencyStatus.Sources(),
|
||||
yieldSupplyStatus = null,
|
||||
)
|
||||
|
|
@ -166,7 +166,7 @@ internal object MockTokensStates {
|
|||
pendingTransactions = emptySet(),
|
||||
hasCurrentNetworkTransactions = false,
|
||||
networkAddress = requireNotNull(networkStatus.value as? NetworkStatus.Verified).address,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
sources = CryptoCurrencyStatus.Sources(),
|
||||
yieldSupplyStatus = null,
|
||||
)
|
||||
|
|
@ -185,7 +185,7 @@ internal object MockTokensStates {
|
|||
.first { it.network == status.currency.network }
|
||||
.value as? NetworkStatus.Verified,
|
||||
).address,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
sources = CryptoCurrencyStatus.Sources(),
|
||||
yieldSupplyStatus = null,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import com.tangem.domain.models.network.NetworkStatus.Amount
|
|||
import com.tangem.domain.models.network.TxInfo
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.staking.BalanceItem
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.YieldBalanceItem
|
||||
import com.tangem.domain.models.yield.supply.YieldSupplyStatus
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
|
|
@ -54,7 +54,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
inner class MissedDerivation {
|
||||
|
||||
private val networkStatus = NetworkStatus.MissedDerivation.toStatus()
|
||||
private val maybeYieldBalance = none<YieldBalance>() // not relevant for this test
|
||||
private val maybeStakingBalance = none<StakingBalance>() // not relevant for this test
|
||||
|
||||
@Test
|
||||
fun `network is MissedDerivation and QuoteStatus is Data`() {
|
||||
|
|
@ -63,7 +63,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = fullQuote.toStatus().some(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -82,7 +82,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = emptyQuoteStatus.some(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -97,7 +97,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = none(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -112,7 +112,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
|
||||
private val networkStatus = NetworkStatus.Unreachable(address = networkAddress).toStatus()
|
||||
|
||||
private val maybeYieldBalance = none<YieldBalance>() // not relevant for this test
|
||||
private val maybeStakingBalance = none<StakingBalance>() // not relevant for this test
|
||||
|
||||
@Test
|
||||
fun `network is Unreachable and QuoteStatus is Data`() {
|
||||
|
|
@ -121,7 +121,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = fullQuote.toStatus().some(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -141,7 +141,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = emptyQuoteStatus.some(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -161,7 +161,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = none(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -185,7 +185,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
source = StatusSource.ACTUAL,
|
||||
).toStatus()
|
||||
|
||||
private val maybeYieldBalance = none<YieldBalance>() // not relevant for this test
|
||||
private val maybeStakingBalance = none<StakingBalance>() // not relevant for this test
|
||||
|
||||
@Test
|
||||
fun `network is NoAccount and QuoteStatus is Data`() {
|
||||
|
|
@ -194,7 +194,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = fullQuote.toStatus().some(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -217,7 +217,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = emptyQuoteStatus.some(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -239,7 +239,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = none(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -261,7 +261,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
|
||||
private val networkStatus = createVerified(amounts = mapOf(currency.id to Amount.NotFound)).toStatus()
|
||||
|
||||
private val maybeYieldBalance = none<YieldBalance>() // not relevant for this test
|
||||
private val maybeStakingBalance = none<StakingBalance>() // not relevant for this test
|
||||
|
||||
@Test
|
||||
fun `network is Verified with Amount is NotFound and QuoteStatus is Data`() {
|
||||
|
|
@ -270,7 +270,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = fullQuote.toStatus().some(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -289,7 +289,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = emptyQuoteStatus.some(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -304,7 +304,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = none(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -317,7 +317,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class Loading {
|
||||
|
||||
private val maybeYieldBalance = none<YieldBalance>() // not relevant for this test
|
||||
private val maybeStakingBalance = none<StakingBalance>() // not relevant for this test
|
||||
|
||||
@Test
|
||||
fun `network is null`() {
|
||||
|
|
@ -326,7 +326,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = none(),
|
||||
maybeQuoteStatus = none(), // not relevant for this test,
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -344,7 +344,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = none(), // not relevant for this test,
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -364,7 +364,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = none(),
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -387,14 +387,14 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
fun `network is Verified, QuoteStatus is null, YieldBalance is null`() {
|
||||
// Arrange
|
||||
val maybeQuoteStatus = none<QuoteStatus>()
|
||||
val maybeYieldBalance = none<YieldBalance>()
|
||||
val maybeStakingBalance = none<StakingBalance>()
|
||||
|
||||
// Act
|
||||
val actual = CryptoCurrencyStatusFactory.create(
|
||||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = maybeQuoteStatus,
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -405,7 +405,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
fiatAmount = null,
|
||||
fiatRate = null,
|
||||
priceChange = null,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
@ -420,7 +420,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
@Test
|
||||
fun `network is Verified, QuoteStatus is Data, YieldBalance is Data`() {
|
||||
// Arrange
|
||||
val yieldBalance = YieldBalance.Data(
|
||||
val stakeKitBalance = StakingBalance.Data.StakeKit(
|
||||
stakingId = StakingID(
|
||||
integrationId = StakingIntegrationID.StakeKit.Coin.Cardano.value,
|
||||
address = networkAddress.defaultAddress.value,
|
||||
|
|
@ -444,7 +444,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = fullQuote.toStatus().some(),
|
||||
maybeYieldBalance = yieldBalance.some(),
|
||||
maybeStakingBalance = stakeKitBalance.some(),
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -455,9 +455,9 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
fiatAmount = BigDecimal.TEN * fullQuote.fiatRate,
|
||||
fiatRate = fullQuote.fiatRate,
|
||||
priceChange = fullQuote.priceChange,
|
||||
yieldBalance = yieldBalance.copy(
|
||||
balance = yieldBalance.balance.copy(
|
||||
items = yieldBalance.balance.items.subList(0, 1),
|
||||
stakingBalance = stakeKitBalance.copy(
|
||||
balance = stakeKitBalance.balance.copy(
|
||||
items = stakeKitBalance.balance.items.subList(0, 1),
|
||||
),
|
||||
),
|
||||
yieldSupplyStatus = null,
|
||||
|
|
@ -490,20 +490,20 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
@Test
|
||||
fun `network is Verified and YieldBalance is null`() {
|
||||
// Arrange
|
||||
val maybeYieldBalance = none<YieldBalance>()
|
||||
val maybeStakingBalance = none<StakingBalance>()
|
||||
|
||||
// Act
|
||||
val actual = CryptoCurrencyStatusFactory.create(
|
||||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = maybeQuoteStatus,
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
val expected = CryptoCurrencyStatus.NoQuote(
|
||||
amount = BigDecimal.TEN,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = yieldSupplyStatuses[currency.id]!!,
|
||||
hasCurrentNetworkTransactions = true,
|
||||
pendingTransactions = pendingTransactions[currency.id]!!,
|
||||
|
|
@ -517,7 +517,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
@Test
|
||||
fun `network is Verified and YieldBalance is Data`() {
|
||||
// Arrange
|
||||
val yieldBalance = YieldBalance.Data(
|
||||
val stakeKitBalance = StakingBalance.Data.StakeKit(
|
||||
stakingId = StakingID(
|
||||
integrationId = StakingIntegrationID.StakeKit.Coin.Cardano.value,
|
||||
address = networkAddress.defaultAddress.value,
|
||||
|
|
@ -541,15 +541,15 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = maybeQuoteStatus,
|
||||
maybeYieldBalance = yieldBalance.some(),
|
||||
maybeStakingBalance = stakeKitBalance.some(),
|
||||
)
|
||||
|
||||
// Assert
|
||||
val expected = CryptoCurrencyStatus.NoQuote(
|
||||
amount = BigDecimal.TEN,
|
||||
yieldBalance = yieldBalance.copy(
|
||||
balance = yieldBalance.balance.copy(
|
||||
items = yieldBalance.balance.items.subList(0, 1),
|
||||
stakingBalance = stakeKitBalance.copy(
|
||||
balance = stakeKitBalance.balance.copy(
|
||||
items = stakeKitBalance.balance.items.subList(0, 1),
|
||||
),
|
||||
),
|
||||
yieldSupplyStatus = yieldSupplyStatuses[currency.id]!!,
|
||||
|
|
@ -576,14 +576,14 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
@Test
|
||||
fun `network is Verified and YieldBalance is null`() {
|
||||
// Arrange
|
||||
val maybeYieldBalance = none<YieldBalance>()
|
||||
val maybeStakingBalance = none<StakingBalance>()
|
||||
|
||||
// Act
|
||||
val actual = CryptoCurrencyStatusFactory.create(
|
||||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = maybeQuoteStatus,
|
||||
maybeYieldBalance = maybeYieldBalance,
|
||||
maybeStakingBalance = maybeStakingBalance,
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -592,7 +592,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
fiatAmount = BigDecimal.TEN * fullQuote.fiatRate,
|
||||
fiatRate = fullQuote.fiatRate,
|
||||
priceChange = fullQuote.priceChange,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
@ -606,7 +606,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
@Test
|
||||
fun `network is Verified and YieldBalance is Data`() {
|
||||
// Arrange
|
||||
val yieldBalance = YieldBalance.Data(
|
||||
val stakeKitBalance = StakingBalance.Data.StakeKit(
|
||||
stakingId = StakingID(
|
||||
integrationId = StakingIntegrationID.StakeKit.Coin.Cardano.value,
|
||||
address = networkAddress.defaultAddress.value,
|
||||
|
|
@ -630,7 +630,7 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
currency = currency,
|
||||
maybeNetworkStatus = networkStatus.some(),
|
||||
maybeQuoteStatus = fullQuote.toStatus().some(),
|
||||
maybeYieldBalance = yieldBalance.some(),
|
||||
maybeStakingBalance = stakeKitBalance.some(),
|
||||
)
|
||||
|
||||
// Assert
|
||||
|
|
@ -639,9 +639,9 @@ class CryptoCurrencyStatusFactoryTest {
|
|||
fiatAmount = BigDecimal.TEN * fullQuote.fiatRate,
|
||||
fiatRate = fullQuote.fiatRate,
|
||||
priceChange = fullQuote.priceChange,
|
||||
yieldBalance = yieldBalance.copy(
|
||||
balance = yieldBalance.balance.copy(
|
||||
items = yieldBalance.balance.items.subList(0, 1),
|
||||
stakingBalance = stakeKitBalance.copy(
|
||||
balance = stakeKitBalance.balance.copy(
|
||||
items = stakeKitBalance.balance.items.subList(0, 1),
|
||||
),
|
||||
),
|
||||
yieldSupplyStatus = null,
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ class PriceChangeCalculatorTest {
|
|||
fiatAmount = amount,
|
||||
fiatRate = BigDecimal.ONE,
|
||||
priceChange = priceChange,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
|||
import com.tangem.domain.models.network.NetworkAddress
|
||||
import com.tangem.domain.models.staking.BalanceItem
|
||||
import com.tangem.domain.models.staking.BalanceType
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.YieldBalanceItem
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
|
|
@ -192,7 +192,7 @@ class TotalFiatBalanceCalculatorTest {
|
|||
createCustom(
|
||||
currency = cryptoCurrencyFactory.cardano,
|
||||
fiatAmount = BigDecimal.ZERO,
|
||||
yieldBalance = createYieldBalance(
|
||||
stakingBalance = createStakeKitBalance(
|
||||
amount = BigDecimal(20),
|
||||
// It is important to use `BalanceType.REWARDS` because Cardano should not include the full
|
||||
// staking balance. See `getTotalWithRewardsStakingBalance`.
|
||||
|
|
@ -207,7 +207,7 @@ class TotalFiatBalanceCalculatorTest {
|
|||
createCustom(
|
||||
currency = cryptoCurrencyFactory.stellar,
|
||||
fiatAmount = BigDecimal.ONE,
|
||||
yieldBalance = createYieldBalance(
|
||||
stakingBalance = createStakeKitBalance(
|
||||
amount = BigDecimal(9),
|
||||
balanceType = BalanceType.STAKED,
|
||||
),
|
||||
|
|
@ -246,7 +246,7 @@ class TotalFiatBalanceCalculatorTest {
|
|||
createLoaded(
|
||||
currency = cryptoCurrencyFactory.cardano,
|
||||
fiatAmount = BigDecimal.ZERO,
|
||||
yieldBalance = createYieldBalance(
|
||||
stakingBalance = createStakeKitBalance(
|
||||
amount = BigDecimal(20),
|
||||
// It is important to use `BalanceType.REWARDS` because Cardano should not include the full
|
||||
// staking balance. See `getTotalWithRewardsStakingBalance`.
|
||||
|
|
@ -261,7 +261,7 @@ class TotalFiatBalanceCalculatorTest {
|
|||
createLoaded(
|
||||
currency = cryptoCurrencyFactory.stellar,
|
||||
fiatAmount = BigDecimal.ONE,
|
||||
yieldBalance = createYieldBalance(
|
||||
stakingBalance = createStakeKitBalance(
|
||||
amount = BigDecimal(9),
|
||||
balanceType = BalanceType.STAKED,
|
||||
),
|
||||
|
|
@ -497,7 +497,7 @@ class TotalFiatBalanceCalculatorTest {
|
|||
currency = currency,
|
||||
value = CryptoCurrencyStatus.NoQuote(
|
||||
amount = BigDecimal.ONE,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
@ -545,7 +545,7 @@ class TotalFiatBalanceCalculatorTest {
|
|||
private fun createCustom(
|
||||
currency: CryptoCurrency,
|
||||
fiatAmount: BigDecimal?,
|
||||
yieldBalance: YieldBalance? = null,
|
||||
stakingBalance: StakingBalance.Data.StakeKit? = null,
|
||||
): CryptoCurrencyStatus {
|
||||
return CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
|
|
@ -554,7 +554,7 @@ class TotalFiatBalanceCalculatorTest {
|
|||
fiatAmount = fiatAmount,
|
||||
fiatRate = BigDecimal.ONE,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
yieldBalance = yieldBalance,
|
||||
stakingBalance = stakingBalance,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
@ -567,7 +567,7 @@ class TotalFiatBalanceCalculatorTest {
|
|||
private fun createLoaded(
|
||||
currency: CryptoCurrency,
|
||||
fiatAmount: BigDecimal,
|
||||
yieldBalance: YieldBalance? = null,
|
||||
stakingBalance: StakingBalance.Data.StakeKit? = null,
|
||||
source: StatusSource = StatusSource.ACTUAL,
|
||||
): CryptoCurrencyStatus {
|
||||
return CryptoCurrencyStatus(
|
||||
|
|
@ -577,7 +577,7 @@ class TotalFiatBalanceCalculatorTest {
|
|||
fiatAmount = fiatAmount,
|
||||
fiatRate = BigDecimal.ONE,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
yieldBalance = yieldBalance,
|
||||
stakingBalance = stakingBalance,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
@ -587,8 +587,8 @@ class TotalFiatBalanceCalculatorTest {
|
|||
)
|
||||
}
|
||||
|
||||
private fun createYieldBalance(amount: BigDecimal, balanceType: BalanceType): YieldBalance.Data {
|
||||
return YieldBalance.Data(
|
||||
private fun createStakeKitBalance(amount: BigDecimal, balanceType: BalanceType): StakingBalance.Data.StakeKit {
|
||||
return StakingBalance.Data.StakeKit(
|
||||
stakingId = mockk(),
|
||||
source = StatusSource.ACTUAL,
|
||||
balance = YieldBalanceItem(
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
|
|||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.wallet.FetchingSource.*
|
||||
import com.tangem.domain.tokens.wallet.implementor.MultiWalletBalanceFetcher
|
||||
|
|
@ -41,7 +41,7 @@ internal class WalletBalanceFetcherTest {
|
|||
private val singleWalletBalanceFetcher: SingleWalletBalanceFetcher = mockk()
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher = mockk()
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher = mockk()
|
||||
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher = mockk()
|
||||
private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher = mockk()
|
||||
private val stakingIdFactory: StakingIdFactory = mockk()
|
||||
|
||||
private val fetcher = WalletBalanceFetcher(
|
||||
|
|
@ -51,7 +51,7 @@ internal class WalletBalanceFetcherTest {
|
|||
singleWalletBalanceFetcher = singleWalletBalanceFetcher,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher = multiStakingBalanceFetcher,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
|
@ -65,7 +65,7 @@ internal class WalletBalanceFetcherTest {
|
|||
singleWalletBalanceFetcher,
|
||||
multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher,
|
||||
multiYieldBalanceFetcher,
|
||||
multiStakingBalanceFetcher,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ internal class WalletBalanceFetcherTest {
|
|||
multiNetworkStatusFetcher(params = any())
|
||||
multiQuoteStatusFetcher(params = any())
|
||||
stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ internal class WalletBalanceFetcherTest {
|
|||
multiNetworkStatusFetcher(params = any())
|
||||
multiQuoteStatusFetcher(params = any())
|
||||
stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ internal class WalletBalanceFetcherTest {
|
|||
multiNetworkStatusFetcher(params = any())
|
||||
multiQuoteStatusFetcher(params = any())
|
||||
stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ internal class WalletBalanceFetcherTest {
|
|||
multiNetworkStatusFetcher(params = any())
|
||||
multiQuoteStatusFetcher(params = any())
|
||||
stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ internal class WalletBalanceFetcherTest {
|
|||
singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any())
|
||||
multiQuoteStatusFetcher(params = any())
|
||||
stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ internal class WalletBalanceFetcherTest {
|
|||
singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any())
|
||||
multiNetworkStatusFetcher(params = any())
|
||||
stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -292,7 +292,7 @@ internal class WalletBalanceFetcherTest {
|
|||
}
|
||||
|
||||
val currencies = cryptoCurrencyFactory.ethereumAndStellar.toSet()
|
||||
val yieldBalanceFetcherParams = MultiYieldBalanceFetcher.Params(
|
||||
val stakingBalanceFetcherParams = MultiStakingBalanceFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
stakingIds = setOf(ethereumStakingId, stellarStakingId),
|
||||
)
|
||||
|
|
@ -308,7 +308,7 @@ internal class WalletBalanceFetcherTest {
|
|||
coEvery {
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar)
|
||||
} returns Either.Right(stellarStakingId)
|
||||
coEvery { multiYieldBalanceFetcher(params = yieldBalanceFetcherParams) } returns exception.left()
|
||||
coEvery { multiStakingBalanceFetcher(params = stakingBalanceFetcherParams) } returns exception.left()
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params = WalletBalanceFetcher.Params(userWalletId = userWalletId))
|
||||
|
|
@ -326,7 +326,7 @@ internal class WalletBalanceFetcherTest {
|
|||
multiWalletBalanceFetcher.fetchingSources
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.ethereum)
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar)
|
||||
multiYieldBalanceFetcher(params = yieldBalanceFetcherParams)
|
||||
multiStakingBalanceFetcher(params = stakingBalanceFetcherParams)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
|
|
@ -372,7 +372,7 @@ internal class WalletBalanceFetcherTest {
|
|||
singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any())
|
||||
multiNetworkStatusFetcher(params = any())
|
||||
multiQuoteStatusFetcher(params = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -414,7 +414,7 @@ internal class WalletBalanceFetcherTest {
|
|||
singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any())
|
||||
multiNetworkStatusFetcher(params = any())
|
||||
multiQuoteStatusFetcher(params = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -462,7 +462,7 @@ internal class WalletBalanceFetcherTest {
|
|||
singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any())
|
||||
multiNetworkStatusFetcher(params = any())
|
||||
multiQuoteStatusFetcher(params = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -485,7 +485,7 @@ internal class WalletBalanceFetcherTest {
|
|||
appCurrencyId = null,
|
||||
)
|
||||
|
||||
val yieldBalanceFetcherParams = MultiYieldBalanceFetcher.Params(
|
||||
val stakingBalanceFetcherParams = MultiStakingBalanceFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
stakingIds = setOf(ethereumStakingId, stellarStakingId),
|
||||
)
|
||||
|
|
@ -503,7 +503,7 @@ internal class WalletBalanceFetcherTest {
|
|||
coEvery {
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar)
|
||||
} returns Either.Right(stellarStakingId)
|
||||
coEvery { multiYieldBalanceFetcher(params = yieldBalanceFetcherParams) } returns exception.left()
|
||||
coEvery { multiStakingBalanceFetcher(params = stakingBalanceFetcherParams) } returns exception.left()
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params = WalletBalanceFetcher.Params(userWalletId = userWalletId))
|
||||
|
|
@ -525,7 +525,7 @@ internal class WalletBalanceFetcherTest {
|
|||
multiQuoteStatusFetcher(params = quoteStatusFetcherParams)
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.ethereum)
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar)
|
||||
multiYieldBalanceFetcher(params = yieldBalanceFetcherParams)
|
||||
multiStakingBalanceFetcher(params = stakingBalanceFetcherParams)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
|
|
@ -553,7 +553,7 @@ internal class WalletBalanceFetcherTest {
|
|||
appCurrencyId = null,
|
||||
)
|
||||
|
||||
val yieldBalanceFetcherParams = MultiYieldBalanceFetcher.Params(
|
||||
val stakingBalanceFetcherParams = MultiStakingBalanceFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
stakingIds = setOf(ethereumStakingId, stellarStakingId),
|
||||
)
|
||||
|
|
@ -569,7 +569,7 @@ internal class WalletBalanceFetcherTest {
|
|||
coEvery {
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar)
|
||||
} returns Either.Right(stellarStakingId)
|
||||
coEvery { multiYieldBalanceFetcher(params = yieldBalanceFetcherParams) } returns Unit.right()
|
||||
coEvery { multiStakingBalanceFetcher(params = stakingBalanceFetcherParams) } returns Unit.right()
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params = WalletBalanceFetcher.Params(userWalletId = userWalletId))
|
||||
|
|
@ -586,7 +586,7 @@ internal class WalletBalanceFetcherTest {
|
|||
multiQuoteStatusFetcher(params = quoteStatusFetcherParams)
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.ethereum)
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar)
|
||||
multiYieldBalanceFetcher(params = yieldBalanceFetcherParams)
|
||||
multiStakingBalanceFetcher(params = stakingBalanceFetcherParams)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
|
|
@ -642,7 +642,7 @@ internal class WalletBalanceFetcherTest {
|
|||
multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any())
|
||||
singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any())
|
||||
stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -692,7 +692,7 @@ internal class WalletBalanceFetcherTest {
|
|||
multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any())
|
||||
singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any())
|
||||
stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any())
|
||||
multiYieldBalanceFetcher(params = any())
|
||||
multiStakingBalanceFetcher(params = any())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class YieldSupplyMinAmountUseCaseTest {
|
|||
fiatAmount = BigDecimal.ZERO,
|
||||
fiatRate = tokenFiatRate,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
@ -103,7 +103,7 @@ class YieldSupplyMinAmountUseCaseTest {
|
|||
fiatAmount = null,
|
||||
fiatRate = null,
|
||||
priceChange = null,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
@ -131,7 +131,7 @@ class YieldSupplyMinAmountUseCaseTest {
|
|||
fiatAmount = BigDecimal.ZERO,
|
||||
fiatRate = BigDecimal.ONE,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class YieldSupplyGetRewardsBalanceUseCaseTest {
|
|||
fiatAmount = null,
|
||||
fiatRate = BigDecimal.ONE,
|
||||
priceChange = null,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
@ -90,7 +90,7 @@ class YieldSupplyGetRewardsBalanceUseCaseTest {
|
|||
fiatAmount = null,
|
||||
fiatRate = BigDecimal.ONE,
|
||||
priceChange = null,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
@ -135,7 +135,7 @@ class YieldSupplyGetRewardsBalanceUseCaseTest {
|
|||
fiatAmount = null,
|
||||
fiatRate = BigDecimal.ONE,
|
||||
priceChange = null,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ class FeeCalculationUtilsTest {
|
|||
fiatAmount = BigDecimal.ZERO,
|
||||
fiatRate = BigDecimal.ZERO,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
yieldBalance = null,
|
||||
stakingBalance = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
networkAddress = mockk(relaxed = true),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<ID>BooleanPropertyNaming:AddStakingNotificationsTransformer.kt$AddStakingNotificationsTransformer$val showNotification = sendingAmount + feeAmount > balance</ID>
|
||||
<ID>BooleanPropertyNaming:AmountCurrencyChangeStateTransformer.kt$AmountCurrencyChangeStateTransformer$private val value: Boolean</ID>
|
||||
<ID>BooleanPropertyNaming:StakingModel.kt$StakingModel$val noBalanceState = balanceState == null</ID>
|
||||
<ID>BooleanPropertyNaming:StakingModel.kt$StakingModel$val noYieldBalanceData = cryptoCurrencyStatus.value.yieldBalance !is YieldBalance.Data</ID>
|
||||
<ID>BooleanPropertyNaming:StakingUiState.kt$StakingStates.InitialInfoState.Data$val showBanner: Boolean</ID>
|
||||
<ID>BooleanPropertyNaming:StakingUiState.kt$StakingUiState$val showColdWalletInteractionIcon: Boolean</ID>
|
||||
<ID>CanBeNonNullable:StakingScreen.kt$bottomSheetConfig: TangemBottomSheetConfig?</ID>
|
||||
|
|
@ -42,7 +41,6 @@
|
|||
<ID>UnnecessaryLet:StakingTosText.kt$let { onTextClick(PRIVACY_POLICY_URL) }</ID>
|
||||
<ID>UnnecessaryLet:StakingTosText.kt$let { onTextClick(TERMS_OF_USE_URL) }</ID>
|
||||
<ID>UnsafeCallOnNullableType:StakingModel.kt$StakingModel$tonAccountInitializeTransaction!!</ID>
|
||||
<ID>UseOrEmpty:StakingModel.kt$StakingModel$yieldBalance?.balance?.items ?: emptyList()</ID>
|
||||
<ID>UseOrEmpty:StakingTransactionSender.kt$StakingTransactionSender$getExplorerTransactionUrlUseCase( txHash = transactionHashes.last(), networkId = cryptoCurrencyStatus.currency.network.id, ).getOrNull() ?: ""</ID>
|
||||
<ID>VarCouldBeVal:StakingModel.kt$StakingModel$private var actionsJobHolder: JobHolder = JobHolder()</ID>
|
||||
<ID>VarCouldBeVal:StakingModel.kt$StakingModel$private var approvalJobHolder: JobHolder = JobHolder()</ID>
|
||||
|
|
|
|||
|
|
@ -190,9 +190,9 @@ internal class StakingModel @Inject constructor(
|
|||
|
||||
private val balancesToShow: List<BalanceItem>
|
||||
get() {
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data
|
||||
val stakeKitBalance = cryptoCurrencyStatus.value.stakingBalance as? StakingBalance.Data.StakeKit
|
||||
return invalidatePendingTransactionsUseCase(
|
||||
balanceItems = yieldBalance?.balance?.items ?: emptyList(),
|
||||
balanceItems = stakeKitBalance?.balance?.items.orEmpty(),
|
||||
stakingActions = stakingActions,
|
||||
token = yield.token,
|
||||
).getOrElse { emptyList() }
|
||||
|
|
@ -277,10 +277,10 @@ internal class StakingModel @Inject constructor(
|
|||
modelScope.launch {
|
||||
val isInitialInfoStep = value.currentStep == StakingStep.InitialInfo
|
||||
val noBalanceState = balanceState == null
|
||||
val noYieldBalanceData = cryptoCurrencyStatus.value.yieldBalance !is YieldBalance.Data
|
||||
val hasNoYieldBalanceData = cryptoCurrencyStatus.value.stakingBalance !is StakingBalance.Data.StakeKit
|
||||
|
||||
when {
|
||||
isInitialInfoStep && noBalanceState && yield.allValidatorsFull && noYieldBalanceData -> {
|
||||
isInitialInfoStep && noBalanceState && yield.allValidatorsFull && hasNoYieldBalanceData -> {
|
||||
stakingEventFactory.createStakingValidatorsUnavailableAlert()
|
||||
return@launch
|
||||
}
|
||||
|
|
@ -1116,7 +1116,7 @@ internal class StakingModel @Inject constructor(
|
|||
private suspend fun onDataLoaded(status: CryptoCurrencyStatus) {
|
||||
if (!isInitialInfoAnalyticSent) {
|
||||
isInitialInfoAnalyticSent = true
|
||||
val balances = status.value.yieldBalance as? YieldBalance.Data
|
||||
val balances = status.value.stakingBalance as? StakingBalance.Data.StakeKit
|
||||
paramsInterceptorHolder.addParamsInterceptor(
|
||||
interceptor = StakingParamsInterceptor(status.currency.symbol),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
|||
import com.tangem.domain.models.staking.BalanceItem
|
||||
import com.tangem.domain.models.staking.BalanceType
|
||||
import com.tangem.domain.models.staking.BalanceType.Companion.isClickable
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.action.StakingActionType
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.utils.getRewardStakingBalance
|
||||
|
|
@ -77,11 +77,11 @@ internal class BalanceItemConverter(
|
|||
val isIncludeStakingTotalBalance = BlockchainUtils.isIncludeStakingTotalBalance(
|
||||
blockchainId = cryptoCurrencyStatus.currency.network.rawId,
|
||||
)
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data
|
||||
val stakeKitBalance = cryptoCurrencyStatus.value.stakingBalance as? StakingBalance.Data.StakeKit
|
||||
return if (isIncludeStakingTotalBalance) {
|
||||
amount
|
||||
} else {
|
||||
amount - yieldBalance?.getRewardStakingBalance().orZero()
|
||||
amount - stakeKitBalance?.getRewardStakingBalance().orZero()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency
|
|||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.staking.BalanceItem
|
||||
import com.tangem.domain.models.staking.BalanceType
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.features.staking.impl.presentation.state.BalanceState
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
|
|
@ -24,9 +24,9 @@ internal class RewardsValidatorStateConverter(
|
|||
private val yield: Yield,
|
||||
) : Converter<Unit, StakingStates.RewardsValidatorsState> {
|
||||
override fun convert(value: Unit): StakingStates.RewardsValidatorsState {
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance
|
||||
return if (yieldBalance is YieldBalance.Data) {
|
||||
val balances = yieldBalance.balance.items
|
||||
val stakingBalance = cryptoCurrencyStatus.value.stakingBalance
|
||||
return if (stakingBalance is StakingBalance.Data.StakeKit) {
|
||||
val balances = stakingBalance.balance.items
|
||||
StakingStates.RewardsValidatorsState.Data(
|
||||
isPrimaryButtonEnabled = true,
|
||||
rewards = balances
|
||||
|
|
@ -35,6 +35,7 @@ internal class RewardsValidatorStateConverter(
|
|||
.toPersistentList(),
|
||||
)
|
||||
} else {
|
||||
// TODO p2p
|
||||
StakingStates.RewardsValidatorsState.Empty()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
|||
import com.tangem.domain.models.staking.BalanceItem
|
||||
import com.tangem.domain.models.staking.BalanceType
|
||||
import com.tangem.domain.models.staking.RewardBlockType
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.action.StakingActionType
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.utils.getRewardStakingBalance
|
||||
|
|
@ -36,11 +36,11 @@ internal class YieldBalancesConverter(
|
|||
val appCurrency = appCurrencyProvider()
|
||||
|
||||
val cryptoCurrency = cryptoCurrencyStatus.currency
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data
|
||||
val stakeKitBalance = cryptoCurrencyStatus.value.stakingBalance as? StakingBalance.Data.StakeKit
|
||||
val balanceToShowItems = balancesToShowProvider()
|
||||
|
||||
return if (yieldBalance != null || balanceToShowItems.any { it.isPending }) {
|
||||
val cryptoRewardsValue = yieldBalance?.getRewardStakingBalance()
|
||||
return if (stakeKitBalance != null || balanceToShowItems.any { it.isPending }) {
|
||||
val cryptoRewardsValue = stakeKitBalance?.getRewardStakingBalance()
|
||||
|
||||
val fiatRate = cryptoCurrencyStatus.value.fiatRate
|
||||
val fiatRewardsValue = if (fiatRate != null && cryptoRewardsValue != null) {
|
||||
|
|
@ -49,13 +49,13 @@ internal class YieldBalancesConverter(
|
|||
null
|
||||
}
|
||||
val type = getRewardBlockType()
|
||||
val pendingRewardsConstraints = yieldBalance?.balance?.items
|
||||
val pendingRewardsConstraints = stakeKitBalance?.balance?.items
|
||||
?.firstOrNull { it.type == BalanceType.REWARDS }
|
||||
?.pendingActionsConstraints
|
||||
?.firstOrNull { it.type == StakingActionType.CLAIM_REWARDS }
|
||||
|
||||
InnerYieldBalanceState.Data(
|
||||
integrationId = yieldBalance?.stakingId?.integrationId,
|
||||
integrationId = stakeKitBalance?.stakingId?.integrationId,
|
||||
reward = YieldReward(
|
||||
rewardsCrypto = cryptoRewardsValue.format { crypto(cryptoCurrency) },
|
||||
rewardsFiat = fiatRewardsValue.format {
|
||||
|
|
@ -71,6 +71,7 @@ internal class YieldBalancesConverter(
|
|||
balances = balanceToShowItems.mapBalances(),
|
||||
)
|
||||
} else {
|
||||
// TODO p2p
|
||||
InnerYieldBalanceState.Empty
|
||||
}
|
||||
}
|
||||
|
|
@ -84,8 +85,8 @@ internal class YieldBalancesConverter(
|
|||
|
||||
private fun getRewardBlockType(): RewardBlockType {
|
||||
val blockchainId = cryptoCurrencyStatus.currency.network.rawId
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data
|
||||
val rewards = yieldBalance?.balance?.items
|
||||
val stakeKitBalance = cryptoCurrencyStatus.value.stakingBalance as? StakingBalance.Data.StakeKit
|
||||
val rewards = stakeKitBalance?.balance?.items
|
||||
?.filter { it.type == BalanceType.REWARDS && !it.amount.isZero() }
|
||||
|
||||
val isActionable = rewards?.any { it.pendingActions.isNotEmpty() } == true
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ internal class SetConfirmationStateAssentTransformer(
|
|||
isFeeApproximate = isFeeApproximate,
|
||||
),
|
||||
isPrimaryButtonEnabled = with(cryptoCurrencyStatus.value) {
|
||||
sources.yieldBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
sources.stakingBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
},
|
||||
)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ internal class SetConfirmationStateCompletedTransformer(
|
|||
return if (this is StakingStates.ConfirmationState.Data) {
|
||||
copy(
|
||||
isPrimaryButtonEnabled = with(cryptoCurrencyStatus.value) {
|
||||
sources.yieldBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
sources.stakingBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
},
|
||||
innerState = InnerConfirmationStakingState.COMPLETED,
|
||||
footerText = TextReference.EMPTY,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ internal class SetConfirmationStateResetAssentTransformer(
|
|||
confirmationState = if (confirmationState is StakingStates.ConfirmationState.Data) {
|
||||
confirmationState.copy(
|
||||
isPrimaryButtonEnabled = with(cryptoCurrencyStatus.value) {
|
||||
sources.yieldBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
sources.stakingBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
},
|
||||
innerState = InnerConfirmationStakingState.ASSENT,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ internal class SetInitialDataStateTransformer(
|
|||
val status = cryptoCurrencyStatus.value
|
||||
return StakingStates.InitialInfoState.Data(
|
||||
isPrimaryButtonEnabled = with(status) {
|
||||
!amount.isNullOrZero() && sources.yieldBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
!amount.isNullOrZero() && sources.stakingBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
},
|
||||
showBanner = !isAnyTokenStaked && yieldBalance == InnerYieldBalanceState.Empty,
|
||||
infoItems = getInfoItems(),
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ internal class SetConfirmationStateAssentApprovalTransformer(
|
|||
isFeeApproximate = false,
|
||||
),
|
||||
isPrimaryButtonEnabled = with(cryptoCurrencyStatus.value) {
|
||||
sources.yieldBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
sources.stakingBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
},
|
||||
isApprovalNeeded = true,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ internal class AddStakingNotificationsTransformer(
|
|||
}
|
||||
|
||||
val isActualSources = with(cryptoCurrencyStatus.value) {
|
||||
sources.yieldBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
sources.stakingBalanceSource.isActual() && sources.networkSource.isActual()
|
||||
}
|
||||
|
||||
return prevState.copy(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.staking.BalanceType
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.action.StakingActionType
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
|
|
@ -134,7 +134,7 @@ internal class StakingInfoNotificationsFactory(
|
|||
private fun MutableList<NotificationUM>.addTronRevoteNotification() {
|
||||
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
|
||||
val isTron = isTron(cryptoCurrencyStatus.currency.network.rawId)
|
||||
val hasStakedBalance = (cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data)?.balance
|
||||
val hasStakedBalance = (cryptoCurrencyStatus.value.stakingBalance as? StakingBalance.Data.StakeKit)?.balance
|
||||
?.items?.any {
|
||||
it.type == BalanceType.PREPARING ||
|
||||
it.type == BalanceType.STAKED ||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
<ID>NullableToStringCall:DefaultTokenDetailsDeepLinkHandler.kt$DefaultTokenDetailsDeepLinkHandler$$tokenId</ID>
|
||||
<ID>NullableToStringCall:TokenDetailsStakingInfoConverter.kt$TokenDetailsStakingInfoConverter$$stakingCryptoAmount</ID>
|
||||
<ID>NullableToStringCall:TokenDetailsStakingInfoConverter.kt$TokenDetailsStakingInfoConverter$$stakingEntryInfo</ID>
|
||||
<ID>NullableToStringCall:TokenDetailsStakingInfoConverter.kt$TokenDetailsStakingInfoConverter$$yieldBalance</ID>
|
||||
<ID>PropertyUsedBeforeDeclaration:ExpressStatusBottomSheetStateProvider.kt$ExpressStatusBottomSheetStateProvider$network</ID>
|
||||
<ID>PropertyUsedBeforeDeclaration:ExpressStatusBottomSheetStateProvider.kt$ExpressStatusBottomSheetStateProvider$token</ID>
|
||||
<ID>PropertyUsedBeforeDeclaration:TokenDetailsModel.kt$TokenDetailsModel$uiState</ID>
|
||||
|
|
@ -48,7 +47,6 @@
|
|||
<ID>UseEmptyCounterpart:TokenDetailsAnalyticsEvent.kt$TokenDetailsAnalyticsEvent$mapOf()</ID>
|
||||
<ID>UseEmptyCounterpart:TokenDetailsAnalyticsEvent.kt$TokenDetailsAnalyticsEvent.Notice$mapOf()</ID>
|
||||
<ID>UseOrEmpty:ExchangeStatusFactory.kt$ExchangeStatusFactory$savedTransactions ?.flatMap { setOf(it.fromCryptoCurrency.id, it.toCryptoCurrency.id) } ?.toSet() ?.getQuotesOrEmpty() ?: emptySet()</ID>
|
||||
<ID>UseOrEmpty:TokenDetailsStakingInfoConverter.kt$TokenDetailsStakingInfoConverter$yieldBalance?.balance?.items ?: emptyList()</ID>
|
||||
<ID>VarCouldBeVal:TokenDetailsModel.kt$TokenDetailsModel$private var expressTxStatusTaskScheduler = SingleTaskScheduler<PersistentList<ExpressTransactionStateUM>>()</ID>
|
||||
</CurrentIssues>
|
||||
</SmellBaseline>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import com.tangem.core.ui.format.bigdecimal.fiat
|
|||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.staking.utils.getTotalWithRewardsStakingBalance
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.utils.getBalance
|
||||
|
|
@ -29,8 +29,8 @@ internal class TokenDetailsBalanceSelectStateConverter(
|
|||
return this
|
||||
}
|
||||
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data
|
||||
val stakingCryptoAmount = yieldBalance?.getTotalWithRewardsStakingBalance(
|
||||
val stakingBalance = cryptoCurrencyStatus.value.stakingBalance as? StakingBalance.Data
|
||||
val stakingCryptoAmount = stakingBalance?.getTotalWithRewardsStakingBalance(
|
||||
cryptoCurrencyStatus.currency.network.rawId,
|
||||
)
|
||||
val stakingFiatAmount = stakingCryptoAmount?.let { cryptoCurrencyStatus.value.fiatRate?.multiply(it) }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import com.tangem.core.ui.format.bigdecimal.*
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.staking.utils.getTotalWithRewardsStakingBalance
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents
|
||||
|
|
@ -73,7 +73,7 @@ internal class TokenDetailsLoadedBalanceConverter(
|
|||
status: CryptoCurrencyStatus,
|
||||
): TokenDetailsBalanceBlockState {
|
||||
val stakingCryptoAmount =
|
||||
(status.value.yieldBalance as? YieldBalance.Data)?.getTotalWithRewardsStakingBalance(
|
||||
(status.value.stakingBalance as? StakingBalance.Data)?.getTotalWithRewardsStakingBalance(
|
||||
status.currency.network.rawId,
|
||||
)
|
||||
val stakingFiatAmount = stakingCryptoAmount?.let { status.value.fiatRate?.multiply(it) }
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import com.tangem.core.ui.format.bigdecimal.format
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.staking.RewardBlockType
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
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.utils.getRewardStakingBalance
|
||||
|
|
@ -54,18 +54,29 @@ internal class TokenDetailsStakingInfoConverter(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private fun getStakingInfoBlock(status: CryptoCurrencyStatus, state: TokenDetailsState): StakingBlockUM? {
|
||||
val yieldBalance = status.value.yieldBalance as? YieldBalance.Data
|
||||
val stakingBalance = status.value.stakingBalance as? StakingBalance.Data
|
||||
|
||||
val stakingCryptoAmount = yieldBalance?.getTotalStakingBalance(status.currency.network.rawId)
|
||||
val pendingBalances = yieldBalance?.balance?.items ?: emptyList()
|
||||
val stakingCryptoAmount = stakingBalance?.getTotalStakingBalance(status.currency.network.rawId)
|
||||
|
||||
val hasPendingBalances = when (stakingBalance) {
|
||||
is StakingBalance.Data.StakeKit -> stakingBalance.balance.items.isNotEmpty()
|
||||
is StakingBalance.Data.P2P -> !stakingBalance.unstakingAmount.isNullOrZero()
|
||||
null -> false
|
||||
}
|
||||
val pendingAmount = when (stakingBalance) {
|
||||
is StakingBalance.Data.StakeKit -> stakingBalance.balance.items.sumOf { it.amount }
|
||||
is StakingBalance.Data.P2P -> stakingBalance.unstakingAmount
|
||||
null -> BigDecimal.ZERO
|
||||
}
|
||||
|
||||
val iconState = state.tokenInfoBlockState.iconState
|
||||
|
||||
Timber.i(
|
||||
"""
|
||||
getStakingInfoBlock:
|
||||
– yieldBalance: $yieldBalance
|
||||
– stakingBalance: ${stakingBalance ?: "null"}
|
||||
– stakingCryptoAmount: $stakingCryptoAmount
|
||||
– stakingEntryInfo: $stakingEntryInfo
|
||||
""".trimIndent(),
|
||||
|
|
@ -73,16 +84,24 @@ internal class TokenDetailsStakingInfoConverter(
|
|||
|
||||
return when {
|
||||
stakingCryptoAmount.isNullOrZero() && stakingEntryInfo != null -> {
|
||||
if (pendingBalances.isEmpty()) {
|
||||
if (!hasPendingBalances) {
|
||||
getStakeAvailableState(stakingEntryInfo, iconState, isStakingButtonEnabled(status))
|
||||
} else {
|
||||
getStakedBlockWithFiatAmount(status, pendingBalances.sumOf { it.amount }, null)
|
||||
getStakedBlockWithFiatAmount(status, pendingAmount, null)
|
||||
}
|
||||
}
|
||||
stakingCryptoAmount.isNullOrZero() && stakingEntryInfo == null -> {
|
||||
null
|
||||
}
|
||||
else -> getStakedBlockWithFiatAmount(status, stakingCryptoAmount, yieldBalance?.getRewardStakingBalance())
|
||||
else -> getStakedBlockWithFiatAmount(
|
||||
status = status,
|
||||
stakingAmount = stakingCryptoAmount,
|
||||
rewardAmount = when (stakingBalance) {
|
||||
is StakingBalance.Data.StakeKit -> stakingBalance.getRewardStakingBalance()
|
||||
is StakingBalance.Data.P2P -> stakingBalance.totalRewards
|
||||
else -> BigDecimal.ZERO
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.core.decompose.di.ModelScoped
|
|||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.staking.YieldBalance
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
|
|
@ -239,7 +239,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
token = currencyStatus.currency.symbol,
|
||||
blockchain = currencyStatus.currency.network.name,
|
||||
action = "Staking",
|
||||
state = if (currencyStatus.value.yieldBalance is YieldBalance.Data) {
|
||||
state = if (currencyStatus.value.stakingBalance is StakingBalance.Data) {
|
||||
"Enabled"
|
||||
} else {
|
||||
"Disabled"
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue