Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-13 12:58:22 +04:00
parent 9fb5124c38
commit 3b8da73b9c
18 changed files with 373 additions and 433 deletions

View file

@ -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,

View file

@ -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<Throwable, Unit> {
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)
}
}
}

View file

@ -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,
)
}

View file

@ -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,
)
}

View file

@ -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<CryptoCurrency> {
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<CryptoCurrency>,
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
}
}
}

View file

@ -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<UserWallet> {
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<UserWallet> {
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<UserWallet> {
every { walletId } returns userWalletId
every { isMultiCurrency } returns true

View file

@ -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)

View file

@ -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<MultiWalletCryptoCurrenciesFetcher.Params> {
interface MultiWalletAccountListFetcher : FlowFetcher<MultiWalletAccountListFetcher.Params> {
data class Params(val userWalletId: UserWalletId)
}

View file

@ -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<CryptoCurrency>
/**
* 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?
}

View file

@ -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<FetchingSource>
/** Get crypto currencies of wallet with [userWalletId] */
suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set<CryptoCurrency>
/** Get crypto currencies of [userWallet] */
suspend fun getCryptoCurrencies(userWallet: UserWallet): Set<CryptoCurrency>
}

View file

@ -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<CryptoCurrency>) {
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,

View file

@ -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<CryptoCurrency> {
multiWalletCryptoCurrenciesFetcher(
params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId),
override suspend fun getCryptoCurrencies(userWallet: UserWallet): Set<CryptoCurrency> {
val userWalletId = userWallet.walletId
multiWalletAccountListFetcher(
params = MultiWalletAccountListFetcher.Params(userWalletId = userWalletId),
)
.onLeft(Timber::e)

View file

@ -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<FetchingSource> = setOf(
@ -22,12 +23,13 @@ internal class SingleWalletBalanceFetcher(
FetchingSource.QUOTE,
)
override suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set<CryptoCurrency> {
val primaryCurrency = currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(
userWalletId = userWalletId,
refresh = true,
override suspend fun getCryptoCurrencies(userWallet: UserWallet): Set<CryptoCurrency> {
val coldWallet = userWallet.requireColdWallet()
val currency = cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(
userWallet = coldWallet,
)
return setOf(primaryCurrency)
return setOf(currency)
}
}

View file

@ -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<FetchingSource> = setOf(
@ -22,10 +23,11 @@ internal class SingleWalletWithTokenBalanceFetcher(
FetchingSource.QUOTE,
)
override suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set<CryptoCurrency> {
return currenciesRepository.getSingleCurrencyWalletWithCardCurrencies(
userWalletId = userWalletId,
refresh = true,
).toSet()
override suspend fun getCryptoCurrencies(userWallet: UserWallet): Set<CryptoCurrency> {
val coldWallet = userWallet.requireColdWallet()
val currencies = cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(coldWallet)
return currencies.toSet()
}
}

View file

@ -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<CardTypesResolver> {
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<UserWallet.Hot>()
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<UserWallet.Cold>()
every { userWalletsListRepository.getSyncStrict(userWalletId) } returns coldWallet
mockkStatic(UserWallet.Cold::cardTypesResolver)
every { coldWallet.cardTypesResolver } returns cardTypesResolver
}
private companion object {
val userWalletId = UserWalletId("011")

View file

@ -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<Set<CryptoCurrency>>()
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<CryptoCurrency>()
@ -123,5 +124,8 @@ class MultiWalletBalanceFetcherTest {
private companion object {
val userWalletId = UserWalletId("011")
val userWallet: UserWallet = mockk {
every { walletId } returns userWalletId
}
}
}

View file

@ -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<UserWallet.Cold>()
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)

View file

@ -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<UserWallet.Cold>()
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()