From 3b8da73b9c530e631b118449a53b002cdb345cb6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 13 Mar 2026 12:58:22 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/di/domain/TokensDomainModule.kt | 15 +- .../AccountListCryptoCurrenciesFetcher.kt | 28 +- ...=> MultiWalletAccountListFetcherModule.kt} | 11 +- .../tangem/data/tokens/di/TokensDataModule.kt | 9 - .../repository/DefaultCurrenciesRepository.kt | 138 ------- .../AccountListCryptoCurrenciesFetcherTest.kt | 14 +- domain/tokens/build.gradle.kts | 4 +- ...er.kt => MultiWalletAccountListFetcher.kt} | 4 +- .../tokens/repository/CurrenciesRepository.kt | 49 --- .../tokens/wallet/BaseWalletBalanceFetcher.kt | 6 +- .../tokens/wallet/WalletBalanceFetcher.kt | 65 +++- .../implementor/MultiWalletBalanceFetcher.kt | 16 +- .../implementor/SingleWalletBalanceFetcher.kt | 20 +- .../SingleWalletWithTokenBalanceFetcher.kt | 20 +- .../tokens/wallet/WalletBalanceFetcherTest.kt | 337 ++++++++++++------ .../MultiWalletBalanceFetcherTest.kt | 24 +- .../SingleWalletBalanceFetcherTest.kt | 23 +- ...SingleWalletWithTokenBalanceFetcherTest.kt | 23 +- 18 files changed, 373 insertions(+), 433 deletions(-) rename data/tokens/src/main/kotlin/com/tangem/data/tokens/di/{MultiWalletCryptoCurrenciesFetcherModule.kt => MultiWalletAccountListFetcherModule.kt} (70%) rename domain/tokens/src/main/kotlin/com/tangem/domain/tokens/{MultiWalletCryptoCurrenciesFetcher.kt => MultiWalletAccountListFetcher.kt} (54%) diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index f4503ac3d3..d9ec3d207e 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -1,7 +1,10 @@ package com.tangem.tap.di.domain import com.tangem.core.configtoggle.feature.FeatureTogglesManager +import com.tangem.domain.common.tokens.CardCryptoCurrencyFactory +import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.exchange.RampStateManager +import com.tangem.domain.express.ExpressServiceFetcher import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.networks.repository.NetworksRepository import com.tangem.domain.networks.single.SingleNetworkStatusFetcher @@ -148,8 +151,10 @@ internal object TokensDomainModule { @Provides @Singleton fun provideWalletBalanceFetcher( - currenciesRepository: CurrenciesRepository, - multiWalletCryptoCurrenciesFetcher: MultiWalletCryptoCurrenciesFetcher, + userWalletsListRepository: UserWalletsListRepository, + cardCryptoCurrencyFactory: CardCryptoCurrencyFactory, + expressServiceFetcher: ExpressServiceFetcher, + multiWalletAccountListFetcher: MultiWalletAccountListFetcher, multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, multiNetworkStatusFetcher: MultiNetworkStatusFetcher, multiQuoteStatusFetcher: MultiQuoteStatusFetcher, @@ -159,8 +164,10 @@ internal object TokensDomainModule { dispatchers: CoroutineDispatcherProvider, ): WalletBalanceFetcher { return WalletBalanceFetcher( - currenciesRepository = currenciesRepository, - multiWalletCryptoCurrenciesFetcher = multiWalletCryptoCurrenciesFetcher, + userWalletsListRepository = userWalletsListRepository, + cardCryptoCurrencyFactory = cardCryptoCurrencyFactory, + expressServiceFetcher = expressServiceFetcher, + multiWalletAccountListFetcher = multiWalletAccountListFetcher, multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier, multiNetworkStatusFetcher = multiNetworkStatusFetcher, multiQuoteStatusFetcher = multiQuoteStatusFetcher, diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcher.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcher.kt index 642add41ce..1e6ad0b644 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcher.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcher.kt @@ -1,35 +1,30 @@ package com.tangem.data.tokens import arrow.core.Either -import arrow.core.right import com.tangem.data.common.account.WalletAccountsFetcher -import com.tangem.datasource.api.tangemTech.models.account.flattenTokens import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.common.wallets.getSyncStrict import com.tangem.domain.core.utils.catchOn -import com.tangem.domain.express.ExpressServiceFetcher -import com.tangem.domain.express.models.ExpressAsset import com.tangem.domain.models.wallet.isMultiCurrency -import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher -import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher.Params +import com.tangem.domain.tokens.MultiWalletAccountListFetcher +import com.tangem.domain.tokens.MultiWalletAccountListFetcher.Params import com.tangem.utils.coroutines.CoroutineDispatcherProvider /** - * Implementation of [MultiWalletCryptoCurrenciesFetcher] that fetches crypto currencies of all accounts + * Implementation of [MultiWalletAccountListFetcher] that fetches the account list for a multi-currency wallet + * by delegating to [WalletAccountsFetcher]. * * @property userWalletsListRepository repository to get user wallets * @property walletAccountsFetcher instance of [WalletAccountsFetcher] to fetch accounts for a multi wallet - * @property expressServiceFetcher fetcher of express service - * @property dispatchers dispatchers + * @property dispatchers provider for coroutine dispatchers used to run fetch operations * [REDACTED_AUTHOR] */ internal class AccountListCryptoCurrenciesFetcher( private val userWalletsListRepository: UserWalletsListRepository, private val walletAccountsFetcher: WalletAccountsFetcher, - private val expressServiceFetcher: ExpressServiceFetcher, private val dispatchers: CoroutineDispatcherProvider, -) : MultiWalletCryptoCurrenciesFetcher { +) : MultiWalletAccountListFetcher { override suspend fun invoke(params: Params): Either { return Either.catchOn(dispatchers.default) { @@ -37,16 +32,7 @@ internal class AccountListCryptoCurrenciesFetcher( if (!userWallet.isMultiCurrency) error("${this::class.simpleName} supports only multi-currency wallet") - val response = walletAccountsFetcher.fetch(userWalletId = params.userWalletId) - - expressServiceFetcher.fetch( - userWallet = userWallet, - assetIds = response.flattenTokens().mapTo(hashSetOf()) { - ExpressAsset.ID(networkId = it.networkId, contractAddress = it.contractAddress) - }, - ) - - Unit.right() + walletAccountsFetcher.fetch(userWalletId = params.userWalletId) } } } \ No newline at end of file diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/MultiWalletCryptoCurrenciesFetcherModule.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/MultiWalletAccountListFetcherModule.kt similarity index 70% rename from data/tokens/src/main/kotlin/com/tangem/data/tokens/di/MultiWalletCryptoCurrenciesFetcherModule.kt rename to data/tokens/src/main/kotlin/com/tangem/data/tokens/di/MultiWalletAccountListFetcherModule.kt index 68065f148b..68136d2160 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/MultiWalletCryptoCurrenciesFetcherModule.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/MultiWalletAccountListFetcherModule.kt @@ -3,8 +3,7 @@ package com.tangem.data.tokens.di import com.tangem.data.common.account.WalletAccountsFetcher import com.tangem.data.tokens.AccountListCryptoCurrenciesFetcher import com.tangem.domain.common.wallets.UserWalletsListRepository -import com.tangem.domain.express.ExpressServiceFetcher -import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher +import com.tangem.domain.tokens.MultiWalletAccountListFetcher import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides @@ -14,20 +13,18 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) -internal class MultiWalletCryptoCurrenciesFetcherModule { +internal class MultiWalletAccountListFetcherModule { @Singleton @Provides - fun provideMultiWalletCryptoCurrenciesFetcher( + fun provideMultiWalletAccountListFetcher( userWalletsListRepository: UserWalletsListRepository, walletAccountsFetcher: WalletAccountsFetcher, - expressServiceFetcher: ExpressServiceFetcher, dispatchers: CoroutineDispatcherProvider, - ): MultiWalletCryptoCurrenciesFetcher { + ): MultiWalletAccountListFetcher { return AccountListCryptoCurrenciesFetcher( userWalletsListRepository = userWalletsListRepository, walletAccountsFetcher = walletAccountsFetcher, - expressServiceFetcher = expressServiceFetcher, dispatchers = dispatchers, ) } diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt index 6a9b6ec68a..9165cfa1b2 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt @@ -1,8 +1,6 @@ package com.tangem.data.tokens.di import com.tangem.blockchainsdk.utils.ExcludedBlockchains -import com.tangem.data.common.cache.CacheRegistry -import com.tangem.domain.common.tokens.CardCryptoCurrencyFactory import com.tangem.data.tokens.repository.DefaultCurrenciesRepository import com.tangem.data.tokens.repository.DefaultCurrencyChecksRepository import com.tangem.data.tokens.repository.DefaultTokenReceiveWarningsViewedRepository @@ -11,7 +9,6 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.token.TokenReceiveWarningActionStore import com.tangem.domain.common.wallets.UserWalletsListRepository -import com.tangem.domain.express.ExpressServiceFetcher import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.CurrencyChecksRepository import com.tangem.domain.tokens.repository.TokenReceiveWarningsViewedRepository @@ -34,21 +31,15 @@ internal object TokensDataModule { tangemTechApi: TangemTechApi, userWalletsListRepository: UserWalletsListRepository, walletManagersFacade: WalletManagersFacade, - cacheRegistry: CacheRegistry, dispatchers: CoroutineDispatcherProvider, - expressServiceFetcher: ExpressServiceFetcher, excludedBlockchains: ExcludedBlockchains, - cardCryptoCurrencyFactory: CardCryptoCurrencyFactory, ): CurrenciesRepository { return DefaultCurrenciesRepository( tangemTechApi = tangemTechApi, userWalletsListRepository = userWalletsListRepository, walletManagersFacade = walletManagersFacade, - cacheRegistry = cacheRegistry, - expressServiceFetcher = expressServiceFetcher, dispatchers = dispatchers, excludedBlockchains = excludedBlockchains, - cardCryptoCurrencyFactory = cardCryptoCurrencyFactory, ) } diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt index e61f2b466d..077f772d62 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt @@ -5,119 +5,33 @@ import com.tangem.blockchain.common.TransactionStatus import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.blockchainsdk.utils.toBlockchain -import com.tangem.data.common.cache.CacheRegistry -import com.tangem.domain.common.tokens.CardCryptoCurrencyFactory import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.data.common.currency.getTokenId import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.tangemTech.TangemTechApi -import com.tangem.domain.card.CardTypesResolver -import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.common.wallets.getSyncStrict -import com.tangem.domain.core.error.DataError -import com.tangem.domain.express.ExpressServiceFetcher -import com.tangem.domain.express.models.ExpressAsset import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.models.wallet.isMultiCurrency -import com.tangem.domain.models.wallet.requireColdWallet import com.tangem.domain.tokens.model.FeePaidCurrency import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import timber.log.Timber import com.tangem.blockchain.common.FeePaidCurrency as FeePaidSdkCurrency -@Suppress("LargeClass", "LongParameterList", "TooManyFunctions") internal class DefaultCurrenciesRepository( private val tangemTechApi: TangemTechApi, private val userWalletsListRepository: UserWalletsListRepository, private val walletManagersFacade: WalletManagersFacade, - private val cacheRegistry: CacheRegistry, - private val expressServiceFetcher: ExpressServiceFetcher, private val dispatchers: CoroutineDispatcherProvider, - private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory, excludedBlockchains: ExcludedBlockchains, ) : CurrenciesRepository { private val cryptoCurrencyFactory = CryptoCurrencyFactory(excludedBlockchains) - override suspend fun getSingleCurrencyWalletPrimaryCurrency( - userWalletId: UserWalletId, - refresh: Boolean, - ): CryptoCurrency { - return withContext(dispatchers.io) { - val userWallet = userWalletsListRepository.getSyncStrict(userWalletId) - userWallet.requireColdWallet() - ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = false) - - val currency = cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard( - userWallet = userWallet, - ) - - fetchExpressAssetsByNetworkIds( - userWallet = userWallet, - cryptoCurrencies = listOf(currency), - refresh = refresh, - ) - - currency - } - } - - override suspend fun getSingleCurrencyWalletWithCardCurrencies( - userWalletId: UserWalletId, - refresh: Boolean, - ): List { - return withContext(dispatchers.io) { - val userWallet = userWalletsListRepository.getSyncStrict(userWalletId) - val scanResponse = userWallet.requireColdWallet().scanResponse - - val currencies = if (scanResponse.cardTypesResolver.isSingleWalletWithToken()) { - cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(userWallet = userWallet) - } else { - cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(userWallet = userWallet) - .run { - listOf(this) - } - } - - fetchExpressAssetsByNetworkIds( - userWallet = userWallet, - cryptoCurrencies = currencies, - refresh = refresh, - ) - - currencies - } - } - - override suspend fun getSingleCurrencyWalletWithCardCurrency( - userWalletId: UserWalletId, - id: CryptoCurrency.ID, - ): CryptoCurrency { - return withContext(dispatchers.io) { - val userWallet = userWalletsListRepository.getSyncStrict(userWalletId) - userWallet.requireColdWallet() - ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = false) - - val currency = cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken( - userWallet = userWallet, - ) - .find { it.id == id } - requireNotNull(currency) { "Unable to find currency with provided ID: $id" } - fetchExpressAssetsByNetworkIds(userWallet, listOf(currency)) - currency - } - } - override suspend fun isSendBlockedByPendingTransactions( userWalletId: UserWalletId, cryptoCurrencyStatus: CryptoCurrencyStatus, @@ -223,56 +137,4 @@ internal class DefaultCurrenciesRepository( val blockchain = Blockchain.fromNetworkId(network.backendId) return blockchain?.isNetworkFeeZero() == true } - - override fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver? { - return (userWalletsListRepository.getSyncStrict(userWalletId) as? UserWallet.Cold)?.cardTypesResolver - } - - private suspend fun fetchExpressAssetsByNetworkIds( - userWallet: UserWallet, - cryptoCurrencies: List, - refresh: Boolean = false, - ) { - val tokens = cryptoCurrencies.mapTo(hashSetOf()) { currency -> - val tokenCurrency = currency as? CryptoCurrency.Token - ExpressAsset.ID( - networkId = currency.network.backendId, - contractAddress = tokenCurrency?.contractAddress, - ) - } - cacheRegistry.invokeOnExpire( - key = getAssetsCacheKey(userWallet.walletId), - skipCache = refresh, - block = { - coroutineScope { - launch { expressServiceFetcher.fetch(userWallet, tokens) } - } - }, - ) - } - - private fun getAssetsCacheKey(userWalletId: UserWalletId): String = "assets_cache_key_${userWalletId.stringValue}" - - private fun ensureIsCorrectUserWallet(userWallet: UserWallet, isMultiCurrencyWalletExpected: Boolean) { - val userWalletId = userWallet.walletId - - val message = when { - !userWallet.isMultiCurrency && isMultiCurrencyWalletExpected -> { - "Multi currency wallet expected, but single currency wallet was found: $userWalletId" - } - - userWallet.isMultiCurrency && !isMultiCurrencyWalletExpected -> { - "Single currency wallet expected, but multi currency wallet was found: $userWalletId" - } - - else -> null - } - - if (message != null) { - val error = DataError.UserWalletError.WrongUserWallet(message) - - Timber.e(error) - throw error - } - } } \ No newline at end of file diff --git a/data/tokens/src/test/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcherTest.kt b/data/tokens/src/test/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcherTest.kt index 3f95f270ca..ccd7edd6ae 100644 --- a/data/tokens/src/test/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcherTest.kt +++ b/data/tokens/src/test/kotlin/com/tangem/data/tokens/AccountListCryptoCurrenciesFetcherTest.kt @@ -1,15 +1,13 @@ package com.tangem.data.tokens import arrow.core.left -import arrow.core.right import com.tangem.data.common.account.WalletAccountsFetcher import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse import com.tangem.domain.common.wallets.UserWalletsListRepository -import com.tangem.domain.express.ExpressServiceFetcher import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.isMultiCurrency -import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher +import com.tangem.domain.tokens.MultiWalletAccountListFetcher import com.tangem.test.core.assertEither import com.tangem.test.core.assertEitherRight import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider @@ -25,13 +23,11 @@ internal class AccountListCryptoCurrenciesFetcherTest { private val userWalletsListRepository: UserWalletsListRepository = mockk(relaxUnitFun = true) private val walletAccountsFetcher: WalletAccountsFetcher = mockk(relaxUnitFun = true) - private val expressServiceFetcher: ExpressServiceFetcher = mockk() private val dispatchers = TestingCoroutineDispatcherProvider() private val fetcher = AccountListCryptoCurrenciesFetcher( userWalletsListRepository = userWalletsListRepository, walletAccountsFetcher = walletAccountsFetcher, - expressServiceFetcher = expressServiceFetcher, dispatchers = dispatchers, ) @@ -43,7 +39,7 @@ internal class AccountListCryptoCurrenciesFetcherTest { @Test fun `returns failure if wallet is not multi-currency`() = runTest { // Arrange - val params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId) + val params = MultiWalletAccountListFetcher.Params(userWalletId = userWalletId) val mockUserWallet = mockk { every { walletId } returns userWalletId every { isMultiCurrency } returns false @@ -68,7 +64,7 @@ internal class AccountListCryptoCurrenciesFetcherTest { @Test fun `returns accounts if wallet is multi-currency`() = runTest { // Arrange - val params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId) + val params = MultiWalletAccountListFetcher.Params(userWalletId = userWalletId) val mockUserWallet = mockk { every { walletId } returns userWalletId every { isMultiCurrency } returns true @@ -79,7 +75,6 @@ internal class AccountListCryptoCurrenciesFetcherTest { every { userWalletsListRepository.userWallets } returns userWalletsFlow coEvery { walletAccountsFetcher.fetch(userWalletId = params.userWalletId) } returns response - coEvery { expressServiceFetcher.fetch(userWallet = mockUserWallet, assetIds = emptySet()) } returns Unit.right() // Act val actual = fetcher(params) @@ -90,14 +85,13 @@ internal class AccountListCryptoCurrenciesFetcherTest { coVerify(ordering = Ordering.SEQUENCE) { userWalletsListRepository.userWallets walletAccountsFetcher.fetch(userWalletId = params.userWalletId) - expressServiceFetcher.fetch(userWallet = mockUserWallet, assetIds = emptySet()) } } @Test fun `returns error if walletAccountsFetcher returns error`() = runTest { // Arrange - val params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId) + val params = MultiWalletAccountListFetcher.Params(userWalletId = userWalletId) val mockUserWallet = mockk { every { walletId } returns userWalletId every { isMultiCurrency } returns true diff --git a/domain/tokens/build.gradle.kts b/domain/tokens/build.gradle.kts index 53e21909a4..52ba7c414e 100644 --- a/domain/tokens/build.gradle.kts +++ b/domain/tokens/build.gradle.kts @@ -16,10 +16,12 @@ dependencies { /** Project - Domain */ api(projects.domain.core) + implementation(projects.domain.common) + implementation(projects.domain.card) + implementation(projects.domain.express) implementation(projects.domain.models) implementation(projects.domain.legacy) implementation(projects.domain.walletManager) - implementation(projects.domain.card) implementation(projects.domain.staking) implementation(projects.domain.visa) implementation(projects.libs.blockchainSdk) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/MultiWalletCryptoCurrenciesFetcher.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/MultiWalletAccountListFetcher.kt similarity index 54% rename from domain/tokens/src/main/kotlin/com/tangem/domain/tokens/MultiWalletCryptoCurrenciesFetcher.kt rename to domain/tokens/src/main/kotlin/com/tangem/domain/tokens/MultiWalletAccountListFetcher.kt index ac4dbf6f25..528707152c 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/MultiWalletCryptoCurrenciesFetcher.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/MultiWalletAccountListFetcher.kt @@ -4,11 +4,11 @@ import com.tangem.domain.core.flow.FlowFetcher import com.tangem.domain.models.wallet.UserWalletId /** - * Fetcher of crypto currencies for a multi-currency wallet with [UserWalletId] + * Fetcher of account list for a multi-currency wallet with [UserWalletId] * [REDACTED_AUTHOR] */ -interface MultiWalletCryptoCurrenciesFetcher : FlowFetcher { +interface MultiWalletAccountListFetcher : FlowFetcher { data class Params(val userWalletId: UserWalletId) } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt index 53f4a03da9..ba37257e3b 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt @@ -1,7 +1,5 @@ package com.tangem.domain.tokens.repository -import com.tangem.domain.card.CardTypesResolver -import com.tangem.domain.core.error.DataError import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.Network @@ -11,52 +9,8 @@ import com.tangem.domain.tokens.model.FeePaidCurrency /** * Repository for everything related to the tokens of user wallet * */ -@Suppress("TooManyFunctions") interface CurrenciesRepository { - /** - * Retrieves the primary cryptocurrency for a specific single-currency user wallet. - * - * @param userWalletId The unique identifier of the user wallet. - * @param refresh Indicates whether to force a refresh of the status data. - * @return The primary cryptocurrency associated with the user wallet. - * @throws DataError.UserWalletError.WrongUserWallet If multi-currency user wallet - * ID provided. - */ - suspend fun getSingleCurrencyWalletPrimaryCurrency( - userWalletId: UserWalletId, - refresh: Boolean = false, - ): CryptoCurrency - - /** - * Retrieves the cryptocurrencies for a specific single-currency user wallet with tokens on the card. - * - * @param userWalletId The unique identifier of the user wallet. - * @param refresh Indicates whether to force a refresh of the status data. - * @return The primary cryptocurrency associated with the user wallet. - * @throws DataError.UserWalletError.WrongUserWallet If multi-currency user wallet - * ID provided. - */ - suspend fun getSingleCurrencyWalletWithCardCurrencies( - userWalletId: UserWalletId, - refresh: Boolean = false, - ): List - - /** - * Retrieves the cryptocurrency for a specific single-currency user old wallet - * that stores token on card - * - * @param userWalletId The unique identifier of the user wallet. - * @param id The unique identifier of the cryptocurrency to be retrieved. - * @return The cryptocurrency associated with the user wallet and ID. - * @throws DataError.UserWalletError.WrongUserWallet If single-currency user wallet - * ID provided. - */ - suspend fun getSingleCurrencyWalletWithCardCurrency( - userWalletId: UserWalletId, - id: CryptoCurrency.ID, - ): CryptoCurrency - /** * Determines whether the currency sending is blocked by network pending transaction * @@ -88,7 +42,4 @@ interface CurrenciesRepository { ): CryptoCurrency.Token fun isNetworkFeeZero(userWalletId: UserWalletId, network: Network): Boolean - - @Throws - fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver? } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/BaseWalletBalanceFetcher.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/BaseWalletBalanceFetcher.kt index 89f51b885b..c9fd602d9b 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/BaseWalletBalanceFetcher.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/BaseWalletBalanceFetcher.kt @@ -1,7 +1,7 @@ package com.tangem.domain.tokens.wallet import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.domain.models.wallet.UserWallet /** * Base contract for implementation of wallet's balance fetcher @@ -13,6 +13,6 @@ internal interface BaseWalletBalanceFetcher { /** Fetching sources */ val fetchingSources: Set - /** Get crypto currencies of wallet with [userWalletId] */ - suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set + /** Get crypto currencies of [userWallet] */ + suspend fun getCryptoCurrencies(userWallet: UserWallet): Set } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/WalletBalanceFetcher.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/WalletBalanceFetcher.kt index 17b46927d6..51ea9c7ea3 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/WalletBalanceFetcher.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/WalletBalanceFetcher.kt @@ -3,18 +3,24 @@ package com.tangem.domain.tokens.wallet import arrow.core.Either import arrow.core.raise.either import arrow.core.right +import com.tangem.domain.card.common.util.cardTypesResolver +import com.tangem.domain.common.tokens.CardCryptoCurrencyFactory +import com.tangem.domain.common.wallets.UserWalletsListRepository +import com.tangem.domain.common.wallets.getSyncStrict import com.tangem.domain.core.flow.FlowFetcher import com.tangem.domain.core.utils.catchOn +import com.tangem.domain.express.ExpressServiceFetcher +import com.tangem.domain.express.models.ExpressAsset import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher import com.tangem.domain.staking.StakingIdFactory import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher -import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher +import com.tangem.domain.tokens.MultiWalletAccountListFetcher import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier -import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.wallet.implementor.MultiWalletBalanceFetcher import com.tangem.domain.tokens.wallet.implementor.SingleWalletBalanceFetcher import com.tangem.domain.tokens.wallet.implementor.SingleWalletWithTokenBalanceFetcher @@ -27,7 +33,8 @@ import timber.log.Timber /** * Fetcher of wallet balance by [UserWalletId] * - * @property currenciesRepository currencies repository + * @property userWalletsListRepository user wallets list repository + * @property expressServiceFetcher express service fetcher * @property multiWalletBalanceFetcher balance fetcher of multi-currency wallet * @property singleWalletWithTokenBalanceFetcher balance fetcher of single-currency wallet with token * @property singleWalletBalanceFetcher balance fetcher of single-currency wallet @@ -40,7 +47,8 @@ import timber.log.Timber */ @Suppress("LongParameterList") class WalletBalanceFetcher internal constructor( - private val currenciesRepository: CurrenciesRepository, + private val userWalletsListRepository: UserWalletsListRepository, + private val expressServiceFetcher: ExpressServiceFetcher, private val multiWalletBalanceFetcher: BaseWalletBalanceFetcher, private val singleWalletWithTokenBalanceFetcher: BaseWalletBalanceFetcher, private val singleWalletBalanceFetcher: BaseWalletBalanceFetcher, @@ -54,8 +62,10 @@ class WalletBalanceFetcher internal constructor( /** Additional constructor without internal dependencies */ constructor( - currenciesRepository: CurrenciesRepository, - multiWalletCryptoCurrenciesFetcher: MultiWalletCryptoCurrenciesFetcher, + userWalletsListRepository: UserWalletsListRepository, + cardCryptoCurrencyFactory: CardCryptoCurrencyFactory, + expressServiceFetcher: ExpressServiceFetcher, + multiWalletAccountListFetcher: MultiWalletAccountListFetcher, multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, multiNetworkStatusFetcher: MultiNetworkStatusFetcher, multiQuoteStatusFetcher: MultiQuoteStatusFetcher, @@ -64,15 +74,18 @@ class WalletBalanceFetcher internal constructor( stakingIdFactory: StakingIdFactory, dispatchers: CoroutineDispatcherProvider, ) : this( - currenciesRepository = currenciesRepository, + userWalletsListRepository = userWalletsListRepository, + expressServiceFetcher = expressServiceFetcher, multiWalletBalanceFetcher = MultiWalletBalanceFetcher( - multiWalletCryptoCurrenciesFetcher = multiWalletCryptoCurrenciesFetcher, + multiWalletAccountListFetcher = multiWalletAccountListFetcher, multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier, ), singleWalletWithTokenBalanceFetcher = SingleWalletWithTokenBalanceFetcher( - currenciesRepository = currenciesRepository, + cardCryptoCurrencyFactory = cardCryptoCurrencyFactory, + ), + singleWalletBalanceFetcher = SingleWalletBalanceFetcher( + cardCryptoCurrencyFactory = cardCryptoCurrencyFactory, ), - singleWalletBalanceFetcher = SingleWalletBalanceFetcher(currenciesRepository = currenciesRepository), multiNetworkStatusFetcher = multiNetworkStatusFetcher, multiQuoteStatusFetcher = multiQuoteStatusFetcher, multiStakingBalanceFetcher = multiStakingBalanceFetcher, @@ -83,19 +96,27 @@ class WalletBalanceFetcher internal constructor( override suspend fun invoke(params: Params) = Either.catchOn(dispatchers.default) { val userWalletId = params.userWalletId - val cardTypesResolver = currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) + val userWallet = userWalletsListRepository.getSyncStrict(userWalletId) - val fetcher = when { - cardTypesResolver == null || cardTypesResolver.isMultiwalletAllowed() -> multiWalletBalanceFetcher - cardTypesResolver.isSingleWalletWithToken() -> singleWalletWithTokenBalanceFetcher - cardTypesResolver.isSingleWallet() -> singleWalletBalanceFetcher - else -> error("Unknown type of wallet: $userWalletId") + val fetcher = when (userWallet) { + is UserWallet.Hot -> multiWalletBalanceFetcher + is UserWallet.Cold -> { + val cardTypesResolver = userWallet.cardTypesResolver + when { + cardTypesResolver.isMultiwalletAllowed() -> multiWalletBalanceFetcher + cardTypesResolver.isSingleWalletWithToken() -> singleWalletWithTokenBalanceFetcher + cardTypesResolver.isSingleWallet() -> singleWalletBalanceFetcher + else -> error("Unknown type of wallet: $userWalletId") + } + } } - val currencies = fetcher.getCryptoCurrencies(userWalletId = userWalletId).ifEmpty { + val currencies = fetcher.getCryptoCurrencies(userWallet = userWallet).ifEmpty { error("UserWallet doesn't contain crypto-currencies: $userWalletId") } + fetchExpressAssets(userWallet = userWallet, currencies = currencies) + fetcher.fetch( userWalletId = userWalletId, currencies = currencies, @@ -190,6 +211,16 @@ class WalletBalanceFetcher internal constructor( } } + private suspend fun fetchExpressAssets(userWallet: UserWallet, currencies: Set) { + val assetIds = currencies.mapTo(hashSetOf()) { currency -> + ExpressAsset.ID( + networkId = currency.network.backendId, + contractAddress = (currency as? CryptoCurrency.Token)?.contractAddress, + ) + } + expressServiceFetcher.fetch(userWallet = userWallet, assetIds = assetIds) + } + private suspend fun fetchPaymentAccount( userWalletId: UserWalletId, paymentAccountRefactorEnabled: Boolean, diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/MultiWalletBalanceFetcher.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/MultiWalletBalanceFetcher.kt index eaa142f3fb..adbd435398 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/MultiWalletBalanceFetcher.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/MultiWalletBalanceFetcher.kt @@ -1,25 +1,25 @@ package com.tangem.domain.tokens.wallet.implementor import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.tokens.MultiWalletAccountListFetcher import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier import com.tangem.domain.tokens.wallet.BaseWalletBalanceFetcher import com.tangem.domain.tokens.wallet.FetchingSource -import com.tangem.domain.models.wallet.UserWalletId import kotlinx.coroutines.flow.firstOrNull import timber.log.Timber /** * Implementation of [BaseWalletBalanceFetcher] for MULTI-CURRENCY wallet * - * @property multiWalletCryptoCurrenciesFetcher multi wallet fetcher of crypto currencies + * @property multiWalletAccountListFetcher multi wallet fetcher of crypto currencies * @property multiWalletCryptoCurrenciesSupplier multi wallet supplier of crypto currencies * [REDACTED_AUTHOR] */ internal class MultiWalletBalanceFetcher( - private val multiWalletCryptoCurrenciesFetcher: MultiWalletCryptoCurrenciesFetcher, + private val multiWalletAccountListFetcher: MultiWalletAccountListFetcher, private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, ) : BaseWalletBalanceFetcher { @@ -30,9 +30,11 @@ internal class MultiWalletBalanceFetcher( FetchingSource.TANGEM_PAY, ) - override suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set { - multiWalletCryptoCurrenciesFetcher( - params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId), + override suspend fun getCryptoCurrencies(userWallet: UserWallet): Set { + val userWalletId = userWallet.walletId + + multiWalletAccountListFetcher( + params = MultiWalletAccountListFetcher.Params(userWalletId = userWalletId), ) .onLeft(Timber::e) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletBalanceFetcher.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletBalanceFetcher.kt index 1440a42560..9e31c0b078 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletBalanceFetcher.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletBalanceFetcher.kt @@ -1,20 +1,21 @@ package com.tangem.domain.tokens.wallet.implementor +import com.tangem.domain.common.tokens.CardCryptoCurrencyFactory import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.tokens.repository.CurrenciesRepository +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.models.wallet.requireColdWallet import com.tangem.domain.tokens.wallet.BaseWalletBalanceFetcher import com.tangem.domain.tokens.wallet.FetchingSource -import com.tangem.domain.models.wallet.UserWalletId /** * Implementation of [BaseWalletBalanceFetcher] for SINGLE-CURRENCY wallet * - * @property currenciesRepository currencies repository + * @property cardCryptoCurrencyFactory card crypto currency factory * [REDACTED_AUTHOR] */ internal class SingleWalletBalanceFetcher( - private val currenciesRepository: CurrenciesRepository, + private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory, ) : BaseWalletBalanceFetcher { override val fetchingSources: Set = setOf( @@ -22,12 +23,13 @@ internal class SingleWalletBalanceFetcher( FetchingSource.QUOTE, ) - override suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set { - val primaryCurrency = currenciesRepository.getSingleCurrencyWalletPrimaryCurrency( - userWalletId = userWalletId, - refresh = true, + override suspend fun getCryptoCurrencies(userWallet: UserWallet): Set { + val coldWallet = userWallet.requireColdWallet() + + val currency = cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard( + userWallet = coldWallet, ) - return setOf(primaryCurrency) + return setOf(currency) } } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletWithTokenBalanceFetcher.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletWithTokenBalanceFetcher.kt index 1e9f83d60e..9f40bad1c4 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletWithTokenBalanceFetcher.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletWithTokenBalanceFetcher.kt @@ -1,20 +1,21 @@ package com.tangem.domain.tokens.wallet.implementor +import com.tangem.domain.common.tokens.CardCryptoCurrencyFactory import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.tokens.repository.CurrenciesRepository +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.models.wallet.requireColdWallet import com.tangem.domain.tokens.wallet.BaseWalletBalanceFetcher import com.tangem.domain.tokens.wallet.FetchingSource -import com.tangem.domain.models.wallet.UserWalletId /** * Implementation of [BaseWalletBalanceFetcher] for SINGLE-CURRENCY wallet WITH TOKEN (like, NODL) * - * @property currenciesRepository currencies repository + * @property cardCryptoCurrencyFactory card crypto currency factory * [REDACTED_AUTHOR] */ internal class SingleWalletWithTokenBalanceFetcher( - private val currenciesRepository: CurrenciesRepository, + private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory, ) : BaseWalletBalanceFetcher { override val fetchingSources: Set = setOf( @@ -22,10 +23,11 @@ internal class SingleWalletWithTokenBalanceFetcher( FetchingSource.QUOTE, ) - override suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set { - return currenciesRepository.getSingleCurrencyWalletWithCardCurrencies( - userWalletId = userWalletId, - refresh = true, - ).toSet() + override suspend fun getCryptoCurrencies(userWallet: UserWallet): Set { + val coldWallet = userWallet.requireColdWallet() + + val currencies = cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(coldWallet) + + return currencies.toSet() } } \ No newline at end of file diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/WalletBalanceFetcherTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/WalletBalanceFetcherTest.kt index 937aa0d32d..eed3947fb1 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/WalletBalanceFetcherTest.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/WalletBalanceFetcherTest.kt @@ -5,8 +5,13 @@ import arrow.core.left import arrow.core.right import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory import com.tangem.domain.card.CardTypesResolver +import com.tangem.domain.card.common.util.cardTypesResolver +import com.tangem.domain.common.wallets.UserWalletsListRepository +import com.tangem.domain.common.wallets.getSyncStrict +import com.tangem.domain.express.ExpressServiceFetcher import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.staking.StakingID +import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher @@ -14,7 +19,6 @@ import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher import com.tangem.domain.staking.StakingIdFactory import com.tangem.domain.staking.model.StakingIntegrationID import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher -import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.wallet.FetchingSource.* import com.tangem.domain.tokens.wallet.implementor.MultiWalletBalanceFetcher import com.tangem.domain.tokens.wallet.implementor.SingleWalletBalanceFetcher @@ -24,6 +28,7 @@ import com.tangem.test.core.assertEitherRight import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.* import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance @@ -36,7 +41,8 @@ internal class WalletBalanceFetcherTest { private val cryptoCurrencyFactory = MockCryptoCurrencyFactory() - private val currenciesRepository: CurrenciesRepository = mockk() + private val userWalletsListRepository: UserWalletsListRepository = mockk() + private val expressServiceFetcher: ExpressServiceFetcher = mockk() private val multiWalletBalanceFetcher: MultiWalletBalanceFetcher = mockk() private val singleWalletWithTokenBalanceFetcher: SingleWalletWithTokenBalanceFetcher = mockk() private val singleWalletBalanceFetcher: SingleWalletBalanceFetcher = mockk() @@ -47,7 +53,8 @@ internal class WalletBalanceFetcherTest { private val stakingIdFactory: StakingIdFactory = mockk() private val fetcher = WalletBalanceFetcher( - currenciesRepository = currenciesRepository, + userWalletsListRepository = userWalletsListRepository, + expressServiceFetcher = expressServiceFetcher, multiWalletBalanceFetcher = multiWalletBalanceFetcher, singleWalletWithTokenBalanceFetcher = singleWalletWithTokenBalanceFetcher, singleWalletBalanceFetcher = singleWalletBalanceFetcher, @@ -62,7 +69,8 @@ internal class WalletBalanceFetcherTest { @BeforeEach fun resetMocks() { clearMocks( - currenciesRepository, + userWalletsListRepository, + expressServiceFetcher, multiWalletBalanceFetcher, singleWalletWithTokenBalanceFetcher, singleWalletBalanceFetcher, @@ -70,32 +78,39 @@ internal class WalletBalanceFetcherTest { multiQuoteStatusFetcher, multiStakingBalanceFetcher, ) + mockkStatic(UserWalletsListRepository::getSyncStrict) + } + + @AfterEach + fun tearDownStaticMocks() { + unmockkStatic(UserWalletsListRepository::getSyncStrict) } @Test - fun `fetch failure if getCardTypesResolver THROWS EXCEPTION`() = runTest { + fun `fetch failure if getSyncStrict THROWS EXCEPTION`() = runTest { // Arrange val exception = IllegalStateException("Error") - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } throws exception + every { userWalletsListRepository.getSyncStrict(userWalletId) } throws exception // Act val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert val expected = exception.left() assertEither(actual, expected) - verifyOrder { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } + verifyOrder { userWalletsListRepository.getSyncStrict(userWalletId) } coVerify(inverse = true) { - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiNetworkStatusFetcher(params = any()) multiQuoteStatusFetcher(params = any()) stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any()) @@ -104,7 +119,7 @@ internal class WalletBalanceFetcherTest { } @Test - fun `fetch failure if getCardTypesResolver cannot resolve wallet type`() = runTest { + fun `fetch failure if cardTypesResolver cannot resolve wallet type`() = runTest { // Arrange val cardTypesResolver = mockk { every { isMultiwalletAllowed() } returns false @@ -112,26 +127,27 @@ internal class WalletBalanceFetcherTest { every { isSingleWallet() } returns false } - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver + mockColdWallet(cardTypesResolver) // Act val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert val expected = IllegalStateException("Unknown type of wallet: $userWalletId").left() assertEither(actual, expected) - verifyOrder { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } + verifyOrder { userWalletsListRepository.getSyncStrict(userWalletId) } coVerify(inverse = true) { - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiNetworkStatusFetcher(params = any()) multiQuoteStatusFetcher(params = any()) stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any()) @@ -148,15 +164,15 @@ internal class WalletBalanceFetcherTest { val exception = IllegalStateException("Error") - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } throws exception + mockColdWallet(cardTypesResolver) + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } throws exception // Act val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert @@ -164,13 +180,14 @@ internal class WalletBalanceFetcherTest { assertEither(actual, expected) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } coVerify(inverse = true) { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiNetworkStatusFetcher(params = any()) multiQuoteStatusFetcher(params = any()) stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any()) @@ -185,15 +202,15 @@ internal class WalletBalanceFetcherTest { every { isMultiwalletAllowed() } returns true } - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } returns emptySet() + mockColdWallet(cardTypesResolver) + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns emptySet() // Act val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert @@ -201,13 +218,14 @@ internal class WalletBalanceFetcherTest { assertEither(actual, expected) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } coVerify(inverse = true) { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiNetworkStatusFetcher(params = any()) multiQuoteStatusFetcher(params = any()) stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any()) @@ -230,8 +248,9 @@ internal class WalletBalanceFetcherTest { val exception = IllegalStateException("Error") - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } returns currencies + mockColdWallet(cardTypesResolver) + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() every { multiWalletBalanceFetcher.fetchingSources } returns setOf(NETWORK) coEvery { multiNetworkStatusFetcher(params = networkStatusFetcherParams) } returns exception.left() @@ -239,8 +258,8 @@ internal class WalletBalanceFetcherTest { val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert @@ -251,15 +270,16 @@ internal class WalletBalanceFetcherTest { assertEither(actual, expected) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiWalletBalanceFetcher.fetchingSources multiNetworkStatusFetcher(params = networkStatusFetcherParams) } coVerify(inverse = true) { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) multiQuoteStatusFetcher(params = any()) stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any()) multiStakingBalanceFetcher(params = any()) @@ -281,8 +301,9 @@ internal class WalletBalanceFetcherTest { val exception = IllegalStateException("Error") - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } returns currencies + mockColdWallet(cardTypesResolver) + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() every { multiWalletBalanceFetcher.fetchingSources } returns setOf(QUOTE) coEvery { multiQuoteStatusFetcher(params = quoteStatusFetcherParams) } returns exception.left() @@ -290,8 +311,8 @@ internal class WalletBalanceFetcherTest { val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert @@ -302,15 +323,16 @@ internal class WalletBalanceFetcherTest { assertEither(actual, expected) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiWalletBalanceFetcher.fetchingSources multiQuoteStatusFetcher(params = quoteStatusFetcherParams) } coVerify(inverse = true) { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) multiNetworkStatusFetcher(params = any()) stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any()) multiStakingBalanceFetcher(params = any()) @@ -332,8 +354,9 @@ internal class WalletBalanceFetcherTest { val exception = IllegalStateException("Error") - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } returns currencies + mockColdWallet(cardTypesResolver) + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() every { multiWalletBalanceFetcher.fetchingSources } returns setOf(STAKING) coEvery { stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.ethereum) @@ -347,8 +370,8 @@ internal class WalletBalanceFetcherTest { val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert @@ -359,8 +382,9 @@ internal class WalletBalanceFetcherTest { assertEither(actual, expected) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiWalletBalanceFetcher.fetchingSources stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.ethereum) stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar) @@ -368,8 +392,8 @@ internal class WalletBalanceFetcherTest { } coVerify(inverse = true) { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) multiNetworkStatusFetcher(params = any()) multiQuoteStatusFetcher(params = any()) } @@ -384,8 +408,9 @@ internal class WalletBalanceFetcherTest { val currencies = cryptoCurrencyFactory.ethereumAndStellar.toSet() - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } returns currencies + mockColdWallet(cardTypesResolver) + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() every { multiWalletBalanceFetcher.fetchingSources } returns setOf(STAKING) coEvery { stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = any()) @@ -395,24 +420,25 @@ internal class WalletBalanceFetcherTest { val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert assertEitherRight(actual) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiWalletBalanceFetcher.fetchingSources stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.ethereum) stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar) } coVerify(inverse = true) { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) multiNetworkStatusFetcher(params = any()) multiQuoteStatusFetcher(params = any()) multiStakingBalanceFetcher(params = any()) @@ -433,8 +459,9 @@ internal class WalletBalanceFetcherTest { ), ) - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } returns currencies + mockColdWallet(cardTypesResolver) + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() every { multiWalletBalanceFetcher.fetchingSources } returns setOf(STAKING) coEvery { stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = any()) } returns stakingId @@ -442,24 +469,25 @@ internal class WalletBalanceFetcherTest { val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert assertEitherRight(actual) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiWalletBalanceFetcher.fetchingSources stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.ethereum) stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar) } coVerify(inverse = true) { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) multiNetworkStatusFetcher(params = any()) multiQuoteStatusFetcher(params = any()) multiStakingBalanceFetcher(params = any()) @@ -481,8 +509,9 @@ internal class WalletBalanceFetcherTest { ) val stellarStakingId = Either.Left(StakingIdFactory.Error.UnsupportedCurrency) - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } returns currencies + mockColdWallet(cardTypesResolver) + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() every { multiWalletBalanceFetcher.fetchingSources } returns setOf(STAKING) coEvery { stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.ethereum) @@ -495,24 +524,25 @@ internal class WalletBalanceFetcherTest { val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert assertEitherRight(actual) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiWalletBalanceFetcher.fetchingSources stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.ethereum) stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar) } coVerify(inverse = true) { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) multiNetworkStatusFetcher(params = any()) multiQuoteStatusFetcher(params = any()) multiStakingBalanceFetcher(params = any()) @@ -545,8 +575,9 @@ internal class WalletBalanceFetcherTest { val exception = IllegalStateException("Error") - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } returns currencies + mockColdWallet(cardTypesResolver) + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() every { multiWalletBalanceFetcher.fetchingSources } returns setOf(NETWORK, QUOTE, STAKING) coEvery { multiNetworkStatusFetcher(params = networkStatusFetcherParams) } returns exception.left() coEvery { multiQuoteStatusFetcher(params = quoteStatusFetcherParams) } returns exception.left() @@ -562,8 +593,8 @@ internal class WalletBalanceFetcherTest { val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert @@ -576,8 +607,9 @@ internal class WalletBalanceFetcherTest { assertEither(actual, expected) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiWalletBalanceFetcher.fetchingSources multiNetworkStatusFetcher(params = networkStatusFetcherParams) multiQuoteStatusFetcher(params = quoteStatusFetcherParams) @@ -587,8 +619,8 @@ internal class WalletBalanceFetcherTest { } coVerify(inverse = true) { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } } @@ -616,8 +648,9 @@ internal class WalletBalanceFetcherTest { stakingIds = setOf(ethereumStakingId, stellarStakingId), ) - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } returns currencies + mockColdWallet(cardTypesResolver) + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() every { multiWalletBalanceFetcher.fetchingSources } returns setOf(NETWORK, QUOTE, STAKING) coEvery { multiNetworkStatusFetcher(params = networkStatusFetcherParams) } returns Unit.right() coEvery { multiQuoteStatusFetcher(params = quoteStatusFetcherParams) } returns Unit.right() @@ -633,8 +666,8 @@ internal class WalletBalanceFetcherTest { val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert @@ -642,8 +675,9 @@ internal class WalletBalanceFetcherTest { assertEither(actual, expected) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) multiWalletBalanceFetcher.fetchingSources multiNetworkStatusFetcher(params = networkStatusFetcherParams) multiQuoteStatusFetcher(params = quoteStatusFetcherParams) @@ -653,8 +687,8 @@ internal class WalletBalanceFetcherTest { } coVerify(inverse = true) { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } } @@ -678,10 +712,11 @@ internal class WalletBalanceFetcherTest { appCurrencyId = null, ) - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver + mockColdWallet(cardTypesResolver) coEvery { - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() every { singleWalletWithTokenBalanceFetcher.fetchingSources } returns setOf(NETWORK, QUOTE) coEvery { multiNetworkStatusFetcher(params = networkStatusFetcherParams) } returns Unit.right() coEvery { multiQuoteStatusFetcher(params = quoteStatusFetcherParams) } returns Unit.right() @@ -690,8 +725,8 @@ internal class WalletBalanceFetcherTest { val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert @@ -699,16 +734,17 @@ internal class WalletBalanceFetcherTest { assertEither(actual, expected) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) singleWalletWithTokenBalanceFetcher.fetchingSources multiNetworkStatusFetcher(params = networkStatusFetcherParams) multiQuoteStatusFetcher(params = quoteStatusFetcherParams) } coVerify(inverse = true) { - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any()) multiStakingBalanceFetcher(params = any()) } @@ -735,8 +771,9 @@ internal class WalletBalanceFetcherTest { appCurrencyId = null, ) - every { currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) } returns cardTypesResolver - coEvery { singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) } returns currencies + mockColdWallet(cardTypesResolver) + coEvery { singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() every { singleWalletBalanceFetcher.fetchingSources } returns setOf(NETWORK, QUOTE) coEvery { multiNetworkStatusFetcher(params = networkStatusFetcherParams) } returns Unit.right() coEvery { multiQuoteStatusFetcher(params = quoteStatusFetcherParams) } returns Unit.right() @@ -745,8 +782,8 @@ internal class WalletBalanceFetcherTest { val actual = fetcher( params = WalletBalanceFetcher.Params( userWalletId = userWalletId, - isPaymentAccountRefactorEnabled = false - ) + isPaymentAccountRefactorEnabled = false, + ), ) // Assert @@ -754,21 +791,89 @@ internal class WalletBalanceFetcherTest { assertEither(actual, expected) coVerifyOrder { - currenciesRepository.getCardTypesResolver(userWalletId = userWalletId) - singleWalletBalanceFetcher.getCryptoCurrencies(userWalletId = userWalletId) + userWalletsListRepository.getSyncStrict(userWalletId) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) singleWalletBalanceFetcher.fetchingSources multiNetworkStatusFetcher(params = networkStatusFetcherParams) multiQuoteStatusFetcher(params = quoteStatusFetcherParams) } coVerify(inverse = true) { - multiWalletBalanceFetcher.getCryptoCurrencies(userWalletId = any()) - singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWalletId = any()) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) stakingIdFactory.create(userWalletId = any(), cryptoCurrency = any()) multiStakingBalanceFetcher(params = any()) } } + @Test + fun `fetch successfully for hot wallet`() = runTest { + // Arrange + val hotWallet = mockk() + every { userWalletsListRepository.getSyncStrict(userWalletId) } returns hotWallet + + val currencies = cryptoCurrencyFactory.ethereumAndStellar.toSet() + + val networkStatusFetcherParams = MultiNetworkStatusFetcher.Params( + userWalletId = userWalletId, + networks = currencies.mapTo(destination = hashSetOf(), transform = CryptoCurrency::network), + ) + + val quoteStatusFetcherParams = MultiQuoteStatusFetcher.Params( + currenciesIds = currencies.mapNotNullTo(destination = hashSetOf(), transform = { it.id.rawCurrencyId }), + appCurrencyId = null, + ) + + val stakingBalanceFetcherParams = MultiStakingBalanceFetcher.Params( + userWalletId = userWalletId, + stakingIds = setOf(ethereumStakingId, stellarStakingId), + ) + + coEvery { multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) } returns currencies + coEvery { expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) } returns mockk() + every { multiWalletBalanceFetcher.fetchingSources } returns setOf(NETWORK, QUOTE, STAKING) + coEvery { multiNetworkStatusFetcher(params = networkStatusFetcherParams) } returns Unit.right() + coEvery { multiQuoteStatusFetcher(params = quoteStatusFetcherParams) } returns Unit.right() + coEvery { + stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.ethereum) + } returns Either.Right(ethereumStakingId) + coEvery { + stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = cryptoCurrencyFactory.stellar) + } returns Either.Right(stellarStakingId) + coEvery { multiStakingBalanceFetcher(params = stakingBalanceFetcherParams) } returns Unit.right() + + // Act + val actual = fetcher( + params = WalletBalanceFetcher.Params( + userWalletId = userWalletId, + isPaymentAccountRefactorEnabled = false, + ), + ) + + // Assert + val expected = Unit.right() + assertEither(actual, expected) + + coVerifyOrder { + userWalletsListRepository.getSyncStrict(userWalletId) + multiWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + expressServiceFetcher.fetch(userWallet = any(), assetIds = any()) + } + + coVerify(inverse = true) { + singleWalletWithTokenBalanceFetcher.getCryptoCurrencies(userWallet = any()) + singleWalletBalanceFetcher.getCryptoCurrencies(userWallet = any()) + } + } + + private fun mockColdWallet(cardTypesResolver: CardTypesResolver) { + val coldWallet = mockk() + every { userWalletsListRepository.getSyncStrict(userWalletId) } returns coldWallet + mockkStatic(UserWallet.Cold::cardTypesResolver) + every { coldWallet.cardTypesResolver } returns cardTypesResolver + } + private companion object { val userWalletId = UserWalletId("011") diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/MultiWalletBalanceFetcherTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/MultiWalletBalanceFetcherTest.kt index 100c5964c1..aa4e51b9e9 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/MultiWalletBalanceFetcherTest.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/MultiWalletBalanceFetcherTest.kt @@ -5,11 +5,12 @@ import arrow.core.right import com.google.common.truth.Truth import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.domain.tokens.MultiWalletAccountListFetcher import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier import com.tangem.domain.tokens.wallet.FetchingSource -import com.tangem.domain.models.wallet.UserWalletId import io.mockk.clearMocks import io.mockk.coEvery import io.mockk.every @@ -29,10 +30,10 @@ class MultiWalletBalanceFetcherTest { private val cryptoCurrencyFactory = MockCryptoCurrencyFactory() - private val multiWalletFetcher: MultiWalletCryptoCurrenciesFetcher = mockk() + private val multiWalletFetcher: MultiWalletAccountListFetcher = mockk() private val multiWalletSupplier: MultiWalletCryptoCurrenciesSupplier = mockk() private val fetcher = MultiWalletBalanceFetcher( - multiWalletCryptoCurrenciesFetcher = multiWalletFetcher, + multiWalletAccountListFetcher = multiWalletFetcher, multiWalletCryptoCurrenciesSupplier = multiWalletSupplier, ) @@ -63,7 +64,7 @@ class MultiWalletBalanceFetcherTest { val supplierFlow = flowOf(currencies) coEvery { - multiWalletFetcher(params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId)) + multiWalletFetcher(params = MultiWalletAccountListFetcher.Params(userWalletId = userWalletId)) } returns Unit.right() every { @@ -71,7 +72,7 @@ class MultiWalletBalanceFetcherTest { } returns supplierFlow // Act - val actual = fetcher.getCryptoCurrencies(userWalletId = userWalletId) + val actual = fetcher.getCryptoCurrencies(userWallet = userWallet) // Assert val expected = currencies.toSet() @@ -85,7 +86,7 @@ class MultiWalletBalanceFetcherTest { val supplierFlow = flowOf(currencies) coEvery { - multiWalletFetcher(params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId)) + multiWalletFetcher(params = MultiWalletAccountListFetcher.Params(userWalletId = userWalletId)) } returns IllegalStateException().left() every { @@ -93,7 +94,7 @@ class MultiWalletBalanceFetcherTest { } returns supplierFlow // Act - val actual = fetcher.getCryptoCurrencies(userWalletId = userWalletId) + val actual = fetcher.getCryptoCurrencies(userWallet = userWallet) // Assert val expected = currencies.toSet() @@ -106,7 +107,7 @@ class MultiWalletBalanceFetcherTest { val supplierFlow = emptyFlow>() coEvery { - multiWalletFetcher(params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId)) + multiWalletFetcher(params = MultiWalletAccountListFetcher.Params(userWalletId = userWalletId)) } returns Unit.right() every { @@ -114,7 +115,7 @@ class MultiWalletBalanceFetcherTest { } returns supplierFlow // Act - val actual = fetcher.getCryptoCurrencies(userWalletId = userWalletId) + val actual = fetcher.getCryptoCurrencies(userWallet = userWallet) // Assert val expected = emptySet() @@ -123,5 +124,8 @@ class MultiWalletBalanceFetcherTest { private companion object { val userWalletId = UserWalletId("011") + val userWallet: UserWallet = mockk { + every { walletId } returns userWalletId + } } } \ No newline at end of file diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletBalanceFetcherTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletBalanceFetcherTest.kt index 4dae4b7a01..bae0299511 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletBalanceFetcherTest.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletBalanceFetcherTest.kt @@ -2,11 +2,11 @@ package com.tangem.domain.tokens.wallet.implementor import com.google.common.truth.Truth import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory -import com.tangem.domain.tokens.repository.CurrenciesRepository +import com.tangem.domain.common.tokens.CardCryptoCurrencyFactory +import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.tokens.wallet.FetchingSource -import com.tangem.domain.models.wallet.UserWalletId import io.mockk.clearMocks -import io.mockk.coEvery +import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.BeforeEach @@ -21,12 +21,15 @@ class SingleWalletBalanceFetcherTest { private val cryptoCurrencyFactory = MockCryptoCurrencyFactory() - private val currenciesRepository: CurrenciesRepository = mockk() - private val fetcher = SingleWalletBalanceFetcher(currenciesRepository = currenciesRepository) + private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory = mockk() + + private val fetcher = SingleWalletBalanceFetcher( + cardCryptoCurrencyFactory = cardCryptoCurrencyFactory, + ) @BeforeEach fun resetMocks() { - clearMocks(currenciesRepository) + clearMocks(cardCryptoCurrencyFactory) } @Test @@ -42,15 +45,13 @@ class SingleWalletBalanceFetcherTest { @Test fun getCryptoCurrencies() = runTest { // Arrange - val userWalletId = UserWalletId("011") val currency = cryptoCurrencyFactory.ethereum + val coldWallet = mockk() - coEvery { - currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(userWalletId = userWalletId, refresh = true) - } returns currency + every { cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(coldWallet) } returns currency // Act - val actual = fetcher.getCryptoCurrencies(userWalletId = userWalletId) + val actual = fetcher.getCryptoCurrencies(userWallet = coldWallet) // Assert val expected = setOf(currency) diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletWithTokenBalanceFetcherTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletWithTokenBalanceFetcherTest.kt index 31221257e6..56d54f2d0a 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletWithTokenBalanceFetcherTest.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/wallet/implementor/SingleWalletWithTokenBalanceFetcherTest.kt @@ -2,11 +2,11 @@ package com.tangem.domain.tokens.wallet.implementor import com.google.common.truth.Truth import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory -import com.tangem.domain.tokens.repository.CurrenciesRepository +import com.tangem.domain.common.tokens.CardCryptoCurrencyFactory +import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.tokens.wallet.FetchingSource -import com.tangem.domain.models.wallet.UserWalletId import io.mockk.clearMocks -import io.mockk.coEvery +import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.BeforeEach @@ -21,12 +21,15 @@ class SingleWalletWithTokenBalanceFetcherTest { private val cryptoCurrencyFactory = MockCryptoCurrencyFactory() - private val currenciesRepository: CurrenciesRepository = mockk() - private val fetcher = SingleWalletWithTokenBalanceFetcher(currenciesRepository = currenciesRepository) + private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory = mockk() + + private val fetcher = SingleWalletWithTokenBalanceFetcher( + cardCryptoCurrencyFactory = cardCryptoCurrencyFactory, + ) @BeforeEach fun resetMocks() { - clearMocks(currenciesRepository) + clearMocks(cardCryptoCurrencyFactory) } @Test @@ -42,15 +45,15 @@ class SingleWalletWithTokenBalanceFetcherTest { @Test fun getCryptoCurrencies() = runTest { // Arrange - val userWalletId = UserWalletId("011") val currencies = cryptoCurrencyFactory.ethereumAndStellar + val coldWallet = mockk() - coEvery { - currenciesRepository.getSingleCurrencyWalletWithCardCurrencies(userWalletId = userWalletId, refresh = true) + every { + cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(coldWallet) } returns currencies // Act - val actual = fetcher.getCryptoCurrencies(userWalletId = userWalletId) + val actual = fetcher.getCryptoCurrencies(userWallet = coldWallet) // Assert val expected = currencies.toSet()