Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-05 10:35:43 +04:00
parent eb96c3be40
commit def92569d3
13 changed files with 196 additions and 73 deletions

View file

@ -17,7 +17,7 @@ dependencies {
// region Project Domain
implementation(projects.domain.core)
implementation(projects.domain.account.status)
implementation(projects.domain.account)
implementation(projects.domain.models)
implementation(projects.domain.networks)
implementation(projects.domain.nft.models)

View file

@ -1,15 +1,16 @@
package com.tangem.domain.nft
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.nft.utils.NFTCleaner
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.wallets.repository.WalletsRepository
class DisableWalletNFTUseCase(
private val walletsRepository: WalletsRepository,
private val nftRepository: NFTRepository,
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val nftCleaner: NFTCleaner,
) {
suspend operator fun invoke(userWalletId: UserWalletId) {
@ -20,7 +21,7 @@ class DisableWalletNFTUseCase(
)
.orEmpty()
val networks = currencies.map { it.network }
nftRepository.clearCache(userWalletId, networks)
val networks = currencies.mapTo(destination = hashSetOf(), transform = CryptoCurrency::network)
nftCleaner(userWalletId, networks)
}
}

View file

@ -1,9 +1,8 @@
package com.tangem.domain.nft
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.AccountStatus
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.nft.models.NFTCollections
@ -16,7 +15,7 @@ import kotlinx.coroutines.flow.*
class GetNFTCollectionsUseCase(
private val currenciesRepository: CurrenciesRepository,
private val nftRepository: NFTRepository,
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
private val singleAccountListSupplier: SingleAccountListSupplier,
private val accountsFeatureToggles: AccountsFeatureToggles,
) {
@ -33,13 +32,17 @@ class GetNFTCollectionsUseCase(
}
}
@OptIn(ExperimentalCoroutinesApi::class)
fun invokeForAccounts(userWalletId: UserWalletId): Flow<WalletNFTCollections> {
fun AccountStatus.flowOfNFTCollections(): Flow<Pair<Account, List<NFTCollections>>> =
nftCollections(userWalletId, this.flattenCurrencies().map { it.currency })
.map { nfts -> this.account to nfts }
fun Account.flowOfNFTCollections(): Flow<Pair<Account, List<NFTCollections>>> {
val currencies = (this as? Account.CryptoPortfolio)?.cryptoCurrencies.orEmpty()
return singleAccountStatusListSupplier(userWalletId)
.mapLatest { statusList -> statusList.accountStatuses.map { it.flowOfNFTCollections() } }
return nftCollections(userWalletId = userWalletId, cryptoCurrencies = currencies.toList())
.map { nfts -> this to nfts }
}
return singleAccountListSupplier(userWalletId)
.mapLatest { statusList -> statusList.accounts.map { it.flowOfNFTCollections() } }
.flatMapLatest { flows -> combine(flows) { WalletNFTCollections(it.toMap()) } }
}

View file

@ -1,12 +1,14 @@
package com.tangem.domain.nft
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.models.PortfolioId
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.nft.models.NFTNetworks
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.tokens.repository.CurrenciesRepository
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
@ -14,19 +16,25 @@ import kotlinx.coroutines.flow.mapNotNull
class GetNFTNetworksUseCase(
private val currenciesRepository: CurrenciesRepository,
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
private val singleAccountListSupplier: SingleAccountListSupplier,
private val nftRepository: NFTRepository,
) {
@OptIn(ExperimentalCoroutinesApi::class)
operator fun invoke(portfolioId: PortfolioId): Flow<NFTNetworks> = when (portfolioId) {
is PortfolioId.Account -> singleAccountStatusListSupplier(portfolioId.userWalletId)
.map { it.accountStatuses }
.mapNotNull { accountStatuses -> accountStatuses.find { it.account.accountId == portfolioId.accountId } }
.map { accountStatus -> accountStatus.flattenCurrencies().map { it.currency } }
.mapLatest { it.toNFTNetworks(portfolioId.userWalletId) }
is PortfolioId.Wallet ->
is PortfolioId.Account -> {
singleAccountListSupplier(portfolioId.userWalletId)
.mapNotNull { accountList ->
val account = accountList.accounts.find { it.accountId == portfolioId.accountId }
(account as? Account.CryptoPortfolio)?.cryptoCurrencies?.toList()
}
.mapLatest { it.toNFTNetworks(portfolioId.userWalletId) }
}
is PortfolioId.Wallet -> {
currenciesRepository
.getWalletCurrenciesUpdates(portfolioId.userWalletId)
.map { cryptoCurrencies -> cryptoCurrencies.toNFTNetworks(portfolioId.userWalletId) }
}
}
private suspend fun List<CryptoCurrency>.toNFTNetworks(userWalletId: UserWalletId): NFTNetworks {

View file

@ -6,12 +6,12 @@ import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.nft.utils.NFTCleaner
import com.tangem.domain.tokens.repository.CurrenciesRepository
import kotlinx.coroutines.flow.*
class ObserveAndClearNFTCacheIfNeedUseCase(
private val nftRepository: NFTRepository,
private val nftCleaner: NFTCleaner,
private val currenciesRepository: CurrenciesRepository,
private val accountsFeatureToggles: AccountsFeatureToggles,
private val singleAccountListSupplier: SingleAccountListSupplier,
@ -26,7 +26,7 @@ class ObserveAndClearNFTCacheIfNeedUseCase(
.distinctUntilChanged()
.onEach { removedNetworks ->
if (removedNetworks.isNotEmpty()) {
nftRepository.clearCache(userWalletId, removedNetworks.toList())
nftCleaner(userWalletId, removedNetworks)
}
}

View file

@ -2,11 +2,11 @@ package com.tangem.domain.nft.repository
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.nft.models.NFTAsset
import com.tangem.domain.nft.models.NFTCollection
import com.tangem.domain.nft.models.NFTCollections
import com.tangem.domain.nft.models.NFTSalePrice
import com.tangem.domain.models.wallet.UserWalletId
import kotlinx.coroutines.flow.Flow
interface NFTRepository {
@ -32,6 +32,4 @@ interface NFTRepository {
suspend fun getNFTSupportedNetworks(userWalletId: UserWalletId): List<Network>
suspend fun getNFTExploreUrl(network: Network, assetIdentifier: NFTAsset.Identifier): String?
suspend fun clearCache(userWalletId: UserWalletId, networks: List<Network>)
}

View file

@ -0,0 +1,30 @@
package com.tangem.domain.nft.utils
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWalletId
/**
* Cleans up NFT data for a given user wallet and network(s).
*
[REDACTED_AUTHOR]
*/
interface NFTCleaner {
/**
* Cleans up NFT data for a given user wallet and single network.
*
* @param userWalletId the user wallet id
* @param network the network to clean up
*/
suspend operator fun invoke(userWalletId: UserWalletId, network: Network) {
invoke(userWalletId = userWalletId, networks = setOf(network))
}
/**
* Cleans up NFT data for a given user wallet and multiple networks.
*
* @param userWalletId the user wallet id
* @param networks the set of networks to clean up
*/
suspend operator fun invoke(userWalletId: UserWalletId, networks: Set<Network>)
}