Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-01 14:42:30 +04:00
parent 799c132a5b
commit 6c16caedba
22 changed files with 288 additions and 82 deletions

View file

@ -4,7 +4,9 @@ import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.domain.managetokens.*
import com.tangem.domain.managetokens.repository.CustomTokensRepository
import com.tangem.domain.managetokens.repository.ManageTokensRepository
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.tokens.repository.QuotesRepository
@ -70,6 +72,8 @@ internal object ManageTokensDomainModule {
derivationsRepository: DerivationsRepository,
stakingRepository: StakingRepository,
quotesRepository: QuotesRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): SaveManagedTokensUseCase {
return SaveManagedTokensUseCase(
customTokensRepository = customTokensRepository,
@ -79,6 +83,8 @@ internal object ManageTokensDomainModule {
derivationsRepository = derivationsRepository,
stakingRepository = stakingRepository,
quotesRepository = quotesRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
}

View file

@ -4,7 +4,9 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains
import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.domain.markets.*
import com.tangem.domain.markets.repositories.MarketsTokenRepository
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.tokens.repository.QuotesRepository
@ -60,6 +62,8 @@ object MarketsDomainModule {
networksRepository: NetworksRepository,
stakingRepository: StakingRepository,
quotesRepository: QuotesRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): SaveMarketTokensUseCase {
return SaveMarketTokensUseCase(
derivationsRepository = derivationsRepository,
@ -68,6 +72,8 @@ object MarketsDomainModule {
networksRepository = networksRepository,
stakingRepository = stakingRepository,
quotesRepository = quotesRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
}

View file

@ -3,6 +3,8 @@ package com.tangem.tap.di.domain
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.promo.PromoRepository
import com.tangem.domain.staking.repositories.StakingRepository
@ -32,12 +34,16 @@ internal object TokensDomainModule {
networksRepository: NetworksRepository,
stakingRepository: StakingRepository,
quotesRepository: QuotesRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): AddCryptoCurrenciesUseCase {
return AddCryptoCurrenciesUseCase(
currenciesRepository = currenciesRepository,
networksRepository = networksRepository,
stakingRepository = stakingRepository,
quotesRepository = quotesRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
}
@ -48,12 +54,16 @@ internal object TokensDomainModule {
quotesRepository: QuotesRepository,
networksRepository: NetworksRepository,
stakingRepository: StakingRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): FetchTokenListUseCase {
return FetchTokenListUseCase(
currenciesRepository = currenciesRepository,
networksRepository = networksRepository,
quotesRepository = quotesRepository,
stakingRepository = stakingRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
}
@ -157,12 +167,16 @@ internal object TokensDomainModule {
quotesRepository: QuotesRepository,
networksRepository: NetworksRepository,
stakingRepository: StakingRepository,
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): FetchCurrencyStatusUseCase {
return FetchCurrencyStatusUseCase(
currenciesRepository,
networksRepository,
quotesRepository,
stakingRepository,
currenciesRepository = currenciesRepository,
networksRepository = networksRepository,
quotesRepository = quotesRepository,
stakingRepository = stakingRepository,
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
}
@ -173,8 +187,17 @@ internal object TokensDomainModule {
quotesRepository: QuotesRepository,
networksRepository: NetworksRepository,
stakingRepository: StakingRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): FetchCardTokenListUseCase {
return FetchCardTokenListUseCase(currenciesRepository, networksRepository, quotesRepository, stakingRepository)
return FetchCardTokenListUseCase(
currenciesRepository = currenciesRepository,
networksRepository = networksRepository,
quotesRepository = quotesRepository,
stakingRepository = stakingRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
}
@Provides
@ -284,9 +307,13 @@ internal object TokensDomainModule {
@Singleton
fun provideUpdateDelayedCurrencyStatusUseCase(
networksRepository: NetworksRepository,
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): UpdateDelayedNetworkStatusUseCase {
return UpdateDelayedNetworkStatusUseCase(
networksRepository = networksRepository,
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
}
@ -362,6 +389,7 @@ internal object TokensDomainModule {
networksRepository: NetworksRepository,
stakingRepository: StakingRepository,
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
): BaseCurrenciesStatusesOperations {
return CachedCurrenciesStatusesOperations(
@ -370,6 +398,7 @@ internal object TokensDomainModule {
networksRepository = networksRepository,
stakingRepository = stakingRepository,
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
@ -384,6 +413,7 @@ internal object TokensDomainModule {
networksRepository: NetworksRepository,
stakingRepository: StakingRepository,
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
): BaseCurrencyStatusOperations {
return CachedCurrenciesStatusesOperations(
@ -392,6 +422,7 @@ internal object TokensDomainModule {
networksRepository = networksRepository,
stakingRepository = stakingRepository,
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)

View file

@ -2,6 +2,8 @@ package com.tangem.tap.di.domain
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.transaction.FeeRepository
@ -49,12 +51,16 @@ internal object TransactionDomainModule {
walletManagersFacade: WalletManagersFacade,
currenciesRepository: CurrenciesRepository,
networksRepository: NetworksRepository,
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): AssociateAssetUseCase {
return AssociateAssetUseCase(
cardSdkConfigRepository = cardSdkConfigRepository,
walletManagersFacade = walletManagersFacade,
currenciesRepository = currenciesRepository,
networksRepository = networksRepository,
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
}

View file

@ -20,11 +20,13 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object NetworksStatusesStoreModule {
@Singleton
@Provides
fun providePersistenceNetworksStatusesStore(
@NetworkMoshi moshi: Moshi,
@ -42,6 +44,7 @@ internal object NetworksStatusesStoreModule {
)
}
@Singleton
@Provides
fun provideNetworksStatusesStore(
persistenceNetworksStatusesStore: DataStore<Map<String, Set<NetworkStatusDM>>>,

View file

@ -26,6 +26,8 @@ interface CardTypesResolver {
fun isDevKit(): Boolean
fun isSingleWallet(): Boolean
fun isSingleWalletWithToken(): Boolean
fun isMultiwalletAllowed(): Boolean

View file

@ -50,6 +50,8 @@ internal class TangemCardTypesResolver(
override fun isDevKit(): Boolean = card.batchId == DEV_KIT_CARD_BATCH_ID
override fun isSingleWallet(): Boolean = !isMultiwalletAllowed() && !isSingleWalletWithToken() && !isVisaWallet()
override fun isSingleWalletWithToken(): Boolean = walletData?.token != null && !isMultiwalletAllowed()
override fun isMultiwalletAllowed(): Boolean {

View file

@ -11,8 +11,9 @@ android {
dependencies {
/* Domain */
api(projects.domain.manageTokens.models)
api(projects.domain.core)
api(projects.domain.manageTokens.models)
api(projects.domain.networks)
implementation(projects.domain.wallets.models)
implementation(projects.domain.tokens.models)
implementation(projects.domain.staking)

View file

@ -5,7 +5,9 @@ import arrow.core.flatten
import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
import com.tangem.domain.managetokens.repository.CustomTokensRepository
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.repository.CurrenciesRepository
@ -23,6 +25,8 @@ class SaveManagedTokensUseCase(
private val derivationsRepository: DerivationsRepository,
private val stakingRepository: StakingRepository,
private val quotesRepository: QuotesRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(
@ -92,11 +96,20 @@ class SaveManagedTokensUseCase(
val networkToUpdate = currenciesToAdd.map { it.network }
.subtract(existingCurrencies.map { it.network }.toSet())
networksRepository.getNetworkStatusesSync(
userWalletId = userWalletId,
networks = networksToUpdate + networkToUpdate,
refresh = true,
)
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
multiNetworkStatusFetcher(
MultiNetworkStatusFetcher.Params(
userWalletId = userWalletId,
networks = networksToUpdate + networkToUpdate,
),
)
} else {
networksRepository.getNetworkStatusesSync(
userWalletId = userWalletId,
networks = networksToUpdate + networkToUpdate,
refresh = true,
)
}
}
private suspend fun refreshUpdatedYieldBalances(

View file

@ -15,12 +15,13 @@ dependencies {
api(projects.domain.appCurrency.models)
api(projects.domain.card)
api(projects.domain.core)
api(projects.domain.markets.models)
api(projects.domain.wallets.models)
api(projects.domain.models)
api(projects.domain.legacy)
api(projects.domain.wallets)
api(projects.domain.markets.models)
api(projects.domain.models)
api(projects.domain.networks)
api(projects.domain.staking)
api(projects.domain.wallets)
api(projects.domain.wallets.models)
implementation(projects.domain.tokens.models)
implementation(projects.domain.tokens)

View file

@ -3,7 +3,9 @@ package com.tangem.domain.markets
import arrow.core.Either
import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.domain.markets.repositories.MarketsTokenRepository
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.repository.CurrenciesRepository
@ -20,6 +22,7 @@ import com.tangem.domain.wallets.models.UserWalletId
*
[REDACTED_AUTHOR]
*/
@Suppress("LongParameterList")
class SaveMarketTokensUseCase(
private val derivationsRepository: DerivationsRepository,
private val marketsTokenRepository: MarketsTokenRepository,
@ -27,6 +30,8 @@ class SaveMarketTokensUseCase(
private val networksRepository: NetworksRepository,
private val stakingRepository: StakingRepository,
private val quotesRepository: QuotesRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(
@ -73,11 +78,20 @@ class SaveMarketTokensUseCase(
}
private suspend fun refreshUpdatedNetworks(userWalletId: UserWalletId, addedCurrencies: List<CryptoCurrency>) {
networksRepository.getNetworkStatusesSync(
userWalletId = userWalletId,
networks = addedCurrencies.map(CryptoCurrency::network).toSet(),
refresh = true,
)
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
multiNetworkStatusFetcher(
MultiNetworkStatusFetcher.Params(
userWalletId = userWalletId,
networks = addedCurrencies.map(CryptoCurrency::network).toSet(),
),
)
} else {
networksRepository.getNetworkStatusesSync(
userWalletId = userWalletId,
networks = addedCurrencies.map(CryptoCurrency::network).toSet(),
refresh = true,
)
}
}
private suspend fun refreshUpdatedYieldBalances(

View file

@ -5,6 +5,7 @@ import arrow.core.raise.Raise
import arrow.core.raise.catch
import arrow.core.raise.either
import arrow.core.toNonEmptyListOrNull
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
@ -25,6 +26,8 @@ class AddCryptoCurrenciesUseCase(
private val networksRepository: NetworksRepository,
private val stakingRepository: StakingRepository,
private val quotesRepository: QuotesRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
/**
@ -132,16 +135,25 @@ class AddCryptoCurrenciesUseCase(
val networkToUpdate = currenciesToAdd.map { it.network }
.subtract(existingCurrencies.map { it.network }.toSet())
catch(
{
networksRepository.getNetworkStatusesSync(
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
multiNetworkStatusFetcher(
MultiNetworkStatusFetcher.Params(
userWalletId = userWalletId,
networks = networksToUpdate + networkToUpdate,
refresh = true,
)
},
) {
raise(it)
),
)
} else {
catch(
{
networksRepository.getNetworkStatusesSync(
userWalletId = userWalletId,
networks = networksToUpdate + networkToUpdate,
refresh = true,
)
},
) {
raise(it)
}
}
}

View file

@ -4,6 +4,7 @@ import arrow.core.Either
import arrow.core.raise.Raise
import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.model.CryptoCurrency
@ -21,6 +22,8 @@ class FetchCardTokenListUseCase(
private val networksRepository: NetworksRepository,
private val quotesRepository: QuotesRepository,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(userWalletId: UserWalletId, refresh: Boolean = false): Either<TokenListError, Unit> {
@ -73,10 +76,17 @@ class FetchCardTokenListUseCase(
networks: Set<Network>,
refresh: Boolean,
) {
catch(
block = { networksRepository.getNetworkStatusesSync(userWalletId, networks, refresh) },
catch = { raise(TokenListError.DataError(it)) },
)
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
multiNetworkStatusFetcher(
MultiNetworkStatusFetcher.Params(userWalletId = userWalletId, networks = networks),
)
.mapLeft { TokenListError.DataError(it) }
} else {
catch(
block = { networksRepository.getNetworkStatusesSync(userWalletId, networks, refresh) },
catch = { raise(TokenListError.DataError(it)) },
)
}
}
private suspend fun fetchQuotes(currenciesIds: Set<CryptoCurrency.RawID>, refresh: Boolean) {

View file

@ -4,6 +4,7 @@ import arrow.core.Either
import arrow.core.raise.Raise
import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.model.CryptoCurrency
@ -31,6 +32,8 @@ class FetchCurrencyStatusUseCase(
private val networksRepository: NetworksRepository,
private val quotesRepository: QuotesRepository,
private val stakingRepository: StakingRepository,
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
/**
@ -116,10 +119,17 @@ class FetchCurrencyStatusUseCase(
network: Network,
refresh: Boolean,
) {
catch(
block = { networksRepository.getNetworkStatusesSync(userWalletId, setOf(network), refresh) },
) {
raise(CurrencyStatusError.DataError(it))
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
singleNetworkStatusFetcher(
params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network),
)
.mapLeft { CurrencyStatusError.DataError(it) }
} else {
catch(
block = { networksRepository.getNetworkStatusesSync(userWalletId, setOf(network), refresh) },
) {
raise(CurrencyStatusError.DataError(it))
}
}
}

View file

@ -6,6 +6,7 @@ import arrow.core.raise.catch
import arrow.core.raise.either
import arrow.core.raise.ensureNotNull
import arrow.core.toNonEmptyListOrNull
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.model.CryptoCurrency
@ -33,6 +34,8 @@ class FetchTokenListUseCase(
private val networksRepository: NetworksRepository,
private val quotesRepository: QuotesRepository,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
/**
@ -104,10 +107,20 @@ class FetchTokenListUseCase(
networks: Set<Network>,
refresh: Boolean,
) {
catch(
block = { networksRepository.getNetworkStatusesSync(userWalletId, networks, refresh) },
) {
raise(TokenListError.DataError(it))
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
if (refresh) {
multiNetworkStatusFetcher(
params = MultiNetworkStatusFetcher.Params(userWalletId, networks),
)
.mapLeft { TokenListError.DataError(it) }
.bind()
}
} else {
catch(
block = { networksRepository.getNetworkStatusesSync(userWalletId, networks, refresh) },
) {
raise(TokenListError.DataError(it))
}
}
}

View file

@ -4,6 +4,7 @@ import arrow.core.Either
import arrow.core.raise.Raise
import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.repository.NetworksRepository
@ -20,6 +21,8 @@ import kotlinx.coroutines.delay
class UpdateDelayedNetworkStatusUseCase(
private val networksRepository: NetworksRepository,
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
/**
@ -47,10 +50,17 @@ class UpdateDelayedNetworkStatusUseCase(
network: Network,
refresh: Boolean,
) {
catch(
block = { networksRepository.getNetworkStatusesSync(userWalletId, setOf(network), refresh) },
) {
raise(CurrencyStatusError.DataError(it))
if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
singleNetworkStatusFetcher(
params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network),
)
.mapLeft { CurrencyStatusError.DataError(it) }
} else {
catch(
block = { networksRepository.getNetworkStatusesSync(userWalletId, setOf(network), refresh) },
) {
raise(CurrencyStatusError.DataError(it))
}
}
}
}

View file

@ -6,9 +6,14 @@ import arrow.core.raise.catch
import arrow.core.raise.either
import arrow.core.raise.recover
import com.tangem.domain.core.utils.EitherFlow
import com.tangem.domain.networks.multi.MultiNetworkStatusProducer
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
import com.tangem.domain.networks.single.SingleNetworkStatusProducer
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.staking.model.stakekit.YieldBalance
import com.tangem.domain.staking.model.stakekit.YieldBalanceList
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.model.*
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error
import com.tangem.domain.tokens.repository.CurrenciesRepository
@ -17,7 +22,6 @@ import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.tokens.utils.CurrencyStatusProxyCreator
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
/**
* Base operations for working with currency status
@ -29,12 +33,15 @@ import kotlinx.coroutines.launch
*
[REDACTED_AUTHOR]
*/
@Suppress("LargeClass")
@Suppress("LargeClass", "LongParameterList")
abstract class BaseCurrencyStatusOperations(
private val currenciesRepository: CurrenciesRepository,
private val quotesRepository: QuotesRepository,
private val networksRepository: NetworksRepository,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
protected val currencyStatusProxyCreator = CurrencyStatusProxyCreator(stakingRepository)
@ -102,26 +109,13 @@ abstract class BaseCurrencyStatusOperations(
val yieldBalanceFlow = getYieldBalance(userWalletId = userWalletId, cryptoCurrency = currency)
return channelFlow {
launch {
fetchComponents(
userWalletId = userWalletId,
networks = nonEmptySetOf(currency.network),
currenciesIds = nonEmptySetOf(currency.id),
currencies = nonEmptyListOf(currency),
)
}
combine(quoteFlow, statusFlow, yieldBalanceFlow) { maybeQuote, maybeNetworkStatus, maybeYieldBalance ->
currencyStatusProxyCreator.createCurrencyStatus(
currency = currency,
maybeQuote = maybeQuote,
maybeNetworkStatus = maybeNetworkStatus,
maybeYieldBalance = maybeYieldBalance,
)
}
.onEach(::send)
.launchIn(this)
return combine(quoteFlow, statusFlow, yieldBalanceFlow) { maybeQuote, maybeNetworkStatus, maybeYieldBalance ->
currencyStatusProxyCreator.createCurrencyStatus(
currency = currency,
maybeQuote = maybeQuote,
maybeNetworkStatus = maybeNetworkStatus,
maybeYieldBalance = maybeYieldBalance,
)
}
}
@ -179,12 +173,25 @@ abstract class BaseCurrencyStatusOperations(
}
val quote = cryptoCurrencyId.rawCurrencyId?.let { quotesRepository.getQuoteSync(it) }?.right()
?: Error.EmptyQuotes.left()
val networkStatuses =
val networkStatuses = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
singleNetworkStatusSupplier(
params = SingleNetworkStatusProducer.Params(
userWalletId = userWalletId,
network = currency.network,
),
)
.firstOrNull()
.right()
} else {
networksRepository.getNetworkStatusesSync(
userWalletId = userWalletId,
networks = setOf(currency.network),
refresh = false,
).firstOrNull { it.network == currency.network }.right()
)
.firstOrNull { it.network == currency.network }
.right()
}
val yieldBalances = getYieldBalanceSync(userWalletId, currency)
@ -231,8 +238,17 @@ abstract class BaseCurrencyStatusOperations(
val (networks, currenciesIds) = getIds(nonEmptyCurrencies)
val rawIds = currenciesIds.mapNotNull { it.rawCurrencyId }.toSet()
val quotes = quotesRepository.getQuotesSync(rawIds, false).right()
val networkStatuses =
val networkStatuses = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
multiNetworkStatusSupplier(
params = MultiNetworkStatusProducer.Params(userWalletId = userWalletId),
)
.firstOrNull()
.orEmpty()
.right()
} else {
networksRepository.getNetworkStatusesSync(userWalletId, networks, false).right()
}
val yieldBalances = getYieldBalancesSync(userWalletId, nonEmptyCurrencies)
return currencyStatusProxyCreator.createCurrenciesStatuses(
@ -259,14 +275,27 @@ abstract class BaseCurrencyStatusOperations(
},
catch = { Error.DataError(it).left() },
)
val networkStatus = catch(
block = {
networksRepository.getNetworkStatusesSync(userWalletId, setOf(currency.network))
.firstOrNull { it.network == currency.network }
.right()
},
catch = { Error.DataError(it).left() },
)
val networkStatus = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
singleNetworkStatusSupplier(
params = SingleNetworkStatusProducer.Params(
userWalletId = userWalletId,
network = currency.network,
),
)
.firstOrNull()
.right()
} else {
catch(
block = {
networksRepository.getNetworkStatusesSync(userWalletId, setOf(currency.network))
.firstOrNull { it.network == currency.network }
.right()
},
catch = { Error.DataError(it).left() },
)
}
val yieldBalances = getYieldBalanceSync(userWalletId, currency)
return currencyStatusProxyCreator.createCurrencyStatus(

View file

@ -11,6 +11,7 @@ import com.tangem.domain.core.utils.EitherFlow
import com.tangem.domain.core.utils.lceContent
import com.tangem.domain.core.utils.lceError
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
import com.tangem.domain.networks.single.SingleNetworkStatusProducer
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.staking.model.stakekit.YieldBalance
@ -36,10 +37,19 @@ class CachedCurrenciesStatusesOperations(
private val networksRepository: NetworksRepository,
private val stakingRepository: StakingRepository,
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) : BaseCurrenciesStatusesOperations,
BaseCurrencyStatusOperations(currenciesRepository, quotesRepository, networksRepository, stakingRepository) {
BaseCurrencyStatusOperations(
currenciesRepository = currenciesRepository,
quotesRepository = quotesRepository,
networksRepository = networksRepository,
stakingRepository = stakingRepository,
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
tokensFeatureToggles = tokensFeatureToggles,
) {
override fun getCurrenciesStatuses(
userWalletId: UserWalletId,

View file

@ -183,6 +183,7 @@ internal class GetPrimaryCurrencyStatusUpdatesUseCaseTest {
},
singleNetworkStatusSupplier = mockk(),
multiNetworkStatusFetcher = mockk(),
multiNetworkStatusSupplier = mockk(),
),
dispatchers = dispatchers,
)

View file

@ -32,4 +32,5 @@ dependencies {
implementation(projects.domain.transaction.models)
implementation(projects.domain.demo)
implementation(projects.domain.card)
api(projects.domain.networks)
}

View file

@ -5,6 +5,9 @@ import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.blockchain.extensions.SimpleResult
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.networks.single.SingleNetworkStatusProducer
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyAmountStatus
import com.tangem.domain.tokens.model.NetworkStatus
@ -14,12 +17,15 @@ import com.tangem.domain.transaction.error.AssociateAssetError
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.isNullOrZero
import kotlinx.coroutines.flow.firstOrNull
class AssociateAssetUseCase(
private val cardSdkConfigRepository: CardSdkConfigRepository,
private val walletManagersFacade: WalletManagersFacade,
private val currenciesRepository: CurrenciesRepository,
private val networksRepository: NetworksRepository,
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(
@ -53,13 +59,25 @@ class AssociateAssetUseCase(
}
private suspend fun isBalanceZero(userWalletId: UserWalletId, currency: CryptoCurrency): Boolean {
val networkStatus = networksRepository.getNetworkStatusesSync(
userWalletId = userWalletId,
networks = setOf(currency.network),
).find { it.network == currency.network }
val networkStatus = if (tokensFeatureToggles.isNetworksLoadingRefactoringEnabled) {
singleNetworkStatusSupplier(
params = SingleNetworkStatusProducer.Params(
userWalletId = userWalletId,
network = currency.network,
),
)
.firstOrNull()
} else {
networksRepository.getNetworkStatusesSync(
userWalletId = userWalletId,
networks = setOf(currency.network),
).find { it.network == currency.network }
}
val networkCoinAmountStatus = (networkStatus?.value as? NetworkStatus.Verified)
?.amounts
?.get(currency.id)
return networkCoinAmountStatus is CryptoCurrencyAmountStatus.Loaded &&
networkCoinAmountStatus.value.isNullOrZero()
}

View file

@ -10,8 +10,10 @@ import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.nft.FetchNFTCollectionsUseCase
import com.tangem.domain.settings.*
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.repository.WalletsRepository
@ -79,6 +81,7 @@ internal class WalletModel @Inject constructor(
private val analyticsEventsHandler: AnalyticsEventHandler,
private val fetchNFTCollectionsUseCase: FetchNFTCollectionsUseCase,
private val walletsRepository: WalletsRepository,
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
val screenLifecycleProvider: ScreenLifecycleProvider,
val innerWalletRouter: InnerWalletRouter,
) : Model() {
@ -353,6 +356,10 @@ internal class WalletModel @Inject constructor(
coroutineScope = modelScope,
)
if (action.selectedWallet.scanResponse.cardTypesResolver.isSingleWallet()) {
fetchCurrencyStatusUseCase(userWalletId = action.selectedWallet.walletId)
}
if (action.wallets.size > 1 && isWalletsScrollPreviewEnabled()) {
withContext(dispatchers.io) { delay(timeMillis = 1_800) }