Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-03 09:55:24 +04:00
parent 38614dbf4f
commit 39c859f73a
31 changed files with 142 additions and 546 deletions

View file

@ -6,7 +6,6 @@ import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -33,29 +32,21 @@ internal object NFTDomainModule {
@Provides
@Singleton
fun providesFetchNFTCollectionsUseCase(
currenciesRepository: CurrenciesRepository,
nftRepository: NFTRepository,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): FetchNFTCollectionsUseCase = FetchNFTCollectionsUseCase(
currenciesRepository = currenciesRepository,
nftRepository = nftRepository,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
@Provides
@Singleton
fun providesRefreshAllNFTUseCase(
currenciesRepository: CurrenciesRepository,
nftRepository: NFTRepository,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): RefreshAllNFTUseCase = RefreshAllNFTUseCase(
currenciesRepository = currenciesRepository,
nftRepository = nftRepository,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
@Provides
@ -127,16 +118,12 @@ internal object NFTDomainModule {
fun provideDisableWalletNFTUseCase(
walletsRepository: WalletsRepository,
nftRepository: NFTRepository,
currenciesRepository: CurrenciesRepository,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): DisableWalletNFTUseCase {
return DisableWalletNFTUseCase(
walletsRepository = walletsRepository,
nftRepository = nftRepository,
currenciesRepository = currenciesRepository,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
}

View file

@ -47,7 +47,6 @@ internal object TokensDomainModule {
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
stakingIdFactory: StakingIdFactory,
): AddCryptoCurrenciesUseCase {
return AddCryptoCurrenciesUseCase(
@ -56,7 +55,6 @@ internal object TokensDomainModule {
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
singleYieldBalanceFetcher = singleYieldBalanceFetcher,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
stakingIdFactory = stakingIdFactory,
)
}
@ -111,13 +109,11 @@ internal object TokensDomainModule {
currenciesRepository: CurrenciesRepository,
walletManagersFacade: WalletManagersFacade,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): RemoveCurrencyUseCase {
return RemoveCurrencyUseCase(
currenciesRepository = currenciesRepository,
walletManagersFacade = walletManagersFacade,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
}
@ -156,7 +152,6 @@ internal object TokensDomainModule {
dispatchers: CoroutineDispatcherProvider,
baseCurrencyStatusOperations: BaseCurrencyStatusOperations,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): GetCurrencyWarningsUseCase {
return GetCurrencyWarningsUseCase(
walletManagersFacade = walletManagersFacade,
@ -165,7 +160,6 @@ internal object TokensDomainModule {
currencyChecksRepository = currencyChecksRepository,
currencyStatusOperations = baseCurrencyStatusOperations,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
}
@ -177,7 +171,6 @@ internal object TokensDomainModule {
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
stakingIdFactory: StakingIdFactory,
): FetchCurrencyStatusUseCase {
return FetchCurrencyStatusUseCase(
@ -186,7 +179,6 @@ internal object TokensDomainModule {
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
singleYieldBalanceFetcher = singleYieldBalanceFetcher,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
stakingIdFactory = stakingIdFactory,
)
}
@ -214,9 +206,8 @@ internal object TokensDomainModule {
fun provideGetCryptoCurrencyUseCase(
currenciesRepository: CurrenciesRepository,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): GetCryptoCurrencyUseCase {
return GetCryptoCurrencyUseCase(currenciesRepository, multiWalletCryptoCurrenciesSupplier, tokensFeatureToggles)
return GetCryptoCurrencyUseCase(currenciesRepository, multiWalletCryptoCurrenciesSupplier)
}
@Provides
@ -238,13 +229,11 @@ internal object TokensDomainModule {
fun provideApplyTokenListSortingUseCase(
currenciesRepository: CurrenciesRepository,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
dispatchers: CoroutineDispatcherProvider,
): ApplyTokenListSortingUseCase {
return ApplyTokenListSortingUseCase(
currenciesRepository = currenciesRepository,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
dispatchers = dispatchers,
)
}
@ -304,14 +293,10 @@ internal object TokensDomainModule {
@Provides
@Singleton
fun provideIsCryptoCurrencyCoinCouldHideUseCase(
currenciesRepository: CurrenciesRepository,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): IsCryptoCurrencyCoinCouldHideUseCase {
return IsCryptoCurrencyCoinCouldHideUseCase(
currenciesRepository = currenciesRepository,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
}
@ -330,13 +315,11 @@ internal object TokensDomainModule {
fun provideGetBalanceNotEnoughForFeeWarningUseCase(
currenciesRepository: CurrenciesRepository,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
dispatchers: CoroutineDispatcherProvider,
): GetBalanceNotEnoughForFeeWarningUseCase {
return GetBalanceNotEnoughForFeeWarningUseCase(
currenciesRepository = currenciesRepository,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
dispatchers = dispatchers,
)
}
@ -377,16 +360,12 @@ internal object TokensDomainModule {
@Provides
@Singleton
fun provideRefreshMultiCurrencyWalletQuotesUseCase(
currenciesRepository: CurrenciesRepository,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): RefreshMultiCurrencyWalletQuotesUseCase {
return RefreshMultiCurrencyWalletQuotesUseCase(
currenciesRepository = currenciesRepository,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
}
@ -402,18 +381,13 @@ internal object TokensDomainModule {
@Provides
@Singleton
fun provideBaseCurrencyStatusOperations(
tokensFeatureToggles: TokensFeatureToggles,
currenciesRepository: CurrenciesRepository,
quotesRepository: QuotesRepository,
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
multiYieldBalanceSupplier: MultiYieldBalanceSupplier,
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
stakingIdFactory: StakingIdFactory,
): BaseCurrencyStatusOperations {
@ -422,15 +396,10 @@ internal object TokensDomainModule {
quotesRepository = quotesRepository,
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
singleQuoteStatusSupplier = singleQuoteStatusSupplier,
singleYieldBalanceSupplier = singleYieldBalanceSupplier,
multiYieldBalanceSupplier = multiYieldBalanceSupplier,
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
stakingIdFactory = stakingIdFactory,
)
}

View file

@ -6,8 +6,6 @@ import com.tangem.domain.demo.models.DemoConfig
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.transaction.FeeRepository
import com.tangem.domain.transaction.TransactionRepository
import com.tangem.domain.transaction.WalletAddressServiceRepository
@ -63,18 +61,14 @@ internal object TransactionDomainModule {
fun provideAssociateAssetUseCase(
cardSdkConfigRepository: CardSdkConfigRepository,
walletManagersFacade: WalletManagersFacade,
currenciesRepository: CurrenciesRepository,
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): AssociateAssetUseCase {
return AssociateAssetUseCase(
cardSdkConfigRepository = cardSdkConfigRepository,
walletManagersFacade = walletManagersFacade,
currenciesRepository = currenciesRepository,
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
}

View file

@ -4,9 +4,5 @@ import com.tangem.core.configtoggle.feature.FeatureTogglesManager
import com.tangem.domain.tokens.TokensFeatureToggles
internal class DefaultTokensFeatureToggles(
private val featureTogglesManager: FeatureTogglesManager,
) : TokensFeatureToggles {
override val isWalletBalanceFetcherEnabled: Boolean
get() = featureTogglesManager.isFeatureEnabled(name = "WALLET_BALANCE_FETCHER_ENABLED")
}
@Suppress("UnusedPrivateMember") private val featureTogglesManager: FeatureTogglesManager,
) : TokensFeatureToggles

View file

@ -43,10 +43,6 @@
"name": "SEND_REDESIGN_ENABLED",
"version": "5.28.0"
},
{
"name": "WALLET_BALANCE_FETCHER_ENABLED",
"version": "5.27.0"
},
{
"name": "HOT_WALLET_ENABLED",
"version": "undefined"

View file

@ -21,8 +21,6 @@ import com.tangem.datasource.di.SdkMoshi
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.datasource.local.walletconnect.WalletConnectStore
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.walletconnect.WcPairService
import com.tangem.domain.walletconnect.WcRequestService
import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
@ -177,15 +175,11 @@ internal object WalletConnectDataModule {
fun wcNetworksConverter(
namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>,
walletManagersFacade: WalletManagersFacade,
currenciesRepository: CurrenciesRepository,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): WcNetworksConverter = WcNetworksConverter(
namespaceConverters = namespaceConverters,
walletManagersFacade = walletManagersFacade,
currenciesRepository = currenciesRepository,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
@Provides
@ -193,15 +187,11 @@ internal object WalletConnectDataModule {
fun associateNetworksDelegate(
namespaceConverters: Set<@JvmSuppressWildcards WcNamespaceConverter>,
getWallets: GetWalletsUseCase,
currenciesRepository: CurrenciesRepository,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): AssociateNetworksDelegate = AssociateNetworksDelegate(
namespaceConverters = namespaceConverters,
getWallets = getWallets,
currenciesRepository = currenciesRepository,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
@Provides

View file

@ -10,8 +10,6 @@ import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.isMultiCurrency
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.walletconnect.model.WcPairError
import com.tangem.domain.walletconnect.model.WcSessionProposal.ProposalNetwork
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
@ -19,9 +17,7 @@ import com.tangem.domain.wallets.usecase.GetWalletsUseCase
internal class AssociateNetworksDelegate(
private val namespaceConverters: Set<WcNamespaceConverter>,
private val getWallets: GetWalletsUseCase,
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
@Throws(WcPairError.UnsupportedBlockchains::class)
@ -96,14 +92,10 @@ internal class AssociateNetworksDelegate(
}
private suspend fun getWalletNetworks(userWalletId: UserWalletId): List<Network> {
return if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
}
return multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId),
)
.orEmpty()
.filterIsInstance<CryptoCurrency.Coin>()
.map(CryptoCurrency.Coin::network)
// flatten all derivation

View file

@ -9,8 +9,6 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.walletconnect.model.WcSession
import com.tangem.domain.walletconnect.model.WcSessionApprove
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
@ -20,9 +18,7 @@ import javax.inject.Inject
internal class WcNetworksConverter @Inject constructor(
private val namespaceConverters: Set<WcNamespaceConverter>,
private val walletManagersFacade: WalletManagersFacade,
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
fun createNetwork(chainId: String, wallet: UserWallet): Network? {
@ -101,12 +97,10 @@ internal class WcNetworksConverter @Inject constructor(
}
private suspend fun getWalletNetworks(userWalletId: UserWalletId): List<Network> {
return if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId),
).orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
}.filterIsInstance<CryptoCurrency.Coin>().map(CryptoCurrency.Coin::network)
return multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId),
)
.orEmpty()
.filterIsInstance<CryptoCurrency.Coin>().map(CryptoCurrency.Coin::network)
}
}

View file

@ -1,32 +1,24 @@
package com.tangem.domain.nft
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.wallets.repository.WalletsRepository
class DisableWalletNFTUseCase(
private val walletsRepository: WalletsRepository,
private val nftRepository: NFTRepository,
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(userWalletId: UserWalletId) {
walletsRepository.disableNFT(userWalletId)
val currencies = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCachedCurrenciesSync(userWalletId)
}
val currencies = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
val networks = currencies.map { it.network }
nftRepository.clearCache(userWalletId, networks)

View file

@ -1,28 +1,20 @@
package com.tangem.domain.nft
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.models.wallet.UserWalletId
class FetchNFTCollectionsUseCase(
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
private val nftRepository: NFTRepository,
) {
suspend operator fun invoke(userWalletId: UserWalletId) {
val currencies = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
}
val currencies = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
nftRepository.refreshCollections(userWalletId, currencies.map { it.network }.distinct())
}

View file

@ -1,29 +1,21 @@
package com.tangem.domain.nft
import arrow.core.Either
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.models.wallet.UserWalletId
class RefreshAllNFTUseCase(
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
private val nftRepository: NFTRepository,
) {
suspend operator fun invoke(userWalletId: UserWalletId): Either<Throwable, Unit> = Either.catch {
val currencies = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
}
val currencies = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
nftRepository.refreshAll(userWalletId, currencies.map { it.network }.distinct())
}

View file

@ -33,7 +33,6 @@ class AddCryptoCurrenciesUseCase(
private val singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val stakingIdFactory: StakingIdFactory,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
/**
@ -92,15 +91,11 @@ class AddCryptoCurrenciesUseCase(
): Either<Throwable, CryptoCurrency> = either {
val existingCurrencies = catch(
block = {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
.toList()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
}
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
.toList()
},
catch = ::raise,
)

View file

@ -18,7 +18,6 @@ import kotlinx.coroutines.withContext
class ApplyTokenListSortingUseCase(
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
private val dispatchers: CoroutineDispatcherProvider,
) {
@ -88,14 +87,10 @@ class ApplyTokenListSortingUseCase(
private suspend fun Raise<TokenListSortingError>.getCurrencies(userWalletId: UserWalletId): List<CryptoCurrency> {
val tokens = catch(
block = {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId, refresh = false)
}
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
},
catch = { raise(TokenListSortingError.DataError(it)) },
)

View file

@ -35,7 +35,6 @@ class FetchCurrencyStatusUseCase(
private val singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val stakingIdFactory: StakingIdFactory,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
/**
@ -97,15 +96,11 @@ class FetchCurrencyStatusUseCase(
): CryptoCurrency {
return catch(
block = {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.firstOrNull { it.id == id }
?: error("Unable to find currency with ID: $id")
} else {
currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId = userWalletId, id = id)
}
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.firstOrNull { it.id == id }
?: error("Unable to find currency with ID: $id")
},
) {
raise(CurrencyStatusError.DataError(it))

View file

@ -26,7 +26,6 @@ import java.math.BigDecimal
class GetBalanceNotEnoughForFeeWarningUseCase(
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
private val dispatchers: CoroutineDispatcherProvider,
) {
suspend operator fun invoke(
@ -71,14 +70,10 @@ class GetBalanceNotEnoughForFeeWarningUseCase(
tokenStatus: CryptoCurrencyStatus,
feePaidToken: FeePaidCurrency.Token,
): CryptoCurrencyWarning {
val tokens = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
}
val tokens = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
val token = tokens.find {
it is CryptoCurrency.Token &&

View file

@ -5,16 +5,15 @@ import arrow.core.raise.Raise
import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.repository.CurrenciesRepository
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.error.CurrencyStatusError
import com.tangem.domain.tokens.repository.CurrenciesRepository
class GetCryptoCurrencyUseCase(
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
/**
@ -55,15 +54,11 @@ class GetCryptoCurrencyUseCase(
): CryptoCurrency {
return catch(
block = {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.firstOrNull { it.id.value == id }
?: error("Unable to find currency with ID: $id")
} else {
currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, id)
}
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.firstOrNull { it.id.value == id }
?: error("Unable to find currency with ID: $id")
},
catch = { raise(CurrencyStatusError.DataError(it)) },
)

View file

@ -29,7 +29,6 @@ class GetCurrencyWarningsUseCase(
private val currencyChecksRepository: CurrencyChecksRepository,
private val currencyStatusOperations: BaseCurrencyStatusOperations,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(
@ -152,14 +151,10 @@ class GetCurrencyWarningsUseCase(
tokenStatus: CryptoCurrencyStatus,
feePaidToken: FeePaidCurrency.Token,
): CryptoCurrencyWarning {
val tokens = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
}
val tokens = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
val token = tokens.find {
it is CryptoCurrency.Token &&

View file

@ -1,27 +1,17 @@
package com.tangem.domain.tokens
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.models.wallet.UserWalletId
class IsCryptoCurrencyCoinCouldHideUseCase(
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(userWalletId: UserWalletId, cryptoCurrencyCoin: CryptoCurrency.Coin): Boolean {
return if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(
userWalletId = userWalletId,
refresh = false,
)
}
return multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
.none { it is CryptoCurrency.Token && it.network == cryptoCurrencyCoin.network }
}
}

View file

@ -5,19 +5,16 @@ import arrow.core.getOrElse
import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.tokens.error.QuotesError
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.models.wallet.UserWalletId
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
class RefreshMultiCurrencyWalletQuotesUseCase(
private val currenciesRepository: CurrenciesRepository,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(userWalletId: UserWalletId): Either<QuotesError, Unit> {
@ -41,15 +38,11 @@ class RefreshMultiCurrencyWalletQuotesUseCase(
return either {
catch(
block = {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
.toList()
} else {
currenciesRepository.getMultiCurrencyWalletCachedCurrenciesSync(userWalletId)
}
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
.toList()
},
catch = ::raise,
)

View file

@ -4,16 +4,15 @@ import arrow.core.Either
import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.tokens.model.remove.RemoveCurrencyError
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.models.wallet.UserWalletId
class RemoveCurrencyUseCase(
private val currenciesRepository: CurrenciesRepository,
private val walletManagersFacade: WalletManagersFacade,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(
@ -46,17 +45,10 @@ class RemoveCurrencyUseCase(
suspend fun hasLinkedTokens(userWalletId: UserWalletId, currency: CryptoCurrency): Boolean {
return when (currency) {
is CryptoCurrency.Coin -> {
val walletCurrencies = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(
userWalletId = userWalletId,
refresh = false,
)
}
val walletCurrencies = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
walletCurrencies.any { it is CryptoCurrency.Token && it.network == currency.network }
}

View file

@ -5,7 +5,4 @@ package com.tangem.domain.tokens
*
[REDACTED_AUTHOR]
*/
interface TokensFeatureToggles {
val isWalletBalanceFetcherEnabled: Boolean
}
interface TokensFeatureToggles

View file

@ -28,7 +28,6 @@ import com.tangem.domain.staking.single.SingleYieldBalanceProducer
import com.tangem.domain.staking.single.SingleYieldBalanceSupplier
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error
import com.tangem.domain.tokens.repository.CurrenciesRepository
@ -53,7 +52,6 @@ abstract class BaseCurrencyStatusOperations(
private val multiYieldBalanceSupplier: MultiYieldBalanceSupplier,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val stakingIdFactory: StakingIdFactory,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
protected val currencyStatusProxyCreator = CurrencyStatusProxyCreator()
@ -62,13 +60,6 @@ abstract class BaseCurrencyStatusOperations(
protected abstract fun getQuotes(id: CryptoCurrency.RawID): Flow<Either<Error, Set<QuoteStatus>>>
protected abstract suspend fun fetchComponents(
userWalletId: UserWalletId,
networks: Set<Network>,
currenciesIds: Set<CryptoCurrency.ID>,
currencies: List<CryptoCurrency>,
): Either<Throwable, Unit>
suspend fun getCurrencyStatusFlow(
userWalletId: UserWalletId,
currencyId: CryptoCurrency.ID,
@ -262,14 +253,10 @@ abstract class BaseCurrencyStatusOperations(
return either {
catch(
block = {
val nonEmptyCurrencies = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.toNonEmptyListOrNull()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId).toNonEmptyListOrNull()
}
val nonEmptyCurrencies = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.toNonEmptyListOrNull()
?: return emptyList<CryptoCurrencyStatus>().right()
val (_, currenciesIds) = getIds(nonEmptyCurrencies)
@ -332,15 +319,11 @@ abstract class BaseCurrencyStatusOperations(
currencyId: CryptoCurrency.ID,
): CryptoCurrency {
return Either.catch {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.firstOrNull { it.id == currencyId }
?: error("Unable to find currency with ID: $currencyId")
} else {
currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId = userWalletId, id = currencyId)
}
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.firstOrNull { it.id == currencyId }
?: error("Unable to find currency with ID: $currencyId")
}
.mapLeft(Error::DataError)
.bind()
@ -382,16 +365,12 @@ abstract class BaseCurrencyStatusOperations(
derivationPath: Network.DerivationPath,
): CryptoCurrency {
return Either.catch {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.filterIsInstance<CryptoCurrency.Coin>()
?.firstOrNull { it.network.id == networkId }
?: error("Unable to create network coin with ID: $networkId")
} else {
currenciesRepository.getNetworkCoin(userWalletId, networkId, derivationPath)
}
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.filterIsInstance<CryptoCurrency.Coin>()
?.firstOrNull { it.network.id == networkId && it.network.derivationPath == derivationPath }
?: error("Unable to create network coin with ID: $networkId")
}
.mapLeft { Error.DataError(it) }
.bind()

View file

@ -1,7 +1,6 @@
package com.tangem.domain.tokens.operations
import arrow.core.*
import arrow.core.raise.either
import arrow.core.raise.recover
import com.tangem.domain.core.lce.Lce
import com.tangem.domain.core.lce.LceFlow
@ -18,31 +17,27 @@ import com.tangem.domain.models.quote.QuoteStatus
import com.tangem.domain.models.staking.StakingID
import com.tangem.domain.models.staking.YieldBalance
import com.tangem.domain.models.wallet.UserWalletId
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.SingleNetworkStatusProducer
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.quotes.QuotesRepository
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
import com.tangem.domain.staking.StakingIdFactory
import com.tangem.domain.staking.model.StakingIntegrationID
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.multi.MultiYieldBalanceSupplier
import com.tangem.domain.staking.single.SingleYieldBalanceProducer
import com.tangem.domain.staking.single.SingleYieldBalanceSupplier
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.utils.extractAddress
import com.tangem.utils.extensions.addOrReplace
import com.tangem.utils.extensions.isSingleItem
import kotlinx.coroutines.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
@Suppress("LongParameterList", "LargeClass")
class CachedCurrenciesStatusesOperations(
@ -50,16 +45,11 @@ class CachedCurrenciesStatusesOperations(
quotesRepository: QuotesRepository,
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
private val singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
private val singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
multiYieldBalanceSupplier: MultiYieldBalanceSupplier,
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val stakingIdFactory: StakingIdFactory,
private val tokensFeatureToggles: TokensFeatureToggles,
) : BaseCurrencyStatusOperations(
currenciesRepository = currenciesRepository,
quotesRepository = quotesRepository,
@ -70,7 +60,6 @@ class CachedCurrenciesStatusesOperations(
multiYieldBalanceSupplier = multiYieldBalanceSupplier,
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
stakingIdFactory = stakingIdFactory,
tokensFeatureToggles = tokensFeatureToggles,
) {
override fun getCurrenciesStatuses(
@ -90,20 +79,6 @@ class CachedCurrenciesStatusesOperations(
): LceFlow<TokenListError, List<CryptoCurrencyStatus>> = lceFlow {
val prevStatuses = MutableStateFlow(value = emptyList<CryptoCurrencyStatus>())
val nonEmptyCurrencies = currenciesFlow.mapNotNull { it.getOrNull() }.firstOrNull()?.toNonEmptyListOrNull()
if (!tokensFeatureToggles.isWalletBalanceFetcherEnabled && !isFetchingStarted(userWalletId) &&
nonEmptyCurrencies != null
) {
launch {
setFetchStarted(userWalletId)
val (networks, currenciesIds) = getIds(nonEmptyCurrencies)
fetchComponents(userWalletId, networks, currenciesIds, nonEmptyCurrencies)
}
.invokeOnCompletion { setFetchFinished(userWalletId) }
}
currenciesFlow.flatMapLatest { maybeCurrencies ->
val currencies = maybeCurrencies
.getOrElse { return@flatMapLatest flowOf(it.lceError()) }
@ -154,15 +129,6 @@ class CachedCurrenciesStatusesOperations(
)
}
if (!tokensFeatureToggles.isWalletBalanceFetcherEnabled && !isFetchingStarted(userWalletId)) {
launch {
setFetchStarted(userWalletId)
fetchComponents(userWalletId, networks, currenciesIds, currencies)
}
.invokeOnCompletion { setFetchFinished(userWalletId) }
}
val networksStatusesUpdates = getNetworkStatusesUpdates(userWalletId, networks)
combine(
@ -183,11 +149,7 @@ class CachedCurrenciesStatusesOperations(
getYieldsBalancesUpdates(userWalletId, currenciesAddresses)
},
flow4 = fetchingState.map {
val state = it[userWalletId] ?: return@map false
!state.isFinished()
},
flow4 = flowOf(value = false),
transform = ::createCurrenciesStatuses,
)
.distinctUntilChanged()
@ -200,55 +162,6 @@ class CachedCurrenciesStatusesOperations(
.launchIn(scope = this)
}
override suspend fun fetchComponents(
userWalletId: UserWalletId,
networks: Set<Network>,
currenciesIds: Set<CryptoCurrency.ID>,
currencies: List<CryptoCurrency>,
): Either<Throwable, Unit> = either {
coroutineScope {
awaitAll(
async {
if (networks.isSingleItem()) {
singleNetworkStatusFetcher(
params = SingleNetworkStatusFetcher.Params(
userWalletId = userWalletId,
network = networks.first(),
),
)
} else {
multiNetworkStatusFetcher(
params = MultiNetworkStatusFetcher.Params(
userWalletId = userWalletId,
networks = networks,
),
)
}
},
async {
val rawCurrenciesIds = currenciesIds.mapNotNullTo(mutableSetOf()) { it.rawCurrencyId }
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(currenciesIds = rawCurrenciesIds, appCurrencyId = null),
)
},
async {
val stakingIds = currencies.mapNotNullTo(hashSetOf()) {
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it).getOrNull()
}
multiYieldBalanceFetcher(
params = MultiYieldBalanceFetcher.Params(
userWalletId = userWalletId,
stakingIds = stakingIds,
),
)
},
)
}
.map { }
}
private fun createCurrenciesStatuses(
currencies: NonEmptyList<CryptoCurrency>,
maybeQuotes: Either<TokenListError, Set<QuoteStatus>>?,
@ -428,36 +341,4 @@ class CachedCurrenciesStatusesOperations(
}
.distinctUntilChanged()
}
private fun isFetchingStarted(userWalletId: UserWalletId): Boolean {
return fetchingState.value[userWalletId]?.let { it.isStarted() || it.isFinished() } == true
}
private fun setFetchStarted(userWalletId: UserWalletId) {
fetchingState.update {
it.toMutableMap().apply {
put(key = userWalletId, value = FetchingState.STARTED)
}
}
}
private fun setFetchFinished(userWalletId: UserWalletId) {
fetchingState.update {
it.toMutableMap().apply {
put(key = userWalletId, value = FetchingState.FINISHED)
}
}
}
enum class FetchingState {
STARTED, FINISHED;
fun isStarted() = this == STARTED
fun isFinished() = this == FINISHED
}
companion object {
private val fetchingState = MutableStateFlow(value = emptyMap<UserWalletId, FetchingState>())
}
}

View file

@ -188,7 +188,6 @@ internal class ApplyTokenListSortingUseCaseTest {
currenciesRepository = tokensRepository,
dispatchers = TestingCoroutineDispatcherProvider(),
multiWalletCryptoCurrenciesSupplier = mockk(),
tokensFeatureToggles = mockk(),
)
private fun getTokensRepository(

View file

@ -12,8 +12,6 @@ import com.tangem.domain.networks.single.SingleNetworkStatusProducer
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.transaction.error.AssociateAssetError
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.utils.isNullOrZero
@ -22,10 +20,8 @@ import kotlinx.coroutines.flow.firstOrNull
class AssociateAssetUseCase(
private val cardSdkConfigRepository: CardSdkConfigRepository,
private val walletManagersFacade: WalletManagersFacade,
private val currenciesRepository: CurrenciesRepository,
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(
@ -33,25 +29,19 @@ class AssociateAssetUseCase(
currency: CryptoCurrency,
): Either<AssociateAssetError, Unit> {
return either {
val networkCoin = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.firstOrNull {
val network = currency.network
it.network.id == network.id && it.network.derivationPath == network.derivationPath
}
?: error("Unable to create network coin for currencyID: ${currency.id}")
} else {
currenciesRepository.getNetworkCoin(
userWalletId = userWalletId,
networkId = currency.network.id,
derivationPath = currency.network.derivationPath,
)
}
val networkCoin = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.firstOrNull {
val network = currency.network
it.network.id == network.id && it.network.derivationPath == network.derivationPath
}
?: error("Unable to create network coin for currencyID: ${currency.id}")
if (isBalanceZero(userWalletId, networkCoin)) {
raise(AssociateAssetError.NotEnoughBalance(networkCoin))
}
val signer = cardSdkConfigRepository.getCommonSigner(
cardId = null,
twinKey = null, // use null here because no assets support for Twin cards

View file

@ -22,7 +22,10 @@ import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.tokens.*
import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.transaction.error.GetFeeError
import com.tangem.domain.transaction.usecase.CreateNFTTransferTransactionUseCase
import com.tangem.domain.transaction.usecase.GetFeeUseCase
@ -62,9 +65,7 @@ internal class NFTSendModel @Inject constructor(
private val router: Router,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val getCryptoCurrenciesUseCase: GetCryptoCurrenciesUseCase,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
private val createNFTTransferTransactionUseCase: CreateNFTTransferTransactionUseCase,
@ -178,16 +179,10 @@ internal class NFTSendModel @Inject constructor(
ifRight = { wallet ->
userWallet = wallet
cryptoCurrency = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.firstOrNull { it is CryptoCurrency.Coin && it.network == nftAsset.network }
} else {
getCryptoCurrenciesUseCase(userWalletId).getOrNull()
?.filterIsInstance<CryptoCurrency.Coin>()
?.firstOrNull { it.network == nftAsset.network }
}
cryptoCurrency = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
?.firstOrNull { it is CryptoCurrency.Coin && it.network == nftAsset.network }
?: return@launch
getCurrenciesStatusUpdates(
@ -244,7 +239,7 @@ internal class NFTSendModel @Inject constructor(
).getOrNull() ?: cryptoStatus
if (uiState.value.destinationUM is DestinationUM.Empty) {
router.replaceAll(CommonSendRoute.Destination(isEditMode = false))
router.replaceAll(Destination(isEditMode = false))
}
},
ifLeft = {

View file

@ -6,14 +6,12 @@ import com.tangem.common.routing.AppRouter
import com.tangem.common.routing.deeplink.DeeplinkConst.NETWORK_ID_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.TOKEN_ID_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.WALLET_ID_KEY
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.staking.GetStakingAvailabilityUseCase
import com.tangem.domain.staking.GetYieldUseCase
import com.tangem.domain.staking.model.StakingAvailability
import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.features.staking.api.deeplink.StakingDeepLinkHandler
import dagger.assisted.Assisted
@ -29,9 +27,7 @@ internal class DefaultStakingDeepLinkHandler @AssistedInject constructor(
@Assisted private val queryParams: Map<String, String>,
private val appRouter: AppRouter,
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
private val getCryptoCurrenciesUseCase: GetCryptoCurrenciesUseCase,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
private val getYieldUseCase: GetYieldUseCase,
private val getStakingAvailabilityUseCase: GetStakingAvailabilityUseCase,
) : StakingDeepLinkHandler {
@ -56,17 +52,10 @@ internal class DefaultStakingDeepLinkHandler @AssistedInject constructor(
}
scope.launch {
val cryptoCurrency = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(selectedUserWalletId),
)
.orEmpty()
} else {
getCryptoCurrenciesUseCase(userWalletId = selectedUserWalletId).getOrElse {
Timber.e("Error on getting crypto currency list")
return@launch
}
}
val cryptoCurrency = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(selectedUserWalletId),
)
.orEmpty()
.firstOrNull {
val isNetwork = it.network.backendId.equals(networkId, ignoreCase = true)
val isCurrency = it.id.rawCurrencyId?.value?.equals(tokenId, ignoreCase = true) == true

View file

@ -72,7 +72,6 @@ internal class SwapInteractorImpl @AssistedInject constructor(
private val appCurrencyRepository: AppCurrencyRepository,
private val currenciesRepository: CurrenciesRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
private val initialToCurrencyResolver: InitialToCurrencyResolver,
private val validateTransactionUseCase: ValidateTransactionUseCase,
private val estimateFeeUseCase: EstimateFeeUseCase,
@ -1761,14 +1760,10 @@ internal class SwapInteractorImpl @AssistedInject constructor(
if (feePaidCurrency.balance > fee.multiply(percentsToFeeIncrease)) {
SwapFeeState.Enough
} else {
val tokens = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
} else {
currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId)
}
val tokens = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
)
.orEmpty()
val token = tokens
.filterIsInstance<CryptoCurrency.Token>()

View file

@ -12,13 +12,15 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.notifications.models.NotificationType
import com.tangem.domain.tokens.*
import com.tangem.domain.tokens.wallet.WalletBalanceFetcher
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.isLocked
import com.tangem.domain.models.wallet.isMultiCurrency
import com.tangem.domain.notifications.models.NotificationType
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase
import com.tangem.domain.tokens.GetCryptoCurrencyUseCase
import com.tangem.domain.tokens.wallet.WalletBalanceFetcher
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.SelectWalletUseCase
import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnalyticEvents
@ -45,9 +47,7 @@ internal class DefaultTokenDetailsDeepLinkHandler @AssistedInject constructor(
private val walletDeepLinkActionTrigger: WalletDeepLinkActionTrigger,
private val analyticsEventHandler: AnalyticsEventHandler,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val tokensFeatureToggles: TokensFeatureToggles,
private val walletBalanceFetcher: WalletBalanceFetcher,
private val fetchCardTokenListUseCase: FetchCardTokenListUseCase,
) : TokenDetailsDeepLinkHandler {
init {
@ -119,24 +119,15 @@ internal class DefaultTokenDetailsDeepLinkHandler @AssistedInject constructor(
private suspend fun fetchCurrency(userWallet: UserWallet, cryptoCurrency: CryptoCurrency) {
val isMultiCurrency = userWallet.isMultiCurrency
// single-currency wallet with token (NODL)
val isSingleWalletWithToken = userWallet is UserWallet.Cold &&
userWallet is UserWallet.Cold &&
userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
when {
isMultiCurrency -> fetchCurrencyStatusUseCase.invoke(
userWalletId = userWallet.walletId,
id = cryptoCurrency.id,
)
!isMultiCurrency && tokensFeatureToggles.isWalletBalanceFetcherEnabled ->
walletBalanceFetcher(params = WalletBalanceFetcher.Params(userWalletId = userWallet.walletId))
// remove below after delete tokensFeatureToggles.isWalletBalanceFetcherEnabled
!isMultiCurrency && userWallet is UserWallet.Cold && isSingleWalletWithToken ->
fetchCardTokenListUseCase.invoke(
userWalletId = userWallet.walletId,
refresh = true,
)
!isMultiCurrency -> fetchCurrencyStatusUseCase.invoke(
userWalletId = userWallet.walletId,
refresh = true,
!isMultiCurrency -> walletBalanceFetcher(
params = WalletBalanceFetcher.Params(userWalletId = userWallet.walletId),
)
}
}

View file

@ -10,7 +10,6 @@ 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.card.common.util.cardTypesResolver
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.isLocked
@ -20,9 +19,7 @@ import com.tangem.domain.notifications.GetIsHuaweiDeviceWithoutGoogleServicesUse
import com.tangem.domain.notifications.repository.NotificationsRepository
import com.tangem.domain.notifications.toggles.NotificationsFeatureToggles
import com.tangem.domain.settings.*
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.wallets.usecase.*
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
@ -76,9 +73,7 @@ internal class WalletModel @Inject constructor(
private val tokenListStore: MultiWalletTokenListStore,
private val onrampStatusFactory: OnrampStatusFactory,
private val analyticsEventsHandler: AnalyticsEventHandler,
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
private val walletContentFetcher: WalletContentFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
private val observeAndClearNFTCacheIfNeedUseCase: ObserveAndClearNFTCacheIfNeedUseCase,
private val walletDeepLinkActionListener: WalletDeepLinkActionListener,
private val notificationsRepository: NotificationsRepository,
@ -406,13 +401,11 @@ internal class WalletModel @Inject constructor(
val otherWallets = action.wallets.minus(action.selectedWallet)
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
otherWallets
.filterNot(UserWallet::isLocked)
.onEach { userWallet ->
modelScope.launch { walletContentFetcher(userWalletId = userWallet.walletId) }
}
}
otherWallets
.filterNot(UserWallet::isLocked)
.onEach { userWallet ->
modelScope.launch { walletContentFetcher(userWalletId = userWallet.walletId) }
}
if (action.wallets.size > 1 && isWalletsScrollPreviewEnabled()) {
val direction = if (action.selectedWalletIndex == action.wallets.lastIndex) {
@ -570,27 +563,14 @@ internal class WalletModel @Inject constructor(
}
private suspend fun fetchWalletContent(userWallet: UserWallet) {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
if (userWallet.isLocked) return
if (userWallet.isLocked) return
/*
* Updating the balance of the current wallet is an essential part of InitializationWallets,
* so the coroutine is launched in the current context
*/
supervisorScope {
launch { walletContentFetcher(userWalletId = userWallet.walletId) }
}
} else {
fetchIfSingleWallet(userWallet = userWallet)
}
}
private fun fetchIfSingleWallet(userWallet: UserWallet) {
if (userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWallet()) {
modelScope.launch {
fetchCurrencyStatusUseCase(userWalletId = userWallet.walletId)
.onLeft { Timber.e(it.toString()) }
}
/*
* Updating the balance of the current wallet is an essential part of InitializationWallets,
* so the coroutine is launched in the current context
*/
supervisorScope {
launch { walletContentFetcher(userWalletId = userWallet.walletId) }
}
}

View file

@ -1,18 +1,10 @@
package com.tangem.feature.wallet.child.wallet.model.intents
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.extenstions.unwrap
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.isLocked
import com.tangem.domain.onramp.FetchHotCryptoUseCase
import com.tangem.domain.settings.NeverToShowWalletsScrollPreview
import com.tangem.domain.tokens.FetchCardTokenListUseCase
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.FetchTokenListUseCase
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.domain.wallets.usecase.SelectWalletUseCase
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
@ -23,7 +15,6 @@ import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContent
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetRefreshStateTransformer
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenListErrorTransformer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@ -43,12 +34,7 @@ internal class WalletClickIntents @Inject constructor(
private val walletScreenContentLoader: WalletScreenContentLoader,
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
private val selectWalletUseCase: SelectWalletUseCase,
private val fetchTokenListUseCase: FetchTokenListUseCase,
private val walletContentFetcher: WalletContentFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
private val fetchCardTokenListUseCase: FetchCardTokenListUseCase,
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val neverToShowWalletsScrollPreview: NeverToShowWalletsScrollPreview,
private val rampStateManager: RampStateManager,
private val fetchHotCryptoUseCase: FetchHotCryptoUseCase,
@ -88,7 +74,7 @@ internal class WalletClickIntents @Inject constructor(
stateHolder.update { it.copy(selectedWalletIndex = index) }
maybeUserWallet.onRight {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled && !it.isLocked) {
if (!it.isLocked) {
launch { walletContentFetcher(userWalletId = it.walletId) }
}
@ -131,28 +117,7 @@ internal class WalletClickIntents @Inject constructor(
)
modelScope.launch {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
walletContentFetcher(userWalletId = userWallet.walletId, forceUpdate = true)
} else {
val isSingleWalletWithToken = userWallet is UserWallet.Cold &&
userWallet.cardTypesResolver.isSingleWalletWithToken()
val maybeFetchResult = if (isSingleWalletWithToken) {
fetchCardTokenListUseCase(userWalletId = userWallet.walletId, refresh = true)
} else {
fetchTokenListUseCase(userWalletId = userWallet.walletId)
}
maybeFetchResult.onLeft {
stateHolder.update(
SetTokenListErrorTransformer(
selectedWallet = userWallet,
error = it,
appCurrency = getSelectedAppCurrencyUseCase.unwrap(),
),
)
}
}
walletContentFetcher(userWalletId = userWallet.walletId, forceUpdate = true)
buildList {
async { rampStateManager.fetchSellServiceData() }.let(::add)
@ -177,11 +142,7 @@ internal class WalletClickIntents @Inject constructor(
)
modelScope.launch {
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
walletContentFetcher(userWalletId = userWallet.walletId, forceUpdate = true)
} else {
fetchCurrencyStatusUseCase(userWallet.walletId, refresh = true)
}
walletContentFetcher(userWalletId = userWallet.walletId, forceUpdate = true)
onrampStatusFactory.updateOnrmapTransactionStatuses(userWallet)
walletScreenContentLoader.load(