From 17c25de5db3c4c5d615c1d5dfa5d26cc43153e4c Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 18 Jun 2025 16:03:55 +0400 Subject: [PATCH] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- .../CommonYieldBalanceFetcherDelegate.kt | 154 ------ .../fetcher/YieldBalanceFetcherImplementor.kt | 23 - .../multi/DefaultMultiYieldBalanceFetcher.kt | 203 +++++++- .../DefaultMultiYieldBalanceFetcherV2.kt | 210 -------- .../MultiYieldBalanceFetcherImplementor.kt | 81 --- .../DefaultSingleYieldBalanceFetcher.kt | 56 +-- .../DefaultSingleYieldBalanceFetcherV2.kt | 30 -- .../SingleYieldBalanceFetcherImplementor.kt | 82 --- .../DefaultMultiYieldBalanceFetcherTest.kt | 82 ++- .../DefaultMultiYieldBalanceFetcherV2Test.kt | 470 ------------------ .../DefaultSingleYieldBalanceFetcherTest.kt | 436 ++-------------- .../DefaultSingleYieldBalanceFetcherV2Test.kt | 95 ---- .../managetokens/SaveManagedTokensUseCase.kt | 3 +- .../domain/markets/SaveMarketTokensUseCase.kt | 3 +- .../FetchStakingYieldBalanceUseCase.kt | 3 +- .../staking/multi/MultiYieldBalanceFetcher.kt | 3 +- .../single/SingleYieldBalanceFetcher.kt | 3 +- .../tokens/AddCryptoCurrenciesUseCase.kt | 3 +- .../tokens/FetchCardTokenListUseCase.kt | 3 +- .../tokens/FetchCurrencyStatusUseCase.kt | 3 +- .../domain/tokens/FetchTokenListUseCase.kt | 3 +- .../CachedCurrenciesStatusesOperations.kt | 3 +- 23 files changed, 310 insertions(+), 1644 deletions(-) delete mode 100644 data/staking/src/main/java/com/tangem/data/staking/fetcher/CommonYieldBalanceFetcherDelegate.kt delete mode 100644 data/staking/src/main/java/com/tangem/data/staking/fetcher/YieldBalanceFetcherImplementor.kt delete mode 100644 data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherV2.kt delete mode 100644 data/staking/src/main/java/com/tangem/data/staking/multi/MultiYieldBalanceFetcherImplementor.kt delete mode 100644 data/staking/src/main/java/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherV2.kt delete mode 100644 data/staking/src/main/java/com/tangem/data/staking/single/SingleYieldBalanceFetcherImplementor.kt delete mode 100644 data/staking/src/test/kotlin/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherV2Test.kt delete mode 100644 data/staking/src/test/kotlin/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherV2Test.kt diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index d1f1bdcca8..950e7b9476 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit d1f1bdcca80c2b1f1b53f331fcb0ce78e76d5615 +Subproject commit 950e7b9476c0888a0dcf07690214a5e3c6610a62 diff --git a/data/staking/src/main/java/com/tangem/data/staking/fetcher/CommonYieldBalanceFetcherDelegate.kt b/data/staking/src/main/java/com/tangem/data/staking/fetcher/CommonYieldBalanceFetcherDelegate.kt deleted file mode 100644 index 3376520131..0000000000 --- a/data/staking/src/main/java/com/tangem/data/staking/fetcher/CommonYieldBalanceFetcherDelegate.kt +++ /dev/null @@ -1,154 +0,0 @@ -package com.tangem.data.staking.fetcher - -import arrow.core.Either -import arrow.core.getOrElse -import arrow.core.left -import arrow.core.raise.catch -import arrow.core.raise.either -import arrow.core.raise.ensure -import arrow.core.toOption -import com.tangem.data.staking.store.YieldsBalancesStore -import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO -import com.tangem.datasource.local.token.StakingYieldsStore -import com.tangem.datasource.local.userwallet.UserWalletsStore -import com.tangem.domain.core.flow.FlowFetcher -import com.tangem.domain.core.utils.catchOn -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams -import com.tangem.domain.staking.model.StakingID -import com.tangem.domain.wallets.models.UserWallet -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.domain.wallets.models.isMultiCurrency -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import timber.log.Timber - -internal fun commonFetcher( - implementor: YieldBalanceFetcherImplementor, - userWalletsStore: UserWalletsStore, - stakingYieldsStore: StakingYieldsStore, - yieldsBalancesStore: YieldsBalancesStore, - dispatchers: CoroutineDispatcherProvider, -): FlowFetcher { - return CommonYieldBalanceFetcher( - implementor = implementor, - userWalletsStore = userWalletsStore, - stakingYieldsStore = stakingYieldsStore, - yieldsBalancesStore = yieldsBalancesStore, - dispatchers = dispatchers, - ) -} - -/** - * Common implementation of YieldBalanceFetcher - * - * @property implementor fetcher implementor - * @property userWalletsStore user wallets store - * @property stakingYieldsStore staking yields store - * @property yieldsBalancesStore yields balances store - * @property dispatchers dispatchers - */ -private class CommonYieldBalanceFetcher( - private val implementor: YieldBalanceFetcherImplementor, - private val userWalletsStore: UserWalletsStore, - private val stakingYieldsStore: StakingYieldsStore, - private val yieldsBalancesStore: YieldsBalancesStore, - private val dispatchers: CoroutineDispatcherProvider, -) : FlowFetcher { - - override suspend fun invoke(params: Params): Either { - checkIsSupportedByWalletOrElse(userWalletId = params.userWalletId) { - return it.left() - } - - val stakingIds = getStakingIds(params).getOrElse { - return it.left() - } - - return Either.catchOn(dispatchers.default) { - val availableStakingIds = prefetch( - userWalletId = params.userWalletId, - stakingIds = stakingIds, - ) - - implementor.fetch(params = params, stakingIds = availableStakingIds) - } - .onLeft { - Timber.e(it, "Unable to fetch yield balances $params") - - yieldsBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = stakingIds) - } - } - - private inline fun checkIsSupportedByWalletOrElse(userWalletId: UserWalletId, ifNotSupported: (Throwable) -> Unit) { - val maybeUserWallet = userWalletsStore.getSyncOrNull(key = userWalletId).toOption() - - val isSupportedByWallet = maybeUserWallet.isSome(UserWallet::isMultiCurrency) - - if (!isSupportedByWallet) { - val exception = IllegalStateException("Wallet $userWalletId is not supported: $maybeUserWallet") - Timber.e(exception) - - ifNotSupported(exception) - } - } - - private suspend fun getStakingIds(params: Params): Either> = either { - val stakingIds = catch( - block = { implementor.createStakingIds(params = params) }, - catch = { raise(it) }, - ) - - ensure(stakingIds.isNotEmpty()) { - val exception = IllegalStateException("Unable to create staking ids for $params: list is empty") - Timber.e(exception) - - raise(exception) - } - - stakingIds - } - - private suspend fun prefetch(userWalletId: UserWalletId, stakingIds: Set): Set { - yieldsBalancesStore.refresh(userWalletId = userWalletId, stakingIds = stakingIds) - - val yieldIds = getYieldsIds(userWalletId = userWalletId) - - // [true] -> available - // [false] -> unavailable - val groupedStakingIds = stakingIds.groupBy { stakingId -> - yieldIds.any { it == stakingId.integrationId } - } - - val availableStakingIds = groupedStakingIds[true].orEmpty() - val unavailableStakingIds = groupedStakingIds[false].orEmpty() - - if (unavailableStakingIds.isNotEmpty()) { - yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = unavailableStakingIds.toSet()) - } - - return availableStakingIds.toSet().ifEmpty { - val exception = IllegalStateException( - """ - No available yields to fetch yield balances: - – userWalletId: $userWalletId - – stakingIds: ${stakingIds.joinToString()} - """.trimIndent(), - ) - Timber.d(exception) - throw exception - } - } - - private suspend fun getYieldsIds(userWalletId: UserWalletId): Set { - val yieldsIds = stakingYieldsStore.getSyncWithTimeout().orEmpty() - .mapNotNullTo(destination = hashSetOf(), transform = YieldDTO::id) - - if (yieldsIds.isEmpty()) { - val exception = IllegalStateException("No enabled yields for $userWalletId") - Timber.e(exception) - - throw exception - } - - return yieldsIds - } -} \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/fetcher/YieldBalanceFetcherImplementor.kt b/data/staking/src/main/java/com/tangem/data/staking/fetcher/YieldBalanceFetcherImplementor.kt deleted file mode 100644 index d196e32169..0000000000 --- a/data/staking/src/main/java/com/tangem/data/staking/fetcher/YieldBalanceFetcherImplementor.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.tangem.data.staking.fetcher - -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams -import com.tangem.domain.staking.model.StakingID - -/** - * Implementor of internal logic of YieldBalanceFetcher - * -[REDACTED_AUTHOR] - */ -internal interface YieldBalanceFetcherImplementor { - - /** Create set of [StakingID] */ - suspend fun createStakingIds(params: Params): Set - - /** - * Fetch yield balances - * - * @param params params - * @param stakingIds set of [StakingID] - */ - suspend fun fetch(params: Params, stakingIds: Set) -} \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcher.kt b/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcher.kt index f804e9cdd7..8019b9fcc8 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcher.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcher.kt @@ -1,16 +1,33 @@ package com.tangem.data.staking.multi -import com.tangem.data.staking.fetcher.YieldBalanceFetcherImplementor -import com.tangem.data.staking.fetcher.commonFetcher +import arrow.core.Either +import arrow.core.getOrElse +import arrow.core.left +import arrow.core.raise.catch +import arrow.core.raise.either +import arrow.core.raise.ensure +import arrow.core.toOption +import com.tangem.data.common.api.safeApiCall import com.tangem.data.staking.store.YieldsBalancesStore import com.tangem.data.staking.utils.StakingIdFactory +import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory import com.tangem.datasource.api.stakekit.StakeKitApi +import com.tangem.datasource.api.stakekit.models.request.YieldBalanceRequestBody +import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO +import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO import com.tangem.datasource.local.token.StakingYieldsStore import com.tangem.datasource.local.userwallet.UserWalletsStore -import com.tangem.domain.core.flow.FlowFetcher -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams +import com.tangem.domain.core.utils.catchOn +import com.tangem.domain.staking.model.StakingID import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.domain.wallets.models.isMultiCurrency import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope +import timber.log.Timber import javax.inject.Inject /** @@ -32,25 +49,163 @@ internal class DefaultMultiYieldBalanceFetcher @Inject constructor( private val stakingIdFactory: StakingIdFactory, private val stakeKitApi: StakeKitApi, private val dispatchers: CoroutineDispatcherProvider, -) : MultiYieldBalanceFetcher, - FlowFetcher by commonFetcher( - implementor = createMultiFetcherImplementor(yieldsBalancesStore, stakingIdFactory, stakeKitApi, dispatchers), - userWalletsStore = userWalletsStore, - stakingYieldsStore = stakingYieldsStore, - yieldsBalancesStore = yieldsBalancesStore, - dispatchers = dispatchers, - ) +) : MultiYieldBalanceFetcher { -private fun createMultiFetcherImplementor( - yieldsBalancesStore: YieldsBalancesStore, - stakingIdFactory: StakingIdFactory, - stakeKitApi: StakeKitApi, - dispatchers: CoroutineDispatcherProvider, -): YieldBalanceFetcherImplementor { - return MultiYieldBalanceFetcherImplementor( - yieldsBalancesStore = yieldsBalancesStore, - stakingIdFactory = stakingIdFactory, - stakeKitApi = stakeKitApi, - dispatchers = dispatchers, - ) + override suspend fun invoke(params: MultiYieldBalanceFetcher.Params): Either { + checkIsSupportedByWalletOrElse(userWalletId = params.userWalletId) { + return it.left() + } + + val stakingIds = getStakingIds(params).getOrElse { + return it.left() + } + + return Either.catchOn(dispatchers.default) { + yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = stakingIds) + + val availableStakingIds = getAvailableStakingIds( + userWalletId = params.userWalletId, + stakingIds = stakingIds, + ) + + fetch(userWalletId = params.userWalletId, stakingIds = availableStakingIds) + } + .onLeft { + Timber.e(it, "Unable to fetch yield balances $params") + + yieldsBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = stakingIds) + } + } + + private inline fun checkIsSupportedByWalletOrElse(userWalletId: UserWalletId, ifNotSupported: (Throwable) -> Unit) { + val maybeUserWallet = userWalletsStore.getSyncOrNull(key = userWalletId).toOption() + + val isSupportedByWallet = maybeUserWallet.isSome(UserWallet::isMultiCurrency) + + if (!isSupportedByWallet) { + val exception = IllegalStateException("Wallet $userWalletId is not supported: $maybeUserWallet") + Timber.e(exception) + + ifNotSupported(exception) + } + } + + private suspend fun getStakingIds(params: MultiYieldBalanceFetcher.Params) = either { + val stakingIds = catch( + block = { + params.currencyIdWithNetworkMap.flatMapTo(hashSetOf()) { (currencyId, network) -> + stakingIdFactory.create( + userWalletId = params.userWalletId, + currencyId = currencyId, + network = network, + ) + } + }, + catch = ::raise, + ) + + ensure(stakingIds.isNotEmpty()) { + val exception = IllegalStateException("Unable to create staking ids for $params: list is empty") + Timber.e(exception) + + raise(exception) + } + + stakingIds + } + + private suspend fun getAvailableStakingIds(userWalletId: UserWalletId, stakingIds: Set): Set { + val yieldIds = getYieldsIds(userWalletId = userWalletId) + + // [true] -> available + // [false] -> unavailable + val groupedStakingIds = stakingIds.groupBy { stakingId -> + yieldIds.any { it == stakingId.integrationId } + } + + val availableStakingIds = groupedStakingIds[true].orEmpty() + val unavailableStakingIds = groupedStakingIds[false].orEmpty() + + if (unavailableStakingIds.isNotEmpty()) { + yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = unavailableStakingIds.toSet()) + } + + return availableStakingIds.toSet().ifEmpty { + val exception = IllegalStateException( + """ + No available yields to fetch yield balances: + – userWalletId: $userWalletId + – stakingIds: ${stakingIds.joinToString()} + """.trimIndent(), + ) + Timber.d(exception) + throw exception + } + } + + private suspend fun getYieldsIds(userWalletId: UserWalletId): Set { + val yieldsIds = stakingYieldsStore.getSyncWithTimeout().orEmpty() + .mapNotNullTo(destination = hashSetOf(), transform = YieldDTO::id) + + if (yieldsIds.isEmpty()) { + val exception = IllegalStateException("No enabled yields for $userWalletId") + Timber.e(exception) + + throw exception + } + + return yieldsIds + } + + private suspend fun fetch(userWalletId: UserWalletId, stakingIds: Set) { + safeApiCall( + call = { + val requests = stakingIds.map(YieldBalanceRequestBodyFactory::create) + + val yieldBalances = coroutineScope { + requests + // TODO: in the future, consider optimizing this part + .chunked(size = 16) // StakeKitApi limitation: no more than 16 requests at the same time + .map { + async(dispatchers.io) { stakeKitApi.getMultipleYieldBalances(it).bind() } + } + .awaitAll() + .flatten() + .toSet() + } + + yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = yieldBalances) + + if (!allResponsesReceived(requests, yieldBalances)) { + val values = stakingIds.filter { stakingId -> + yieldBalances.none { + stakingId.integrationId == it.integrationId && + stakingId.address == it.addresses.address + } + } + + yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = values.toSet()) + } + }, + onError = { + Timber.e(it, "Unable to fetch yield balances $userWalletId") + + yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = stakingIds) + + throw it + }, + ) + } + + private fun allResponsesReceived( + requests: List, + yieldBalances: Set, + ): Boolean { + return requests.all { request -> + yieldBalances.any { + request.integrationId == it.integrationId && + request.addresses.address == it.addresses.address + } + } + } } \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherV2.kt b/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherV2.kt deleted file mode 100644 index 89fd57cdb6..0000000000 --- a/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherV2.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.tangem.data.staking.multi - -import arrow.core.Either -import arrow.core.getOrElse -import arrow.core.left -import arrow.core.raise.catch -import arrow.core.raise.either -import arrow.core.raise.ensure -import arrow.core.toOption -import com.tangem.data.common.api.safeApiCall -import com.tangem.data.staking.store.YieldsBalancesStore -import com.tangem.data.staking.utils.StakingIdFactory -import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory -import com.tangem.datasource.api.stakekit.StakeKitApi -import com.tangem.datasource.api.stakekit.models.request.YieldBalanceRequestBody -import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO -import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO -import com.tangem.datasource.local.token.StakingYieldsStore -import com.tangem.datasource.local.userwallet.UserWalletsStore -import com.tangem.domain.core.utils.catchOn -import com.tangem.domain.staking.model.StakingID -import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher -import com.tangem.domain.wallets.models.UserWallet -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.domain.wallets.models.isMultiCurrency -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope -import timber.log.Timber -import javax.inject.Inject - -/** - * Default implementation of [MultiYieldBalanceFetcher] - * - * @property userWalletsStore user wallets store - * @property stakingYieldsStore staking yields store - * @property yieldsBalancesStore yields balances store - * @property stakingIdFactory factory for creating StakingID - * @property stakeKitApi stake kit API - * @property dispatchers dispatchers - * -[REDACTED_AUTHOR] - */ -internal class DefaultMultiYieldBalanceFetcherV2 @Inject constructor( - private val userWalletsStore: UserWalletsStore, - private val stakingYieldsStore: StakingYieldsStore, - private val yieldsBalancesStore: YieldsBalancesStore, - private val stakingIdFactory: StakingIdFactory, - private val stakeKitApi: StakeKitApi, - private val dispatchers: CoroutineDispatcherProvider, -) { - - suspend fun invoke(params: MultiYieldBalanceFetcher.Params): Either { - checkIsSupportedByWalletOrElse(userWalletId = params.userWalletId) { - return it.left() - } - - val stakingIds = getStakingIds(params).getOrElse { - return it.left() - } - - return Either.catchOn(dispatchers.default) { - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = stakingIds) - - val availableStakingIds = getAvailableStakingIds( - userWalletId = params.userWalletId, - stakingIds = stakingIds, - ) - - fetch(params = params, stakingIds = availableStakingIds) - } - .onLeft { - Timber.e(it, "Unable to fetch yield balances $params") - - yieldsBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = stakingIds) - } - } - - private inline fun checkIsSupportedByWalletOrElse(userWalletId: UserWalletId, ifNotSupported: (Throwable) -> Unit) { - val maybeUserWallet = userWalletsStore.getSyncOrNull(key = userWalletId).toOption() - - val isSupportedByWallet = maybeUserWallet.isSome(UserWallet::isMultiCurrency) - - if (!isSupportedByWallet) { - val exception = IllegalStateException("Wallet $userWalletId is not supported: $maybeUserWallet") - Timber.e(exception) - - ifNotSupported(exception) - } - } - - private suspend fun getStakingIds(params: MultiYieldBalanceFetcher.Params) = either { - val stakingIds = catch( - block = { - params.currencyIdWithNetworkMap.flatMapTo(hashSetOf()) { (currencyId, network) -> - stakingIdFactory.create( - userWalletId = params.userWalletId, - currencyId = currencyId, - network = network, - ) - } - }, - catch = ::raise, - ) - - ensure(stakingIds.isNotEmpty()) { - val exception = IllegalStateException("Unable to create staking ids for $params: list is empty") - Timber.e(exception) - - raise(exception) - } - - stakingIds - } - - private suspend fun getAvailableStakingIds(userWalletId: UserWalletId, stakingIds: Set): Set { - val yieldIds = getYieldsIds(userWalletId = userWalletId) - - // [true] -> available - // [false] -> unavailable - val groupedStakingIds = stakingIds.groupBy { stakingId -> - yieldIds.any { it == stakingId.integrationId } - } - - val availableStakingIds = groupedStakingIds[true].orEmpty() - val unavailableStakingIds = groupedStakingIds[false].orEmpty() - - if (unavailableStakingIds.isNotEmpty()) { - yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = unavailableStakingIds.toSet()) - } - - return availableStakingIds.toSet().ifEmpty { - val exception = IllegalStateException( - """ - No available yields to fetch yield balances: - – userWalletId: $userWalletId - – stakingIds: ${stakingIds.joinToString()} - """.trimIndent(), - ) - Timber.d(exception) - throw exception - } - } - - private suspend fun getYieldsIds(userWalletId: UserWalletId): Set { - val yieldsIds = stakingYieldsStore.getSyncWithTimeout().orEmpty() - .mapNotNullTo(destination = hashSetOf(), transform = YieldDTO::id) - - if (yieldsIds.isEmpty()) { - val exception = IllegalStateException("No enabled yields for $userWalletId") - Timber.e(exception) - - throw exception - } - - return yieldsIds - } - - suspend fun fetch(params: MultiYieldBalanceFetcher.Params, stakingIds: Set) { - safeApiCall( - call = { - val requests = stakingIds.map(YieldBalanceRequestBodyFactory::create) - - val yieldBalances = coroutineScope { - requests - .chunked(size = 16) - .map { - async(dispatchers.io) { stakeKitApi.getMultipleYieldBalances(it).bind() } - } - .awaitAll() - .flatten() - .toSet() - } - - yieldsBalancesStore.storeActual(userWalletId = params.userWalletId, values = yieldBalances) - - if (!allResponsesReceived(requests, yieldBalances)) { - val values = stakingIds.filter { stakingId -> - yieldBalances.none { - stakingId.integrationId == it.integrationId && - stakingId.address == it.addresses.address - } - } - - yieldsBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = values.toSet()) - } - }, - onError = { - Timber.e(it, "Unable to fetch yield balances $params") - - yieldsBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = stakingIds) - - throw it - }, - ) - } - - private fun allResponsesReceived( - requests: List, - yieldBalances: Set, - ): Boolean { - return requests.all { request -> - yieldBalances.any { - request.integrationId == it.integrationId && - request.addresses.address == it.addresses.address - } - } - } -} \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/multi/MultiYieldBalanceFetcherImplementor.kt b/data/staking/src/main/java/com/tangem/data/staking/multi/MultiYieldBalanceFetcherImplementor.kt deleted file mode 100644 index bc58c3dd0c..0000000000 --- a/data/staking/src/main/java/com/tangem/data/staking/multi/MultiYieldBalanceFetcherImplementor.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.tangem.data.staking.multi - -import com.tangem.data.common.api.safeApiCall -import com.tangem.data.staking.fetcher.YieldBalanceFetcherImplementor -import com.tangem.data.staking.store.YieldsBalancesStore -import com.tangem.data.staking.utils.StakingIdFactory -import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory -import com.tangem.datasource.api.stakekit.StakeKitApi -import com.tangem.datasource.api.stakekit.models.request.YieldBalanceRequestBody -import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams -import com.tangem.domain.staking.model.StakingID -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.withContext -import timber.log.Timber - -/** - * Implementor of fetcher for refreshing multiple yield balances - * - * @property yieldsBalancesStore yields balances store - * @property stakingIdFactory factory for creating [StakingID] - * @property stakeKitApi StakeKit API - * @property dispatchers dispatchers - */ -internal class MultiYieldBalanceFetcherImplementor( - private val yieldsBalancesStore: YieldsBalancesStore, - private val stakingIdFactory: StakingIdFactory, - private val stakeKitApi: StakeKitApi, - private val dispatchers: CoroutineDispatcherProvider, -) : YieldBalanceFetcherImplementor { - - override suspend fun createStakingIds(params: YieldBalanceFetcherParams.Multi): Set { - return params.currencyIdWithNetworkMap.flatMapTo(hashSetOf()) { (currencyId, network) -> - stakingIdFactory.create(userWalletId = params.userWalletId, currencyId = currencyId, network = network) - } - } - - override suspend fun fetch(params: YieldBalanceFetcherParams.Multi, stakingIds: Set) { - safeApiCall( - call = { - val requests = stakingIds.map(YieldBalanceRequestBodyFactory::create) - - val yieldBalances = withContext(dispatchers.io) { - stakeKitApi.getMultipleYieldBalances(requests).bind() - } - - yieldsBalancesStore.storeActual(userWalletId = params.userWalletId, values = yieldBalances) - - if (!allResponsesReceived(requests, yieldBalances)) { - val values = stakingIds.filter { stakingId -> - yieldBalances.none { - stakingId.integrationId == it.integrationId && - stakingId.address == it.addresses.address - } - } - - yieldsBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = values.toSet()) - } - }, - onError = { - Timber.e(it, "Unable to fetch yield balances $params") - - yieldsBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = stakingIds) - - throw it - }, - ) - } - - private fun allResponsesReceived( - requests: List, - yieldBalances: Set, - ): Boolean { - return requests.all { request -> - yieldBalances.any { - request.integrationId == it.integrationId && - request.addresses.address == it.addresses.address - } - } - } -} \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcher.kt b/data/staking/src/main/java/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcher.kt index 6640397ffb..4f507e4739 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcher.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcher.kt @@ -1,57 +1,29 @@ package com.tangem.data.staking.single -import com.tangem.data.staking.fetcher.YieldBalanceFetcherImplementor -import com.tangem.data.staking.fetcher.commonFetcher -import com.tangem.data.staking.store.YieldsBalancesStore -import com.tangem.data.staking.utils.StakingIdFactory -import com.tangem.datasource.api.stakekit.StakeKitApi -import com.tangem.datasource.local.token.StakingYieldsStore -import com.tangem.datasource.local.userwallet.UserWalletsStore -import com.tangem.domain.core.flow.FlowFetcher -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams +import arrow.core.Either import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.staking.single.SingleYieldBalanceFetcher -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import javax.inject.Inject /** * Default implementation of [MultiYieldBalanceFetcher] * - * @property userWalletsStore user wallets store - * @property stakingYieldsStore staking yields store - * @property yieldsBalancesStore yields balances store - * @property stakingIdFactory factory for creating StakingID - * @property stakeKitApi stake kit API - * @property dispatchers dispatchers + * @property multiYieldBalanceFetcher multi yield balance fetcher * [REDACTED_AUTHOR] */ internal class DefaultSingleYieldBalanceFetcher @Inject constructor( - private val userWalletsStore: UserWalletsStore, - private val stakingYieldsStore: StakingYieldsStore, - private val yieldsBalancesStore: YieldsBalancesStore, - private val stakingIdFactory: StakingIdFactory, - private val stakeKitApi: StakeKitApi, - private val dispatchers: CoroutineDispatcherProvider, -) : SingleYieldBalanceFetcher, - FlowFetcher by commonFetcher( - implementor = createSingleFetcherImplementor(yieldsBalancesStore, stakingIdFactory, stakeKitApi, dispatchers), - userWalletsStore = userWalletsStore, - stakingYieldsStore = stakingYieldsStore, - yieldsBalancesStore = yieldsBalancesStore, - dispatchers = dispatchers, - ) + private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher, +) : SingleYieldBalanceFetcher { -private fun createSingleFetcherImplementor( - yieldsBalancesStore: YieldsBalancesStore, - stakingIdFactory: StakingIdFactory, - stakeKitApi: StakeKitApi, - dispatchers: CoroutineDispatcherProvider, -): YieldBalanceFetcherImplementor { - return SingleYieldBalanceFetcherImplementor( - yieldsBalancesStore = yieldsBalancesStore, - stakingIdFactory = stakingIdFactory, - stakeKitApi = stakeKitApi, - dispatchers = dispatchers, - ) + override suspend fun invoke(params: SingleYieldBalanceFetcher.Params): Either { + return multiYieldBalanceFetcher( + params = MultiYieldBalanceFetcher.Params( + userWalletId = params.userWalletId, + currencyIdWithNetworkMap = mapOf( + params.currencyId to params.network, + ), + ), + ) + } } \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherV2.kt b/data/staking/src/main/java/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherV2.kt deleted file mode 100644 index 03b04083c1..0000000000 --- a/data/staking/src/main/java/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherV2.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.tangem.data.staking.single - -import arrow.core.Either -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams -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 DefaultSingleYieldBalanceFetcherV2 @Inject constructor( - private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher, -) { - - suspend fun invoke(params: SingleYieldBalanceFetcher.Params): Either { - return multiYieldBalanceFetcher( - params = YieldBalanceFetcherParams.Multi( - userWalletId = params.userWalletId, - currencyIdWithNetworkMap = mapOf( - params.currencyId to params.network, - ), - ), - ) - } -} \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/single/SingleYieldBalanceFetcherImplementor.kt b/data/staking/src/main/java/com/tangem/data/staking/single/SingleYieldBalanceFetcherImplementor.kt deleted file mode 100644 index 00ed02954a..0000000000 --- a/data/staking/src/main/java/com/tangem/data/staking/single/SingleYieldBalanceFetcherImplementor.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.tangem.data.staking.single - -import com.tangem.data.common.api.safeApiCall -import com.tangem.data.staking.fetcher.YieldBalanceFetcherImplementor -import com.tangem.data.staking.store.YieldsBalancesStore -import com.tangem.data.staking.utils.StakingIdFactory -import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory -import com.tangem.datasource.api.stakekit.StakeKitApi -import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams -import com.tangem.domain.staking.model.StakingID -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.withContext -import timber.log.Timber - -/** - * Implementor of fetcher for refreshing single yield balance - * - * @property yieldsBalancesStore yields balances store - * @property stakingIdFactory factory for creating [StakingID] - * @property stakeKitApi StakeKit API - * @property dispatchers dispatchers - * -[REDACTED_AUTHOR] - */ -internal class SingleYieldBalanceFetcherImplementor( - private val yieldsBalancesStore: YieldsBalancesStore, - private val stakingIdFactory: StakingIdFactory, - private val stakeKitApi: StakeKitApi, - private val dispatchers: CoroutineDispatcherProvider, -) : YieldBalanceFetcherImplementor { - - override suspend fun createStakingIds(params: YieldBalanceFetcherParams.Single): Set { - val dataStakingId = stakingIdFactory.createForDefault( - userWalletId = params.userWalletId, - currencyId = params.currencyId, - network = params.network, - ) ?: return emptySet() - - return setOf( - StakingID(integrationId = dataStakingId.integrationId, address = dataStakingId.address), - ) - } - - override suspend fun fetch(params: YieldBalanceFetcherParams.Single, stakingIds: Set) { - fetchInternal(userWalletId = params.userWalletId, stakingId = stakingIds.first()) - } - - private suspend fun fetchInternal(userWalletId: UserWalletId, stakingId: StakingID) { - val request = YieldBalanceRequestBodyFactory.create(stakingId) - - safeApiCall( - call = { - val result = withContext(dispatchers.io) { - stakeKitApi.getSingleYieldBalance( - integrationId = stakingId.integrationId, - body = request, - ).bind() - } - - yieldsBalancesStore.storeActual( - userWalletId = userWalletId, - values = setOf( - YieldBalanceWrapperDTO( - balances = result, - integrationId = request.integrationId, - addresses = request.addresses, - ), - ), - ) - }, - onError = { - Timber.e(it, "Unable to fetch yield balances $userWalletId") - - yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = setOf(stakingId)) - - throw it - }, - ) - } -} \ No newline at end of file diff --git a/data/staking/src/test/kotlin/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherTest.kt b/data/staking/src/test/kotlin/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherTest.kt index fc2272eb36..d1ad78ad56 100644 --- a/data/staking/src/test/kotlin/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherTest.kt +++ b/data/staking/src/test/kotlin/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherTest.kt @@ -16,17 +16,20 @@ import com.tangem.datasource.api.stakekit.StakeKitApi import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO import com.tangem.datasource.local.token.StakingYieldsStore import com.tangem.datasource.local.userwallet.UserWalletsStore -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.staking.model.StakingID +import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.wallets.models.UserWalletId import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.* import kotlinx.coroutines.test.runTest -import org.junit.Test +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance /** [REDACTED_AUTHOR] */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) internal class DefaultMultiYieldBalanceFetcherTest { private val userWalletsStore: UserWalletsStore = mockk() @@ -44,11 +47,17 @@ internal class DefaultMultiYieldBalanceFetcherTest { dispatchers = TestingCoroutineDispatcherProvider(), ) + @BeforeEach + fun resetMocks() { + clearMocks(userWalletsStore, stakingYieldsStore, yieldsBalancesStore, stakingIdFactory, stakeKitApi) + } + @Test fun `fetch yields balances successfully`() = runTest { + // Arrange val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap) + val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) @@ -66,8 +75,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { coEvery { stakeKitApi.getMultipleYieldBalances(requests) } returns ApiResponse.Success(result) coEvery { yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = result) } just Runs - val actual = fetcher(params) + // Actual + val actual = fetcher.invoke(params) + // Assert coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) stakingIdFactory.create(params.userWalletId, ton.id, ton.network) @@ -85,9 +96,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { @Test fun `fetch yields balances successfully if one of stakingIds is unavailable`() = runTest { + // Arrange val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap) + val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) @@ -105,8 +117,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { coEvery { stakeKitApi.getMultipleYieldBalances(requests) } returns ApiResponse.Success(result) coEvery { yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = result) } just Runs - val actual = fetcher(params) + // Actual + val actual = fetcher.invoke(params) + // Assert coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) stakingIdFactory.create(params.userWalletId, ton.id, ton.network) @@ -123,15 +137,18 @@ internal class DefaultMultiYieldBalanceFetcherTest { @Test fun `fetch yields balances failure if user wallet is not supported`() = runTest { + // Arrange val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap) + val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) val userWallet = MockUserWalletFactory.create().copy(isMultiCurrency = false) coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - val actual = fetcher(params) + // Actual + val actual = fetcher.invoke(params) + // Assert coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) } coVerify(inverse = true) { @@ -152,14 +169,17 @@ internal class DefaultMultiYieldBalanceFetcherTest { @Test fun `fetch yields balances failure if userWalletsStore returns null`() = runTest { + // Arrange val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap) + val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns null - val actual = fetcher(params) + // Actual + val actual = fetcher.invoke(params) + // Assert coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) } coVerify(inverse = true) { @@ -180,16 +200,19 @@ internal class DefaultMultiYieldBalanceFetcherTest { @Test fun `fetch yields balances failure if stakingIdFactory returns empty list`() = runTest { + // Arrange val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap) + val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns emptySet() coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns emptySet() - val actual = fetcher(params) + // Actual + val actual = fetcher.invoke(params) + // Assert coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) stakingIdFactory.create(params.userWalletId, ton.id, ton.network) @@ -213,9 +236,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { @Test fun `fetch yields balances failure if stakingYieldsStore getSyncWithTimeout returns null`() = runTest { + // Arrange val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap) + val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) @@ -224,8 +248,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { coEvery { stakingYieldsStore.getSyncWithTimeout() } returns null coEvery { yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) } just Runs - val actual = fetcher(params) + // Actual + val actual = fetcher.invoke(params) + // Assert coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) stakingIdFactory.create(params.userWalletId, ton.id, ton.network) @@ -249,9 +275,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { @Test fun `fetch yields balances failure if stakingYieldsStore getSyncWithTimeout returns empty list`() = runTest { + // Arrange val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap) + val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) @@ -260,8 +287,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { coEvery { stakingYieldsStore.getSyncWithTimeout() } returns emptyList() coEvery { yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) } just Runs - val actual = fetcher(params) + // Actual + val actual = fetcher.invoke(params) + // Assert coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) stakingIdFactory.create(params.userWalletId, ton.id, ton.network) @@ -285,9 +314,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { @Test fun `fetch yields balances failure if yields converting is failed`() = runTest { + // Arrange val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap) + val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) @@ -301,8 +331,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields coEvery { yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) } just Runs - val actual = fetcher(params) + // Actual + val actual = fetcher.invoke(params) + // Assert coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) stakingIdFactory.create(params.userWalletId, ton.id, ton.network) @@ -326,9 +358,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { @Test fun `fetch yields balances failure if available yields does not contain ids from params`() = runTest { + // Arrange val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap) + val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) @@ -339,8 +372,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields coEvery { yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) } just Runs - val actual = fetcher(params) + // Actual + val actual = fetcher.invoke(params) + // Assert coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) stakingIdFactory.create(params.userWalletId, ton.id, ton.network) @@ -370,9 +405,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { @Test fun `fetch yields balances failure if stakeKitApi getMultipleYieldBalances is failed`() = runTest { + // Arrange val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap) + val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) @@ -391,8 +427,10 @@ internal class DefaultMultiYieldBalanceFetcherTest { coEvery { stakeKitApi.getMultipleYieldBalances(requests) } returns errorResponse coEvery { yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) } just Runs - val actual = fetcher(params) + // Actual + val actual = fetcher.invoke(params) + // Assert coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) stakingIdFactory.create(params.userWalletId, ton.id, ton.network) diff --git a/data/staking/src/test/kotlin/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherV2Test.kt b/data/staking/src/test/kotlin/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherV2Test.kt deleted file mode 100644 index 4899543e29..0000000000 --- a/data/staking/src/test/kotlin/com/tangem/data/staking/multi/DefaultMultiYieldBalanceFetcherV2Test.kt +++ /dev/null @@ -1,470 +0,0 @@ -package com.tangem.data.staking.multi - -import arrow.core.toOption -import com.google.common.truth.Truth -import com.tangem.blockchain.common.Blockchain -import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory -import com.tangem.common.test.data.staking.MockYieldDTOFactory -import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory -import com.tangem.common.test.domain.wallet.MockUserWalletFactory -import com.tangem.data.staking.store.YieldsBalancesStore -import com.tangem.data.staking.utils.StakingIdFactory -import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory -import com.tangem.datasource.api.common.response.ApiResponse -import com.tangem.datasource.api.common.response.ApiResponseError -import com.tangem.datasource.api.stakekit.StakeKitApi -import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO -import com.tangem.datasource.local.token.StakingYieldsStore -import com.tangem.datasource.local.userwallet.UserWalletsStore -import com.tangem.domain.staking.model.StakingID -import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider -import io.mockk.* -import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.TestInstance - -/** -[REDACTED_AUTHOR] - */ -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -internal class DefaultMultiYieldBalanceFetcherV2Test { - - private val userWalletsStore: UserWalletsStore = mockk() - private val stakingYieldsStore: StakingYieldsStore = mockk() - private val yieldsBalancesStore: YieldsBalancesStore = mockk() - private val stakingIdFactory: StakingIdFactory = mockk() - private val stakeKitApi: StakeKitApi = mockk() - - private val fetcher = DefaultMultiYieldBalanceFetcherV2( - userWalletsStore = userWalletsStore, - stakingYieldsStore = stakingYieldsStore, - yieldsBalancesStore = yieldsBalancesStore, - stakingIdFactory = stakingIdFactory, - stakeKitApi = stakeKitApi, - dispatchers = TestingCoroutineDispatcherProvider(), - ) - - @BeforeEach - fun resetMocks() { - clearMocks(userWalletsStore, stakingYieldsStore, yieldsBalancesStore, stakingIdFactory, stakeKitApi) - } - - @Test - fun `fetch yields balances successfully`() = runTest { - // Arrange - val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - - val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) - coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId) - coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs - - val yields = listOf(MockYieldDTOFactory.create(tonId), MockYieldDTOFactory.create(solanaId)) - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields - - val requests = tonAndSolanaIds.map(YieldBalanceRequestBodyFactory::create).sortedBy { it.integrationId } - val result = setOf( - MockYieldBalanceWrapperDTOFactory.createWithBalance(solanaId), - MockYieldBalanceWrapperDTOFactory.createWithBalance(tonId), - ) - coEvery { stakeKitApi.getMultipleYieldBalances(requests) } returns ApiResponse.Success(result) - coEvery { yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = result) } just Runs - - // Actual - val actual = fetcher.invoke(params) - - // Assert - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.create(params.userWalletId, ton.id, ton.network) - stakingIdFactory.create(params.userWalletId, solana.id, solana.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds) - stakingYieldsStore.getSyncWithTimeout() - stakeKitApi.getMultipleYieldBalances(requests) - yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = result) - } - - coVerify(inverse = true) { yieldsBalancesStore.storeError(any(), any()) } - - Truth.assertThat(actual.isRight()).isTrue() - } - - @Test - fun `fetch yields balances successfully if one of stakingIds is unavailable`() = runTest { - // Arrange - val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - - val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) - coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId) - coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs - - val yields = listOf(MockYieldDTOFactory.create(tonId)) - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields - - coEvery { yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = setOf(solanaId)) } just Runs - - val requests = listOf(YieldBalanceRequestBodyFactory.create(tonId)) - val result = setOf(MockYieldBalanceWrapperDTOFactory.createWithBalance(tonId)) - - coEvery { stakeKitApi.getMultipleYieldBalances(requests) } returns ApiResponse.Success(result) - coEvery { yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = result) } just Runs - - // Actual - val actual = fetcher.invoke(params) - - // Assert - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.create(params.userWalletId, ton.id, ton.network) - stakingIdFactory.create(params.userWalletId, solana.id, solana.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds) - stakingYieldsStore.getSyncWithTimeout() - yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = setOf(solanaId)) - stakeKitApi.getMultipleYieldBalances(requests) - yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = result) - } - - Truth.assertThat(actual.isRight()).isTrue() - } - - @Test - fun `fetch yields balances failure if user wallet is not supported`() = runTest { - // Arrange - val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - - val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) - - val userWallet = MockUserWalletFactory.create().copy(isMultiCurrency = false) - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - - // Actual - val actual = fetcher.invoke(params) - - // Assert - coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) } - - coVerify(inverse = true) { - stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) - yieldsBalancesStore.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()) - } - - val expected = IllegalStateException("Wallet ${params.userWalletId} is not supported: ${userWallet.toOption()}") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if userWalletsStore returns null`() = runTest { - // Arrange - val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - - val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns null - - // Actual - val actual = fetcher.invoke(params) - - // Assert - coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) } - - coVerify(inverse = true) { - stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) - yieldsBalancesStore.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()) - } - - val expected = IllegalStateException("Wallet ${params.userWalletId} is not supported: ${null.toOption()}") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if stakingIdFactory returns empty list`() = runTest { - // Arrange - val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - - val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns emptySet() - coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns emptySet() - - // Actual - val actual = fetcher.invoke(params) - - // Assert - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.create(params.userWalletId, ton.id, ton.network) - stakingIdFactory.create(params.userWalletId, solana.id, solana.network) - } - - coVerify(inverse = true) { - yieldsBalancesStore.refresh(any(), any>()) - stakingYieldsStore.getSyncWithTimeout() - stakeKitApi.getMultipleYieldBalances(any()) - yieldsBalancesStore.storeActual(any(), any()) - yieldsBalancesStore.storeError(any(), any()) - } - - val expected = IllegalStateException("Unable to create staking ids for $params: list is empty") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if stakingYieldsStore getSyncWithTimeout returns null`() = runTest { - // Arrange - val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - - val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) - coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId) - coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns null - coEvery { yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) } just Runs - - // Actual - val actual = fetcher.invoke(params) - - // Assert - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.create(params.userWalletId, ton.id, ton.network) - stakingIdFactory.create(params.userWalletId, solana.id, solana.network) - yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) - stakingYieldsStore.getSyncWithTimeout() - yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) - } - - coVerify(inverse = true) { - stakeKitApi.getMultipleYieldBalances(any()) - yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) - } - - val expected = IllegalStateException("No enabled yields for ${params.userWalletId}") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if stakingYieldsStore getSyncWithTimeout returns empty list`() = runTest { - // Arrange - val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - - val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) - coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId) - coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns emptyList() - coEvery { yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) } just Runs - - // Actual - val actual = fetcher.invoke(params) - - // Assert - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.create(params.userWalletId, ton.id, ton.network) - stakingIdFactory.create(params.userWalletId, solana.id, solana.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds) - stakingYieldsStore.getSyncWithTimeout() - yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) - } - - coVerify(inverse = true) { - stakeKitApi.getMultipleYieldBalances(any()) - yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) - } - - val expected = IllegalStateException("No enabled yields for ${params.userWalletId}") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if yields converting is failed`() = runTest { - // Arrange - val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - - val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) - coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId) - coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs - - val yields = listOf( - MockYieldDTOFactory.create(tonId).copy(id = null), - MockYieldDTOFactory.create(solanaId).copy(id = null), - ) - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields - coEvery { yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) } just Runs - - // Actual - val actual = fetcher.invoke(params) - - // Assert - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.create(params.userWalletId, ton.id, ton.network) - stakingIdFactory.create(params.userWalletId, solana.id, solana.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds) - stakingYieldsStore.getSyncWithTimeout() - yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) - } - - coVerify(inverse = true) { - stakeKitApi.getMultipleYieldBalances(any()) - yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) - } - - val expected = IllegalStateException("No enabled yields for ${params.userWalletId}") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if available yields does not contain ids from params`() = runTest { - // Arrange - val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - - val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) - coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId) - coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs - - val yields = listOf(MockYieldDTOFactory.create(StakingID(integrationId = "polygon", address = "0x1"))) - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields - coEvery { yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) } just Runs - - // Actual - val actual = fetcher.invoke(params) - - // Assert - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.create(params.userWalletId, ton.id, ton.network) - stakingIdFactory.create(params.userWalletId, solana.id, solana.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds) - stakingYieldsStore.getSyncWithTimeout() - yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) - } - - coVerify(inverse = true) { - stakeKitApi.getMultipleYieldBalances(any()) - yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) - } - - val expected = IllegalStateException( - """ - No available yields to fetch yield balances: - – userWalletId: $userWalletId - – stakingIds: ${setOf(solanaId, tonId).joinToString()} - """.trimIndent(), - ) - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if stakeKitApi getMultipleYieldBalances is failed`() = runTest { - // Arrange - val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network) - - val params = MultiYieldBalanceFetcher.Params(userWalletId, currencyIdWithNetworkMap) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId) - coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId) - coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs - - val yields = listOf(MockYieldDTOFactory.create(tonId), MockYieldDTOFactory.create(solanaId)) - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields - - val requests = setOf(solanaId, tonId).map(YieldBalanceRequestBodyFactory::create) - - @Suppress("UNCHECKED_CAST") - val errorResponse = ApiResponse.Error(ApiResponseError.NetworkException) - as ApiResponse> - - coEvery { stakeKitApi.getMultipleYieldBalances(requests) } returns errorResponse - coEvery { yieldsBalancesStore.storeError(userWalletId, tonAndSolanaIds) } just Runs - - // Actual - val actual = fetcher.invoke(params) - - // Assert - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.create(params.userWalletId, ton.id, ton.network) - stakingIdFactory.create(params.userWalletId, solana.id, solana.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds) - stakingYieldsStore.getSyncWithTimeout() - stakeKitApi.getMultipleYieldBalances(requests) - yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = tonAndSolanaIds) - } - - coVerify(inverse = true) { yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) } - - val expected = ApiResponseError.NetworkException - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - private companion object { - val userWalletId = UserWalletId("011") - val userWallet = MockUserWalletFactory.create() - - val mocks = MockCryptoCurrencyFactory() - - val ton = mocks.createCoin(Blockchain.TON) - val solana = mocks.createCoin(Blockchain.Solana) - - val tonId = MockYieldBalanceWrapperDTOFactory.defaultStakingId - val solanaId = StakingID( - integrationId = "solana-sol-native-multivalidator-staking", - address = "0x1", - ) - - val tonAndSolanaIds = setOf(tonId, solanaId) - } -} \ No newline at end of file diff --git a/data/staking/src/test/kotlin/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherTest.kt b/data/staking/src/test/kotlin/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherTest.kt index 292242f445..952da5a8b9 100644 --- a/data/staking/src/test/kotlin/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherTest.kt +++ b/data/staking/src/test/kotlin/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherTest.kt @@ -1,438 +1,94 @@ package com.tangem.data.staking.single -import arrow.core.toOption +import arrow.core.left +import arrow.core.right import com.google.common.truth.Truth import com.tangem.blockchain.common.Blockchain -import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory -import com.tangem.common.test.data.staking.MockYieldDTOFactory import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory -import com.tangem.common.test.domain.wallet.MockUserWalletFactory -import com.tangem.data.staking.store.YieldsBalancesStore -import com.tangem.data.staking.utils.StakingIdFactory -import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory -import com.tangem.datasource.api.common.response.ApiResponse -import com.tangem.datasource.api.common.response.ApiResponseError -import com.tangem.datasource.api.stakekit.StakeKitApi -import com.tangem.datasource.api.stakekit.models.request.YieldBalanceRequestBody -import com.tangem.datasource.api.stakekit.models.response.model.BalanceDTO -import com.tangem.datasource.api.stakekit.models.response.model.NetworkTypeDTO -import com.tangem.datasource.api.stakekit.models.response.model.TokenDTO -import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO -import com.tangem.datasource.local.token.StakingYieldsStore -import com.tangem.datasource.local.userwallet.UserWalletsStore -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams -import com.tangem.domain.staking.model.StakingID +import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher +import com.tangem.domain.staking.single.SingleYieldBalanceFetcher import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider -import io.mockk.* +import io.mockk.clearMocks +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.mockk import kotlinx.coroutines.test.runTest -import org.junit.Test -import java.math.BigDecimal +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance /** [REDACTED_AUTHOR] */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) internal class DefaultSingleYieldBalanceFetcherTest { - private val userWalletsStore: UserWalletsStore = mockk() - private val stakingYieldsStore: StakingYieldsStore = mockk() - private val yieldsBalancesStore: YieldsBalancesStore = mockk() - private val stakingIdFactory: StakingIdFactory = mockk() - private val stakeKitApi: StakeKitApi = mockk() + private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher = mockk() private val fetcher = DefaultSingleYieldBalanceFetcher( - userWalletsStore = userWalletsStore, - stakingYieldsStore = stakingYieldsStore, - yieldsBalancesStore = yieldsBalancesStore, - stakingIdFactory = stakingIdFactory, - stakeKitApi = stakeKitApi, - dispatchers = TestingCoroutineDispatcherProvider(), + multiYieldBalanceFetcher = multiYieldBalanceFetcher, ) + @BeforeEach + fun resetMocks() { + clearMocks(multiYieldBalanceFetcher) + } + @Test - fun `fetch yields balances successfully`() = runTest { - val params = YieldBalanceFetcherParams.Single( + fun `fetch yield balance successfully`() = runTest { + // Arrange + val params = SingleYieldBalanceFetcher.Params( userWalletId = userWalletId, currencyId = ton.id, network = ton.network, ) - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId - coEvery { - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - } just Runs + val multiParams = MultiYieldBalanceFetcher.Params( + userWalletId = userWalletId, + currencyIdWithNetworkMap = mapOf(ton.id to ton.network), + ) - val yields = listOf(MockYieldDTOFactory.create(tonId)) - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields + val multiResult = Unit.right() - val request = YieldBalanceRequestBodyFactory.create(tonId) - val result = listOf(createBalanceDTO()) - coEvery { stakeKitApi.getSingleYieldBalance(tonId.integrationId, request) } returns ApiResponse.Success(result) + coEvery { multiYieldBalanceFetcher(params = multiParams) } returns multiResult - val values = result.mapTo(hashSetOf()) { it.toWrapper(request) } - coEvery { yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = values) } just Runs + // Act + val actual = fetcher.invoke(params).isRight() - val actual = fetcher(params) + // Assert + Truth.assertThat(actual).isTrue() - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - stakingYieldsStore.getSyncWithTimeout() - stakeKitApi.getSingleYieldBalance(integrationId = tonId.integrationId, body = request) - yieldsBalancesStore.storeActual(userWalletId = userWalletId, values = values) - } - - coVerify(inverse = true) { yieldsBalancesStore.storeError(any(), any()) } - - Truth.assertThat(actual.isRight()).isTrue() + coVerify { multiYieldBalanceFetcher(params = multiParams) } } @Test - fun `fetch yields balances failure if user wallet is not supported`() = runTest { - val params = YieldBalanceFetcherParams.Single( + fun `fetch yield balance failure`() = runTest { + // Arrange + val params = SingleYieldBalanceFetcher.Params( userWalletId = userWalletId, currencyId = ton.id, network = ton.network, ) - val userWallet = MockUserWalletFactory.create().copy(isMultiCurrency = false) - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - - val actual = fetcher(params) - - coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) } - - coVerify(inverse = true) { - stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) - yieldsBalancesStore.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()) - } - - val expected = IllegalStateException("Wallet ${params.userWalletId} is not supported: ${userWallet.toOption()}") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if userWalletsStore returns null`() = runTest { - val params = YieldBalanceFetcherParams.Single( + val multiParams = MultiYieldBalanceFetcher.Params( userWalletId = userWalletId, - currencyId = ton.id, - network = ton.network, + currencyIdWithNetworkMap = mapOf(ton.id to ton.network), ) - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns null + val multiResult = IllegalStateException().left() - val actual = fetcher(params) + coEvery { multiYieldBalanceFetcher(params = multiParams) } returns multiResult - coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) } + // Act + val actual = fetcher.invoke(params) - coVerify(inverse = true) { - stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) - yieldsBalancesStore.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()) - } - - val expected = IllegalStateException("Wallet ${params.userWalletId} is not supported: ${null.toOption()}") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if stakingIdFactory createForDefault returns null`() = runTest { - val params = YieldBalanceFetcherParams.Single( - userWalletId = userWalletId, - currencyId = ton.id, - network = ton.network, - ) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns null - - val actual = fetcher(params) - - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.createForDefault(userWalletId = userWalletId, currencyId = ton.id, network = ton.network) - } - - coVerify(inverse = true) { - yieldsBalancesStore.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()) - } - - val expected = IllegalStateException("Unable to create staking ids for $params: list is empty") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if stakingYieldsStore getSyncWithTimeout returns null`() = runTest { - val params = YieldBalanceFetcherParams.Single( - userWalletId = userWalletId, - currencyId = ton.id, - network = ton.network, - ) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId - coEvery { - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - } just Runs - - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns null - coEvery { yieldsBalancesStore.storeError(userWalletId, setOf(tonId)) } just Runs - - val actual = fetcher(params) - - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - stakingYieldsStore.getSyncWithTimeout() - yieldsBalancesStore.storeError(userWalletId, setOf(tonId)) - } - - coVerify(inverse = true) { - stakeKitApi.getSingleYieldBalance(integrationId = any(), body = any()) - yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) - } - - val expected = IllegalStateException("No enabled yields for ${params.userWalletId}") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if stakingYieldsStore getSyncWithTimeout returns empty list`() = runTest { - val params = YieldBalanceFetcherParams.Single( - userWalletId = userWalletId, - currencyId = ton.id, - network = ton.network, - ) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId - coEvery { - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - } just Runs - - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns emptyList() - coEvery { yieldsBalancesStore.storeError(userWalletId, setOf(tonId)) } just Runs - - val actual = fetcher(params) - - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - stakingYieldsStore.getSyncWithTimeout() - yieldsBalancesStore.storeError(userWalletId, setOf(tonId)) - } - - coVerify(inverse = true) { - stakeKitApi.getSingleYieldBalance(integrationId = any(), body = any()) - yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) - } - - val expected = IllegalStateException("No enabled yields for ${params.userWalletId}") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if yields converting is failed`() = runTest { - val params = YieldBalanceFetcherParams.Single( - userWalletId = userWalletId, - currencyId = ton.id, - network = ton.network, - ) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId - coEvery { - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - } just Runs - - val yields = listOf(MockYieldDTOFactory.create(tonId).copy(id = null)) - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields - coEvery { yieldsBalancesStore.storeError(userWalletId, setOf(tonId)) } just Runs - - val actual = fetcher(params) - - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - stakingYieldsStore.getSyncWithTimeout() - yieldsBalancesStore.storeError(userWalletId, setOf(tonId)) - } - - coVerify(inverse = true) { - stakeKitApi.getSingleYieldBalance(integrationId = any(), body = any()) - yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) - } - - val expected = IllegalStateException("No enabled yields for ${params.userWalletId}") - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if available yields does not contain ids from params`() = runTest { - val params = YieldBalanceFetcherParams.Single( - userWalletId = userWalletId, - currencyId = ton.id, - network = ton.network, - ) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId - coEvery { - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - } just Runs - - val yields = listOf(MockYieldDTOFactory.create(StakingID(integrationId = "polygon", address = "0x1"))) - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields - coEvery { yieldsBalancesStore.storeError(userWalletId, setOf(tonId)) } just Runs - - val actual = fetcher(params) - - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - stakingYieldsStore.getSyncWithTimeout() - yieldsBalancesStore.storeError(userWalletId, setOf(tonId)) - } - - coVerify(inverse = true) { - stakeKitApi.getSingleYieldBalance(integrationId = any(), body = any()) - yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) - } - - val expected = IllegalStateException( - """ - No available yields to fetch yield balances: - – userWalletId: $userWalletId - – stakingIds: ${setOf(tonId).joinToString()} - """.trimIndent(), - ) - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - @Test - fun `fetch yields balances failure if stakeKitApi getMultipleYieldBalances is failed`() = runTest { - val params = YieldBalanceFetcherParams.Single( - userWalletId = userWalletId, - currencyId = ton.id, - network = ton.network, - ) - - coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet - coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId - coEvery { - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - } just Runs - - val yields = listOf(MockYieldDTOFactory.create(tonId)) - coEvery { stakingYieldsStore.getSyncWithTimeout() } returns yields - - val request = YieldBalanceRequestBodyFactory.create(tonId) - - @Suppress("UNCHECKED_CAST") - val errorResponse = ApiResponse.Error(ApiResponseError.NetworkException) as ApiResponse> - - coEvery { stakeKitApi.getSingleYieldBalance(tonId.integrationId, request) } returns errorResponse - coEvery { yieldsBalancesStore.storeError(userWalletId, setOf(tonId)) } just Runs - - val actual = fetcher(params) - - coVerify { - userWalletsStore.getSyncOrNull(params.userWalletId) - stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) - yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId)) - stakingYieldsStore.getSyncWithTimeout() - stakeKitApi.getSingleYieldBalance(tonId.integrationId, request) - yieldsBalancesStore.storeError(userWalletId = userWalletId, stakingIds = setOf(tonId)) - } - - coVerify(inverse = true) { yieldsBalancesStore.storeActual(userWalletId = any(), values = any()) } - - val expected = ApiResponseError.NetworkException - - Truth.assertThat(actual.isLeft()).isTrue() - Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java) - Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message) - } - - private fun createBalanceDTO(): BalanceDTO { - return BalanceDTO( - groupId = "dictas", - type = BalanceDTO.BalanceTypeDTO.REWARDS, - amount = BigDecimal.ONE, - date = null, - pricePerShare = BigDecimal.ONE, - pendingActions = listOf(), - pendingActionConstraints = listOf(), - tokenDTO = TokenDTO( - name = "Casandra Paul", - network = NetworkTypeDTO.POLYGON, - symbol = "vim", - decimals = 3994, - address = null, - coinGeckoId = null, - logoURI = null, - isPoints = null, - ), - validatorAddress = null, - validatorAddresses = listOf(), - providerId = null, - ) - } - - private fun BalanceDTO.toWrapper(request: YieldBalanceRequestBody): YieldBalanceWrapperDTO { - return YieldBalanceWrapperDTO( - balances = listOf(this), - integrationId = request.integrationId, - addresses = request.addresses, - ) + // Assert + Truth.assertThat(actual).isEqualTo(multiResult) + coVerify { multiYieldBalanceFetcher(params = multiParams) } } private companion object { val userWalletId = UserWalletId("011") - val userWallet = MockUserWalletFactory.create() - - val mocks = MockCryptoCurrencyFactory() - - val ton = mocks.createCoin(Blockchain.TON) - - val tonId = MockYieldBalanceWrapperDTOFactory.defaultStakingId + val ton = MockCryptoCurrencyFactory().createCoin(Blockchain.TON) } } \ No newline at end of file diff --git a/data/staking/src/test/kotlin/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherV2Test.kt b/data/staking/src/test/kotlin/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherV2Test.kt deleted file mode 100644 index 0455f8bc2b..0000000000 --- a/data/staking/src/test/kotlin/com/tangem/data/staking/single/DefaultSingleYieldBalanceFetcherV2Test.kt +++ /dev/null @@ -1,95 +0,0 @@ -package com.tangem.data.staking.single - -import arrow.core.left -import arrow.core.right -import com.google.common.truth.Truth -import com.tangem.blockchain.common.Blockchain -import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams -import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher -import com.tangem.domain.staking.single.SingleYieldBalanceFetcher -import com.tangem.domain.wallets.models.UserWalletId -import io.mockk.clearMocks -import io.mockk.coEvery -import io.mockk.coVerify -import io.mockk.mockk -import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.TestInstance - -/** -[REDACTED_AUTHOR] - */ -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -internal class DefaultSingleYieldBalanceFetcherV2Test { - - private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher = mockk() - - private val fetcher = DefaultSingleYieldBalanceFetcherV2( - multiYieldBalanceFetcher = multiYieldBalanceFetcher, - ) - - @BeforeEach - fun resetMocks() { - clearMocks(multiYieldBalanceFetcher) - } - - @Test - fun `fetch yield balance successfully`() = runTest { - // Arrange - val params = SingleYieldBalanceFetcher.Params( - userWalletId = userWalletId, - currencyId = ton.id, - network = ton.network, - ) - - val multiParams = YieldBalanceFetcherParams.Multi( - userWalletId = userWalletId, - currencyIdWithNetworkMap = mapOf(ton.id to ton.network), - ) - - val multiResult = Unit.right() - - coEvery { multiYieldBalanceFetcher(params = multiParams) } returns multiResult - - // Act - val actual = fetcher.invoke(params).isRight() - - // Assert - Truth.assertThat(actual).isTrue() - - coVerify { multiYieldBalanceFetcher(params = multiParams) } - } - - @Test - fun `fetch yield balance failure`() = runTest { - // Arrange - val params = SingleYieldBalanceFetcher.Params( - userWalletId = userWalletId, - currencyId = ton.id, - network = ton.network, - ) - - val multiParams = YieldBalanceFetcherParams.Multi( - userWalletId = userWalletId, - currencyIdWithNetworkMap = mapOf(ton.id to ton.network), - ) - - val multiResult = IllegalStateException().left() - - coEvery { multiYieldBalanceFetcher(params = multiParams) } returns multiResult - - // Act - val actual = fetcher.invoke(params) - - // Assert - Truth.assertThat(actual).isEqualTo(multiResult) - coVerify { multiYieldBalanceFetcher(params = multiParams) } - } - - private companion object { - val userWalletId = UserWalletId("011") - val ton = MockCryptoCurrencyFactory().createCoin(Blockchain.TON) - } -} \ No newline at end of file diff --git a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt index f93f9ecbc4..b2cedcf6e1 100644 --- a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt +++ b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt @@ -9,7 +9,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.quotes.multi.MultiQuoteFetcher -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.tokens.TokensFeatureToggles @@ -112,7 +111,7 @@ class SaveManagedTokensUseCase( ) { if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) { multiYieldBalanceFetcher( - params = YieldBalanceFetcherParams.Multi( + params = MultiYieldBalanceFetcher.Params( userWalletId = userWalletId, currencyIdWithNetworkMap = existingCurrencies.associateTo(hashMapOf()) { it.id to it.network }, ), diff --git a/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt b/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt index f61f911e14..95750fda93 100644 --- a/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt +++ b/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt @@ -7,7 +7,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.quotes.multi.MultiQuoteFetcher -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.tokens.TokensFeatureToggles @@ -93,7 +92,7 @@ class SaveMarketTokensUseCase( ) { if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) { multiYieldBalanceFetcher( - params = YieldBalanceFetcherParams.Multi( + params = MultiYieldBalanceFetcher.Params( userWalletId = userWalletId, currencyIdWithNetworkMap = existingCurrencies.associateTo(hashMapOf()) { it.id to it.network }, ), diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingYieldBalanceUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingYieldBalanceUseCase.kt index 2d970c66af..2c61d8395f 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingYieldBalanceUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingYieldBalanceUseCase.kt @@ -4,7 +4,6 @@ import arrow.core.Either import arrow.core.raise.catch import arrow.core.raise.either import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.staking.model.stakekit.StakingError import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository @@ -28,7 +27,7 @@ class FetchStakingYieldBalanceUseCase( block = { if (isRefactoringEnabled) { singleYieldBalanceFetcher( - params = YieldBalanceFetcherParams.Single( + params = SingleYieldBalanceFetcher.Params( userWalletId = userWalletId, currencyId = cryptoCurrency.id, network = cryptoCurrency.network, diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/multi/MultiYieldBalanceFetcher.kt b/domain/staking/src/main/java/com/tangem/domain/staking/multi/MultiYieldBalanceFetcher.kt index 70d96d7b6e..59123af3b9 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/multi/MultiYieldBalanceFetcher.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/multi/MultiYieldBalanceFetcher.kt @@ -3,7 +3,6 @@ package com.tangem.domain.staking.multi import com.tangem.domain.core.flow.FlowFetcher import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.wallets.models.UserWalletId /** @@ -11,7 +10,7 @@ import com.tangem.domain.wallets.models.UserWalletId * [REDACTED_AUTHOR] */ -interface MultiYieldBalanceFetcher : FlowFetcher { +interface MultiYieldBalanceFetcher : FlowFetcher { /** * Params for fetching multiple yield balances diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/single/SingleYieldBalanceFetcher.kt b/domain/staking/src/main/java/com/tangem/domain/staking/single/SingleYieldBalanceFetcher.kt index 603ab4c73a..a265dbb3cd 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/single/SingleYieldBalanceFetcher.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/single/SingleYieldBalanceFetcher.kt @@ -3,7 +3,6 @@ package com.tangem.domain.staking.single import com.tangem.domain.core.flow.FlowFetcher import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.wallets.models.UserWalletId /** @@ -11,7 +10,7 @@ import com.tangem.domain.wallets.models.UserWalletId * [REDACTED_AUTHOR] */ -interface SingleYieldBalanceFetcher : FlowFetcher { +interface SingleYieldBalanceFetcher : FlowFetcher { /** * Params for fetching single yield balance diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt index 99e6c3fd81..bbb70459eb 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt @@ -8,7 +8,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.quotes.multi.MultiQuoteFetcher -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.staking.single.SingleYieldBalanceFetcher import com.tangem.domain.tokens.repository.CurrenciesRepository @@ -147,7 +146,7 @@ class AddCryptoCurrenciesUseCase( private suspend fun refreshUpdatedYieldBalances(userWalletId: UserWalletId, addedCurrency: CryptoCurrency) { if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) { singleYieldBalanceFetcher( - params = YieldBalanceFetcherParams.Single( + params = SingleYieldBalanceFetcher.Params( userWalletId = userWalletId, currencyId = addedCurrency.id, network = addedCurrency.network, diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt index f1aed7a00d..8d69b8ab21 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCardTokenListUseCase.kt @@ -8,7 +8,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.quotes.multi.MultiQuoteFetcher -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.tokens.error.TokenListError @@ -95,7 +94,7 @@ class FetchCardTokenListUseCase( ) { if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) { multiYieldBalanceFetcher( - params = YieldBalanceFetcherParams.Multi( + params = MultiYieldBalanceFetcher.Params( userWalletId = userWalletId, currencyIdWithNetworkMap = currencies.associateTo(hashMapOf()) { it.id to it.network }, ), diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt index b1feda7923..b5783e3a2d 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt @@ -8,7 +8,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.quotes.multi.MultiQuoteFetcher -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.staking.single.SingleYieldBalanceFetcher import com.tangem.domain.tokens.error.CurrencyStatusError @@ -140,7 +139,7 @@ class FetchCurrencyStatusUseCase( ) { if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) { singleYieldBalanceFetcher( - params = YieldBalanceFetcherParams.Single( + params = SingleYieldBalanceFetcher.Params( userWalletId = userWalletId, currencyId = cryptoCurrency.id, network = cryptoCurrency.network, diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt index e093d9eba6..782de0af6f 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchTokenListUseCase.kt @@ -10,7 +10,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.quotes.multi.MultiQuoteFetcher -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.tokens.error.TokenListError @@ -129,7 +128,7 @@ class FetchTokenListUseCase( ) { if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) { multiYieldBalanceFetcher( - params = YieldBalanceFetcherParams.Multi( + params = MultiYieldBalanceFetcher.Params( userWalletId = userWalletId, currencyIdWithNetworkMap = currencies.associateTo(hashMapOf()) { it.id to it.network }, ), diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt index 0ba91d1225..c58bc38c90 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt @@ -21,7 +21,6 @@ import com.tangem.domain.quotes.QuotesRepositoryV2 import com.tangem.domain.quotes.multi.MultiQuoteFetcher import com.tangem.domain.quotes.single.SingleQuoteProducer import com.tangem.domain.quotes.single.SingleQuoteSupplier -import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams import com.tangem.domain.staking.model.stakekit.YieldBalance import com.tangem.domain.staking.model.stakekit.YieldBalanceList import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher @@ -196,7 +195,7 @@ class CachedCurrenciesStatusesOperations( async { if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) { multiYieldBalanceFetcher( - params = YieldBalanceFetcherParams.Multi( + params = MultiYieldBalanceFetcher.Params( userWalletId = userWalletId, currencyIdWithNetworkMap = currencies.associateTo(hashMapOf()) { it.id to it.network }, ),