Updated on 2026-08-14
This commit is contained in:
parent
dcaae36f60
commit
c6578aa652
27 changed files with 111 additions and 1782 deletions
|
|
@ -3,20 +3,11 @@ package com.tangem.tap.di.domain
|
|||
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.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.derivations.DerivationsRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
|
|
@ -57,40 +48,6 @@ internal object ManageTokensDomainModule {
|
|||
return CheckIsCurrencyNotAddedUseCase(customTokensRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRemoveCustomManagedCryptoCurrencyUseCase(
|
||||
customTokensRepository: CustomTokensRepository,
|
||||
): RemoveCustomManagedCryptoCurrencyUseCase {
|
||||
return RemoveCustomManagedCryptoCurrencyUseCase(customTokensRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSaveManagedTokensUseCase(
|
||||
customTokensRepository: CustomTokensRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
derivationsRepository: DerivationsRepository,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): SaveManagedTokensUseCase {
|
||||
return SaveManagedTokensUseCase(
|
||||
customTokensRepository = customTokensRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
currenciesRepository = currenciesRepository,
|
||||
derivationsRepository = derivationsRepository,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
multiStakingBalanceFetcher = multiStakingBalanceFetcher,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default),
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetSupportedNetworksUseCase(
|
||||
|
|
|
|||
|
|
@ -4,22 +4,12 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
|||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.markets.*
|
||||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.promo.PromoRepository
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.derivations.DerivationsRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
|
|
@ -66,32 +56,6 @@ object MarketsDomainModule {
|
|||
return GetCurrencyQuotesUseCase(singleQuoteStatusSupplier = singleQuoteStatusSupplier)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSaveMarketTokensUseCase(
|
||||
derivationsRepository: DerivationsRepository,
|
||||
marketsTokenRepository: MarketsTokenRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): SaveMarketTokensUseCase {
|
||||
return SaveMarketTokensUseCase(
|
||||
derivationsRepository = derivationsRepository,
|
||||
marketsTokenRepository = marketsTokenRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
currenciesRepository = currenciesRepository,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
multiStakingBalanceFetcher = multiStakingBalanceFetcher,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default),
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetTokenMarketCryptoCurrency(
|
||||
|
|
|
|||
|
|
@ -40,28 +40,6 @@ import javax.inject.Singleton
|
|||
@Suppress("TooManyFunctions", "LargeClass")
|
||||
internal object TokensDomainModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAddCryptoCurrenciesUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
singleStakingBalanceFetcher: SingleStakingBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
): AddCryptoCurrenciesUseCase {
|
||||
return AddCryptoCurrenciesUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
singleStakingBalanceFetcher = singleStakingBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideFetchPendingTransactionsUseCase(
|
||||
|
|
@ -88,20 +66,6 @@ internal object TokensDomainModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRemoveCurrencyUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
): RemoveCurrencyUseCase {
|
||||
return RemoveCurrencyUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetCurrencyUseCase(
|
||||
|
|
@ -177,20 +141,6 @@ internal object TokensDomainModule {
|
|||
return GetCryptoCurrencyUseCase(currenciesRepository, multiWalletCryptoCurrenciesSupplier)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideApplyTokenListSortingUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): ApplyTokenListSortingUseCase {
|
||||
return ApplyTokenListSortingUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetCryptoCurrencyActionsUseCase(
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import com.tangem.blockchainsdk.utils.toBlockchain
|
|||
import com.tangem.blockchainsdk.utils.toNetworkId
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
import com.tangem.data.common.currency.CryptoCurrencyFactory
|
||||
import com.tangem.data.common.currency.UserTokensResponseFactory
|
||||
import com.tangem.data.common.currency.UserTokensSaver
|
||||
import com.tangem.data.common.network.NetworkFactory
|
||||
import com.tangem.data.managetokens.utils.TokenAddressesConverter
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
|
|
@ -26,7 +24,6 @@ import com.tangem.domain.models.currency.CryptoCurrency
|
|||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
|
@ -35,10 +32,8 @@ internal class DefaultCustomTokensRepository(
|
|||
private val tangemTechApi: TangemTechApi,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val userTokensResponseStore: UserTokensResponseStore,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val userTokensSaver: UserTokensSaver,
|
||||
private val networkFactory: NetworkFactory,
|
||||
) : CustomTokensRepository {
|
||||
|
||||
|
|
@ -48,7 +43,6 @@ internal class DefaultCustomTokensRepository(
|
|||
)
|
||||
|
||||
private val cryptoCurrencyFactory = CryptoCurrencyFactory(excludedBlockchains)
|
||||
private val userTokensResponseFactory = UserTokensResponseFactory()
|
||||
private val tokenAddressConverter = TokenAddressesConverter()
|
||||
|
||||
override suspend fun validateContractAddress(contractAddress: String, networkId: Network.ID): Boolean =
|
||||
|
|
@ -213,41 +207,6 @@ internal class DefaultCustomTokensRepository(
|
|||
)
|
||||
}
|
||||
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
override suspend fun removeCurrency(userWalletId: UserWalletId, currency: ManagedCryptoCurrency.Custom) =
|
||||
withContext(dispatchers.io) {
|
||||
val cryptoCurrency = when (currency) {
|
||||
is ManagedCryptoCurrency.Custom.Coin -> createCoin(
|
||||
userWalletId = userWalletId,
|
||||
networkId = currency.network.id,
|
||||
derivationPath = currency.network.derivationPath,
|
||||
)
|
||||
is ManagedCryptoCurrency.Custom.Token -> cryptoCurrencyFactory.createToken(
|
||||
network = currency.network,
|
||||
rawId = currency.currencyId.rawCurrencyId,
|
||||
name = currency.name,
|
||||
symbol = currency.symbol,
|
||||
decimals = currency.decimals,
|
||||
contractAddress = currency.contractAddress,
|
||||
)
|
||||
}
|
||||
val storedCurrencies = userTokensResponseStore.getSyncOrNull(userWalletId)
|
||||
|
||||
requireNotNull(storedCurrencies) {
|
||||
"User tokens not found for user wallet [$userWalletId] while removing currency"
|
||||
}
|
||||
|
||||
val token = userTokensResponseFactory.createResponseToken(currency = cryptoCurrency, accountId = null)
|
||||
userTokensSaver.storeAndPush(
|
||||
userWalletId = userWalletId,
|
||||
response = storedCurrencies.copy(tokens = storedCurrencies.tokens.filterNot { it == token }),
|
||||
)
|
||||
when (cryptoCurrency) {
|
||||
is CryptoCurrency.Coin -> walletManagersFacade.remove(userWalletId, setOf(cryptoCurrency.network))
|
||||
is CryptoCurrency.Token -> walletManagersFacade.removeTokens(userWalletId, setOf(cryptoCurrency))
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun convertToCryptoCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
currency: ManagedCryptoCurrency.Custom,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
|||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.managetokens.repository.CustomTokensRepository
|
||||
import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -65,20 +64,16 @@ internal object ManageTokensDataModule {
|
|||
tangemTechApi: TangemTechApi,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
userTokensResponseStore: UserTokensResponseStore,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
userTokensSaver: UserTokensSaver,
|
||||
networkFactory: NetworkFactory,
|
||||
): CustomTokensRepository {
|
||||
return DefaultCustomTokensRepository(
|
||||
tangemTechApi = tangemTechApi,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
userTokensResponseStore = userTokensResponseStore,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
dispatchers = dispatchers,
|
||||
userTokensSaver = userTokensSaver,
|
||||
networkFactory = networkFactory,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ import com.tangem.domain.tokens.model.FeePaidCurrency
|
|||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.runSuspendCatching
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
|
|
@ -66,134 +65,6 @@ internal class DefaultCurrenciesRepository(
|
|||
userTokensSaver = userTokensSaver,
|
||||
)
|
||||
|
||||
override suspend fun saveTokens(
|
||||
userWalletId: UserWalletId,
|
||||
currencies: List<CryptoCurrency>,
|
||||
isGroupedByNetwork: Boolean,
|
||||
isSortedByBalance: Boolean,
|
||||
) = withContext(dispatchers.io) {
|
||||
ensureIsCorrectUserWallet(userWalletId, isMultiCurrencyWalletExpected = true)
|
||||
|
||||
val response = userTokensResponseFactory.createUserTokensResponse(
|
||||
currencies = currencies,
|
||||
isGroupedByNetwork = isGroupedByNetwork,
|
||||
isSortedByBalance = isSortedByBalance,
|
||||
)
|
||||
userTokensSaver.storeAndPush(userWalletId, response)
|
||||
}
|
||||
|
||||
override suspend fun addCurrenciesCache(
|
||||
userWalletId: UserWalletId,
|
||||
currencies: List<CryptoCurrency>,
|
||||
): List<CryptoCurrency> = withContext(dispatchers.io) {
|
||||
val savedCurrencies = requireNotNull(
|
||||
value = getSavedUserTokensResponseSync(key = userWalletId),
|
||||
lazyMessage = { "Saved tokens empty. Can not perform add currencies action" },
|
||||
)
|
||||
|
||||
val currenciesToAdd = filterAlreadyAddedCurrencies(
|
||||
savedCurrencies = savedCurrencies.tokens,
|
||||
currenciesToAdd = populateCurrenciesWithMissedCoins(currencies = currencies),
|
||||
)
|
||||
|
||||
val updatedResponse = savedCurrencies.copy(
|
||||
tokens = savedCurrencies.tokens + currenciesToAdd.map(userTokensResponseFactory::createResponseToken),
|
||||
)
|
||||
|
||||
userTokensSaver.store(
|
||||
userWalletId = userWalletId,
|
||||
response = updatedResponse,
|
||||
)
|
||||
|
||||
fetchExpressAssetsByNetworkIds(
|
||||
userWallet = userWalletsListRepository.getSyncStrict(id = userWalletId),
|
||||
userTokens = updatedResponse,
|
||||
)
|
||||
|
||||
currenciesToAdd
|
||||
}
|
||||
|
||||
private fun filterAlreadyAddedCurrencies(
|
||||
savedCurrencies: List<UserTokensResponse.Token>,
|
||||
currenciesToAdd: List<CryptoCurrency>,
|
||||
): List<CryptoCurrency> {
|
||||
return currenciesToAdd.filter { currency ->
|
||||
val networkId = currency.network.toBlockchain().toNetworkId()
|
||||
val contractAddress = (currency as? CryptoCurrency.Token)?.contractAddress
|
||||
|
||||
savedCurrencies.none { token ->
|
||||
token.contractAddress == contractAddress &&
|
||||
token.networkId == networkId &&
|
||||
token.derivationPath == currency.network.derivationPath.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun populateCurrenciesWithMissedCoins(currencies: List<CryptoCurrency>): List<CryptoCurrency> {
|
||||
val currenciesSequence = currencies.asSequence()
|
||||
|
||||
val networksWithTokens = currenciesSequence
|
||||
.filterIsInstance<CryptoCurrency.Token>()
|
||||
.map { it.network }
|
||||
.distinct()
|
||||
|
||||
val networksWithCoins = currenciesSequence
|
||||
.filterIsInstance<CryptoCurrency.Coin>()
|
||||
.map { it.network }
|
||||
.distinct()
|
||||
|
||||
val networksNeedingCoins = (networksWithTokens - networksWithCoins.toSet()).toMutableList()
|
||||
|
||||
if (networksNeedingCoins.isEmpty()) return currencies
|
||||
|
||||
return buildList {
|
||||
currencies.forEach { currency ->
|
||||
if (currency is CryptoCurrency.Token && currency.network in networksNeedingCoins) {
|
||||
val coin = cryptoCurrencyFactory.createCoin(currency.network)
|
||||
add(coin)
|
||||
|
||||
networksNeedingCoins.remove(currency.network)
|
||||
}
|
||||
|
||||
add(currency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency) =
|
||||
withContext(dispatchers.io) {
|
||||
val savedCurrencies = requireNotNull(
|
||||
value = getSavedUserTokensResponseSync(key = userWalletId),
|
||||
lazyMessage = { "Saved tokens empty. Can not perform remove currency action" },
|
||||
)
|
||||
|
||||
val token = userTokensResponseFactory.createResponseToken(currency)
|
||||
val updatedResponse =
|
||||
savedCurrencies.copy(tokens = savedCurrencies.tokens.filterNot { it == token })
|
||||
userTokensSaver.storeAndPush(
|
||||
userWalletId = userWalletId,
|
||||
response = updatedResponse,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun removeCurrencies(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||
return withContext(dispatchers.io) {
|
||||
val savedCurrencies = requireNotNull(
|
||||
value = getSavedUserTokensResponseSync(key = userWalletId),
|
||||
lazyMessage = { "Saved tokens empty. Can not perform remove currencies action" },
|
||||
)
|
||||
|
||||
val tokens = currencies.map(userTokensResponseFactory::createResponseToken)
|
||||
val updatedResponse = savedCurrencies.copy(
|
||||
tokens = savedCurrencies.tokens.filterNot(tokens::contains),
|
||||
)
|
||||
userTokensSaver.storeAndPush(
|
||||
userWalletId = userWalletId,
|
||||
response = updatedResponse,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getWalletCurrenciesUpdates(userWalletId: UserWalletId): Flow<List<CryptoCurrency>> {
|
||||
return channelFlow {
|
||||
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||
|
|
@ -577,19 +448,6 @@ internal class DefaultCurrenciesRepository(
|
|||
return blockchain?.isNetworkFeeZero() == true
|
||||
}
|
||||
|
||||
override suspend fun syncTokens(userWalletId: UserWalletId) {
|
||||
runSuspendCatching {
|
||||
val savedCurrencies = requireNotNull(
|
||||
value = getSavedUserTokensResponseSync(key = userWalletId),
|
||||
lazyMessage = { "Saved tokens empty. Can not perform add currencies action" },
|
||||
)
|
||||
userTokensSaver.storeAndPush(
|
||||
userWalletId = userWalletId,
|
||||
response = savedCurrencies,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver? {
|
||||
return (userWalletsListRepository.getSyncStrict(userWalletId) as? UserWallet.Cold)?.cardTypesResolver
|
||||
}
|
||||
|
|
@ -712,12 +570,6 @@ internal class DefaultCurrenciesRepository(
|
|||
accountId = null,
|
||||
)
|
||||
|
||||
private fun ensureIsCorrectUserWallet(userWalletId: UserWalletId, isMultiCurrencyWalletExpected: Boolean) {
|
||||
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||
|
||||
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected)
|
||||
}
|
||||
|
||||
private fun ensureIsCorrectUserWallet(userWallet: UserWallet, isMultiCurrencyWalletExpected: Boolean) {
|
||||
val userWalletId = userWallet.walletId
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
package com.tangem.domain.managetokens
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
|
||||
import com.tangem.domain.managetokens.repository.CustomTokensRepository
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
class RemoveCustomManagedCryptoCurrencyUseCase(private val repository: CustomTokensRepository) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
customCurrency: ManagedCryptoCurrency.Custom,
|
||||
): Either<Throwable, Unit> {
|
||||
return Either.catch {
|
||||
repository.removeCurrency(userWalletId, customCurrency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
package com.tangem.domain.managetokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.flatten
|
||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
|
||||
import com.tangem.domain.managetokens.repository.CustomTokensRepository
|
||||
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.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.derivations.DerivationsRepository
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
@Suppress("LongParameterList")
|
||||
class SaveManagedTokensUseCase(
|
||||
private val customTokensRepository: CustomTokensRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val derivationsRepository: DerivationsRepository,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
private val parallelUpdatingScope: CoroutineScope,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
currenciesToAdd: Map<ManagedCryptoCurrency.Token, Set<Network>>,
|
||||
currenciesToRemove: Map<ManagedCryptoCurrency.Token, Set<Network>>,
|
||||
): Either<Throwable, Unit> = Either.catch {
|
||||
if (currenciesToRemove.isNotEmpty()) {
|
||||
val removingCurrencies = currenciesToRemove.mapToCryptoCurrencies(userWalletId)
|
||||
|
||||
currenciesRepository.removeCurrencies(userWalletId = userWalletId, currencies = removingCurrencies)
|
||||
|
||||
removeCurrenciesFromWalletManager(userWalletId = userWalletId, currencies = removingCurrencies)
|
||||
}
|
||||
|
||||
if (currenciesToAdd.isNotEmpty()) {
|
||||
derivationsRepository.derivePublicKeysByNetworks(
|
||||
userWalletId = userWalletId,
|
||||
networks = currenciesToAdd.values.flatten(),
|
||||
)
|
||||
|
||||
val addingCurrencies = currenciesToAdd.mapToCryptoCurrencies(userWalletId)
|
||||
|
||||
val savedCurrencies = currenciesRepository.addCurrenciesCache(
|
||||
userWalletId = userWalletId,
|
||||
currencies = addingCurrencies,
|
||||
)
|
||||
|
||||
parallelUpdatingScope.launch {
|
||||
withContext(NonCancellable) {
|
||||
syncTokens(userWalletId = userWalletId, addedCurrencies = savedCurrencies)
|
||||
|
||||
launch {
|
||||
refreshUpdatedNetworks(
|
||||
userWalletId = userWalletId,
|
||||
addedCurrencies = savedCurrencies,
|
||||
)
|
||||
}
|
||||
launch {
|
||||
refreshUpdatedStakingBalances(
|
||||
userWalletId = userWalletId,
|
||||
addedCurrencies = savedCurrencies,
|
||||
)
|
||||
}
|
||||
launch { refreshUpdatedQuotes(addedCurrencies = savedCurrencies) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun removeCurrenciesFromWalletManager(
|
||||
userWalletId: UserWalletId,
|
||||
currencies: List<CryptoCurrency>,
|
||||
) {
|
||||
walletManagersFacade.remove(
|
||||
userWalletId = userWalletId,
|
||||
networks = currencies
|
||||
.filterIsInstance<CryptoCurrency.Coin>()
|
||||
.mapTo(hashSetOf(), CryptoCurrency::network),
|
||||
)
|
||||
|
||||
walletManagersFacade.removeTokens(
|
||||
userWalletId = userWalletId,
|
||||
tokens = currencies.filterIsInstance<CryptoCurrency.Token>().toSet(),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun syncTokens(userWalletId: UserWalletId, addedCurrencies: List<CryptoCurrency>) {
|
||||
createWalletManagers(userWalletId = userWalletId, currencies = addedCurrencies)
|
||||
currenciesRepository.syncTokens(userWalletId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates wallet managers for the given [currencies] if they do not already exist.
|
||||
* The method will generate addresses for new networks to ensure the stability of the "Push notifications" feature.
|
||||
*
|
||||
* @param userWalletId The ID of the user's wallet.
|
||||
* @param currencies The list of cryptocurrencies for which to create wallet managers.
|
||||
*/
|
||||
private suspend fun createWalletManagers(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||
val networks = currencies.mapTo(hashSetOf(), CryptoCurrency::network)
|
||||
|
||||
for (network in networks) {
|
||||
walletManagersFacade.getOrCreateWalletManager(userWalletId = userWalletId, network = network)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedNetworks(userWalletId: UserWalletId, addedCurrencies: List<CryptoCurrency>) {
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = addedCurrencies.map(CryptoCurrency::network).toSet(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedStakingBalances(
|
||||
userWalletId: UserWalletId,
|
||||
addedCurrencies: List<CryptoCurrency>,
|
||||
) {
|
||||
val stakingIds = addedCurrencies.mapNotNullTo(hashSetOf()) {
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it).getOrNull()
|
||||
}
|
||||
|
||||
multiStakingBalanceFetcher(
|
||||
params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedQuotes(addedCurrencies: List<CryptoCurrency>) {
|
||||
multiQuoteStatusFetcher(
|
||||
params = MultiQuoteStatusFetcher.Params(
|
||||
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
|
||||
appCurrencyId = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun Map<ManagedCryptoCurrency.Token, Set<Network>>.mapToCryptoCurrencies(
|
||||
userWalletId: UserWalletId,
|
||||
): List<CryptoCurrency> {
|
||||
return flatMap { (token, networks) ->
|
||||
token.availableNetworks
|
||||
.filter { sourceNetwork -> networks.contains(sourceNetwork.network) }
|
||||
.map { sourceNetwork ->
|
||||
when (sourceNetwork) {
|
||||
is ManagedCryptoCurrency.SourceNetwork.Default -> customTokensRepository.createToken(
|
||||
managedCryptoCurrency = token,
|
||||
sourceNetwork = sourceNetwork,
|
||||
rawId = CryptoCurrency.RawID(token.id.value),
|
||||
)
|
||||
is ManagedCryptoCurrency.SourceNetwork.Main -> customTokensRepository.createCoin(
|
||||
userWalletId = userWalletId,
|
||||
networkId = sourceNetwork.id,
|
||||
derivationPath = sourceNetwork.network.derivationPath,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -43,9 +43,6 @@ interface CustomTokensRepository {
|
|||
formValues: AddCustomTokenForm.Validated.All,
|
||||
): CryptoCurrency.Token
|
||||
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
suspend fun removeCurrency(userWalletId: UserWalletId, currency: ManagedCryptoCurrency.Custom)
|
||||
|
||||
suspend fun convertToCryptoCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
currency: ManagedCryptoCurrency.Custom,
|
||||
|
|
|
|||
|
|
@ -1,145 +0,0 @@
|
|||
package com.tangem.domain.markets
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
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.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.derivations.DerivationsRepository
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* Use case for saving tokens from Markets
|
||||
*
|
||||
* @property derivationsRepository derivations repository
|
||||
* @property marketsTokenRepository markets token repository
|
||||
* @property currenciesRepository currencies repository
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
@Suppress("LongParameterList")
|
||||
class SaveMarketTokensUseCase(
|
||||
private val derivationsRepository: DerivationsRepository,
|
||||
private val marketsTokenRepository: MarketsTokenRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
private val parallelUpdatingScope: CoroutineScope,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
tokenMarketParams: TokenMarketParams,
|
||||
addedNetworks: Set<TokenMarketInfo.Network>,
|
||||
removedNetworks: Set<TokenMarketInfo.Network>,
|
||||
): Either<Throwable, Unit> = Either.catch {
|
||||
if (removedNetworks.isNotEmpty()) {
|
||||
val removedCurrencies = removedNetworks.mapNotNull { network ->
|
||||
marketsTokenRepository.createCryptoCurrency(
|
||||
userWalletId = userWalletId,
|
||||
token = tokenMarketParams,
|
||||
network = network,
|
||||
)
|
||||
}
|
||||
|
||||
currenciesRepository.removeCurrencies(userWalletId = userWalletId, currencies = removedCurrencies)
|
||||
}
|
||||
|
||||
if (addedNetworks.isNotEmpty()) {
|
||||
derivationsRepository.derivePublicKeysByNetworkIds(
|
||||
userWalletId = userWalletId,
|
||||
networkIds = addedNetworks.map { Network.RawID(it.networkId) },
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
|
||||
val addedCurrencies = addedNetworks.mapNotNull { network ->
|
||||
marketsTokenRepository.createCryptoCurrency(
|
||||
userWalletId = userWalletId,
|
||||
token = tokenMarketParams,
|
||||
network = network,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
}
|
||||
|
||||
val savedCurrencies = currenciesRepository.addCurrenciesCache(
|
||||
userWalletId = userWalletId,
|
||||
currencies = addedCurrencies,
|
||||
)
|
||||
|
||||
parallelUpdatingScope.launch {
|
||||
withContext(NonCancellable) {
|
||||
syncTokens(userWalletId, savedCurrencies)
|
||||
|
||||
launch { refreshUpdatedNetworks(userWalletId, savedCurrencies) }
|
||||
launch { refreshUpdatedStakingBalances(userWalletId, savedCurrencies) }
|
||||
launch { refreshUpdatedQuotes(savedCurrencies) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun syncTokens(userWalletId: UserWalletId, addedCurrencies: List<CryptoCurrency>) {
|
||||
createWalletManagers(userWalletId = userWalletId, currencies = addedCurrencies)
|
||||
currenciesRepository.syncTokens(userWalletId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates wallet managers for the given [currencies] if they do not already exist.
|
||||
* The method will generate addresses for new networks to ensure the stability of the "Push notifications" feature.
|
||||
*
|
||||
* @param userWalletId The ID of the user's wallet.
|
||||
* @param currencies The list of cryptocurrencies for which to create wallet managers.
|
||||
*/
|
||||
private suspend fun createWalletManagers(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||
val networks = currencies.mapTo(hashSetOf(), CryptoCurrency::network)
|
||||
|
||||
for (network in networks) {
|
||||
walletManagersFacade.getOrCreateWalletManager(userWalletId = userWalletId, network = network)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedNetworks(userWalletId: UserWalletId, addedCurrencies: List<CryptoCurrency>) {
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = addedCurrencies.map(CryptoCurrency::network).toSet(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedStakingBalances(
|
||||
userWalletId: UserWalletId,
|
||||
existingCurrencies: List<CryptoCurrency>,
|
||||
) {
|
||||
val stakingIds = existingCurrencies.mapNotNullTo(hashSetOf()) {
|
||||
stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it).getOrNull()
|
||||
}
|
||||
|
||||
multiStakingBalanceFetcher(
|
||||
params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedQuotes(addedCurrencies: List<CryptoCurrency>) {
|
||||
multiQuoteStatusFetcher(
|
||||
params = MultiQuoteStatusFetcher.Params(
|
||||
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
|
||||
appCurrencyId = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.getOrElse
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.right
|
||||
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.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.staking.StakingIdFactory
|
||||
import com.tangem.domain.staking.single.SingleStakingBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
|
||||
/**
|
||||
* A use case for adding multiple cryptocurrencies to a user's wallet.
|
||||
*
|
||||
* This use case interacts with the underlying repositories to both add currencies and refresh
|
||||
* network statuses, particularly after the addition of new tokens.
|
||||
*/
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
@Suppress("LongParameterList")
|
||||
class AddCryptoCurrenciesUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
private val singleStakingBalanceFetcher: SingleStakingBalanceFetcher,
|
||||
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
private val stakingIdFactory: StakingIdFactory,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Adds a [cryptoCurrency] token with specific [network] and derivation to the wallet identified by [userWalletId].
|
||||
*
|
||||
* After successfully adding a currency, it also refreshes the networks for tokens
|
||||
* that are being added and have corresponding coins in the existing currencies list.
|
||||
*
|
||||
* @param userWalletId The ID of the user's wallet.
|
||||
* @param cryptoCurrency Token to add.
|
||||
* @param network Network where we add
|
||||
* @return Either an [Throwable] or [Unit] indicating the success of the operation.
|
||||
*/
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency.Token,
|
||||
network: Network,
|
||||
): Either<Throwable, Unit> = either {
|
||||
val tokenToAdd = currenciesRepository.createTokenCurrency(cryptoCurrency = cryptoCurrency, network = network)
|
||||
invoke(userWalletId = userWalletId, currency = tokenToAdd)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a [currency] to the wallet identified by [userWalletId].
|
||||
*
|
||||
* After successfully adding a currency, it also refreshes the networks for tokens
|
||||
* that are being added and have corresponding coins in the existing currencies list.
|
||||
*
|
||||
* @param userWalletId The ID of the user's wallet.
|
||||
* @param currency Cryptocurrency to add.
|
||||
* @return Either an [Throwable] or [Unit] indicating the success of the operation.
|
||||
*/
|
||||
suspend operator fun invoke(userWalletId: UserWalletId, currency: CryptoCurrency): Either<Throwable, Unit> =
|
||||
either {
|
||||
val existingCurrencies = catch(
|
||||
block = { currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId) },
|
||||
catch = ::raise,
|
||||
)
|
||||
val currencyToAdd = currency.takeUnless(existingCurrencies::contains) ?: return@either
|
||||
|
||||
val addedCurrencies = addCurrencies(userWalletId, currencyToAdd)
|
||||
|
||||
coroutineScope {
|
||||
syncTokens(userWalletId, addedCurrencies)
|
||||
|
||||
awaitAll(
|
||||
async { refreshUpdatedNetworks(userWalletId, currencyToAdd, existingCurrencies) },
|
||||
async { refreshUpdatedStakingBalances(userWalletId, currencyToAdd) },
|
||||
async { refreshUpdatedQuotes(currencyToAdd) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
contractAddress: String,
|
||||
networkId: String,
|
||||
): Either<Throwable, CryptoCurrency> = either {
|
||||
val existingCurrencies = catch(
|
||||
block = {
|
||||
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
|
||||
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
|
||||
)
|
||||
.orEmpty()
|
||||
.toList()
|
||||
},
|
||||
catch = ::raise,
|
||||
)
|
||||
|
||||
val foundToken = existingCurrencies
|
||||
.filterIsInstance<CryptoCurrency.Token>()
|
||||
.firstOrNull { token ->
|
||||
token.network.backendId == networkId &&
|
||||
!token.isCustom &&
|
||||
token.contractAddress.equals(contractAddress, true)
|
||||
}
|
||||
if (foundToken != null) {
|
||||
return@either foundToken
|
||||
}
|
||||
val tokenToAdd = createTokenCurrency(userWalletId, contractAddress, networkId)
|
||||
val addedCurrencies = addCurrencies(userWalletId, tokenToAdd)
|
||||
|
||||
coroutineScope {
|
||||
syncTokens(userWalletId = userWalletId, addedCurrencies = addedCurrencies)
|
||||
|
||||
awaitAll(
|
||||
async { refreshUpdatedNetworks(userWalletId, tokenToAdd, existingCurrencies) },
|
||||
async { refreshUpdatedStakingBalances(userWalletId, tokenToAdd) },
|
||||
async { refreshUpdatedQuotes(tokenToAdd) },
|
||||
)
|
||||
}
|
||||
|
||||
tokenToAdd
|
||||
}
|
||||
|
||||
private suspend fun syncTokens(userWalletId: UserWalletId, addedCurrencies: List<CryptoCurrency>) {
|
||||
createWalletManagers(userWalletId = userWalletId, currencies = addedCurrencies)
|
||||
currenciesRepository.syncTokens(userWalletId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates wallet managers for the given [currencies] if they do not already exist.
|
||||
* The method will generate addresses for new networks to ensure the stability of the "Push notifications" feature.
|
||||
*
|
||||
* @param userWalletId The ID of the user's wallet.
|
||||
* @param currencies The list of cryptocurrencies for which to create wallet managers.
|
||||
*/
|
||||
private suspend fun createWalletManagers(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||
val networks = currencies.mapTo(hashSetOf(), CryptoCurrency::network)
|
||||
|
||||
for (network in networks) {
|
||||
walletManagersFacade.getOrCreateWalletManager(userWalletId = userWalletId, network = network)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the network statuses for tokens that have corresponding coins in the
|
||||
* [existingCurrencies] list.
|
||||
*/
|
||||
private suspend fun refreshUpdatedNetworks(
|
||||
userWalletId: UserWalletId,
|
||||
currencyToAdd: CryptoCurrency,
|
||||
existingCurrencies: List<CryptoCurrency>,
|
||||
) {
|
||||
val networksToUpdate = currencyToAdd.takeIf { currency ->
|
||||
currency is CryptoCurrency.Token && hasCoinForToken(existingCurrencies, currency)
|
||||
}
|
||||
?.network
|
||||
|
||||
val networkToUpdate = currencyToAdd.takeIf {
|
||||
!existingCurrencies.map(CryptoCurrency::network).contains(it.network)
|
||||
}
|
||||
?.network
|
||||
|
||||
multiNetworkStatusFetcher(
|
||||
MultiNetworkStatusFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
networks = setOfNotNull(networksToUpdate, networkToUpdate),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedStakingBalances(
|
||||
userWalletId: UserWalletId,
|
||||
addedCurrency: CryptoCurrency,
|
||||
): Either<Throwable, Unit> = either {
|
||||
val stakingId = stakingIdFactory.create(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = addedCurrency.id,
|
||||
network = addedCurrency.network,
|
||||
)
|
||||
.getOrElse { error ->
|
||||
when (error) {
|
||||
is StakingIdFactory.Error.UnableToGetAddress -> raise(IllegalStateException("$error"))
|
||||
StakingIdFactory.Error.UnsupportedCurrency -> Unit.right()
|
||||
}
|
||||
|
||||
return@either
|
||||
}
|
||||
|
||||
singleStakingBalanceFetcher(
|
||||
params = SingleStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingId = stakingId),
|
||||
)
|
||||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedQuotes(currencyToAdd: CryptoCurrency) {
|
||||
multiQuoteStatusFetcher(
|
||||
params = MultiQuoteStatusFetcher.Params(
|
||||
currenciesIds = setOfNotNull(currencyToAdd.id.rawCurrencyId),
|
||||
appCurrencyId = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun Raise<Throwable>.createTokenCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
contractAddress: String,
|
||||
networkId: String,
|
||||
): CryptoCurrency.Token {
|
||||
return catch(
|
||||
block = {
|
||||
currenciesRepository.createTokenCurrency(
|
||||
userWalletId = userWalletId,
|
||||
contractAddress = contractAddress,
|
||||
networkId = networkId,
|
||||
)
|
||||
},
|
||||
catch = {
|
||||
raise(it)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun Raise<Throwable>.addCurrencies(
|
||||
userWalletId: UserWalletId,
|
||||
currency: CryptoCurrency,
|
||||
): List<CryptoCurrency> {
|
||||
return catch(
|
||||
block = { currenciesRepository.addCurrenciesCache(userWalletId, listOf(currency)) },
|
||||
catch = ::raise,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the [existingCurrencies] list contains a coin that corresponds
|
||||
* to the given [token].
|
||||
*/
|
||||
private fun hasCoinForToken(existingCurrencies: List<CryptoCurrency>, token: CryptoCurrency.Token): Boolean {
|
||||
return existingCurrencies.any { currency ->
|
||||
currency is CryptoCurrency.Coin && currency.network == token.network
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.raise.ensureNotNull
|
||||
import arrow.core.toNonEmptyListOrNull
|
||||
import arrow.core.toNonEmptySetOrNull
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.error.TokenListSortingError
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Deprecated("Use ApplyAccountListSortingUseCase")
|
||||
class ApplyTokenListSortingUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
sortedTokensIds: List<CryptoCurrency.ID>,
|
||||
isGroupedByNetwork: Boolean,
|
||||
isSortedByBalance: Boolean,
|
||||
): Either<TokenListSortingError, Unit> {
|
||||
return either {
|
||||
val storedCurrencies = getCurrencies(userWalletId)
|
||||
val isSortingTypeChanged = checkIsCurrenciesSortedByBalance(userWalletId) != isSortedByBalance
|
||||
val isGroupingTypeChanged = checkIsCurrenciesGroupedByNetwork(userWalletId) != isGroupedByNetwork
|
||||
|
||||
val sortedCurrencies = sortTokens(sortedTokensIds, storedCurrencies)
|
||||
|
||||
if (storedCurrencies != sortedCurrencies || isSortingTypeChanged || isGroupingTypeChanged) {
|
||||
applySorting(
|
||||
userWalletId = userWalletId,
|
||||
currencies = sortedCurrencies,
|
||||
isGrouped = isGroupedByNetwork,
|
||||
isSortedByBalance = isSortedByBalance,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun Raise<TokenListSortingError>.checkIsCurrenciesSortedByBalance(userWalletId: UserWalletId) =
|
||||
catch(
|
||||
block = { currenciesRepository.isTokensSortedByBalance(userWalletId).firstOrNull() == true },
|
||||
catch = { raise(TokenListSortingError.DataError(it)) },
|
||||
)
|
||||
|
||||
private suspend fun Raise<TokenListSortingError>.checkIsCurrenciesGroupedByNetwork(userWalletId: UserWalletId) =
|
||||
catch(
|
||||
block = { currenciesRepository.isTokensGrouped(userWalletId).firstOrNull() == true },
|
||||
catch = { raise(TokenListSortingError.DataError(it)) },
|
||||
)
|
||||
|
||||
private suspend fun Raise<TokenListSortingError>.sortTokens(
|
||||
sortedCurrenciesIds: List<CryptoCurrency.ID>,
|
||||
unsortedCurrencies: List<CryptoCurrency>,
|
||||
): List<CryptoCurrency> = withContext(dispatchers.default) {
|
||||
val nonEmptySortedTokensIds = ensureNotNull(sortedCurrenciesIds.toNonEmptySetOrNull()) {
|
||||
TokenListSortingError.TokenListIsEmpty
|
||||
}
|
||||
|
||||
val sortedTokens = sortedMapOf<Int, CryptoCurrency>()
|
||||
|
||||
unsortedCurrencies.distinct().forEach { currency ->
|
||||
val index = nonEmptySortedTokensIds.indexOfFirst { currencyId ->
|
||||
currencyId == currency.id
|
||||
}
|
||||
|
||||
if (index >= 0) {
|
||||
sortedTokens[index] = currency
|
||||
} else {
|
||||
raise(TokenListSortingError.UnableToSortTokenList)
|
||||
}
|
||||
}
|
||||
|
||||
ensureNotNull(sortedTokens.values.toNonEmptyListOrNull()) {
|
||||
TokenListSortingError.TokenListIsEmpty
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun Raise<TokenListSortingError>.getCurrencies(userWalletId: UserWalletId): List<CryptoCurrency> {
|
||||
val tokens = catch(
|
||||
block = {
|
||||
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
|
||||
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
|
||||
)
|
||||
.orEmpty()
|
||||
},
|
||||
catch = { raise(TokenListSortingError.DataError(it)) },
|
||||
)
|
||||
|
||||
return ensureNotNull(tokens.toNonEmptyListOrNull()) {
|
||||
TokenListSortingError.TokenListIsEmpty
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun Raise<TokenListSortingError>.applySorting(
|
||||
userWalletId: UserWalletId,
|
||||
currencies: List<CryptoCurrency>,
|
||||
isGrouped: Boolean,
|
||||
isSortedByBalance: Boolean,
|
||||
) = withContext(dispatchers.io) {
|
||||
catch(
|
||||
block = { currenciesRepository.saveTokens(userWalletId, currencies, isGrouped, isSortedByBalance) },
|
||||
catch = { raise(TokenListSortingError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
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
|
||||
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
class RemoveCurrencyUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
) {
|
||||
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
currency: CryptoCurrency,
|
||||
): Either<RemoveCurrencyError, Unit> {
|
||||
return either {
|
||||
if (hasLinkedTokens(userWalletId, currency)) {
|
||||
raise(RemoveCurrencyError.HasLinkedTokens)
|
||||
}
|
||||
|
||||
catch(
|
||||
block = {
|
||||
currenciesRepository.removeCurrency(userWalletId, currency)
|
||||
|
||||
when (currency) {
|
||||
is CryptoCurrency.Coin -> {
|
||||
walletManagersFacade.remove(userWalletId, setOf(currency.network))
|
||||
}
|
||||
is CryptoCurrency.Token -> {
|
||||
walletManagersFacade.removeTokens(userWalletId, setOf(currency))
|
||||
}
|
||||
}
|
||||
},
|
||||
catch = { raise(RemoveCurrencyError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun hasLinkedTokens(userWalletId: UserWalletId, currency: CryptoCurrency): Boolean {
|
||||
return when (currency) {
|
||||
is CryptoCurrency.Coin -> {
|
||||
val walletCurrencies = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
|
||||
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
|
||||
)
|
||||
.orEmpty()
|
||||
|
||||
walletCurrencies.any { it is CryptoCurrency.Token && it.network == currency.network }
|
||||
}
|
||||
is CryptoCurrency.Token -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,58 +16,6 @@ import kotlinx.coroutines.flow.Flow
|
|||
@Suppress("TooManyFunctions")
|
||||
interface CurrenciesRepository {
|
||||
|
||||
/**
|
||||
* Saves the given list of cryptocurrencies, along with the preferences for grouping and sorting, for a specific
|
||||
* multi-currency user wallet.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param currencies The list of cryptocurrencies to be saved.
|
||||
* @param isGroupedByNetwork A boolean flag indicating whether the tokens should be grouped by network.
|
||||
* @param isSortedByBalance A boolean flag indicating whether the tokens should be sorted by balance.
|
||||
* @throws DataError.UserWalletError.WrongUserWallet If single-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
suspend fun saveTokens(
|
||||
userWalletId: UserWalletId,
|
||||
currencies: List<CryptoCurrency>,
|
||||
isGroupedByNetwork: Boolean,
|
||||
isSortedByBalance: Boolean,
|
||||
)
|
||||
|
||||
/**
|
||||
* Add currencies to a specific user wallet.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param currencies The currencies which must be added.
|
||||
* @throws DataError.UserWalletError.WrongUserWallet If single-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
suspend fun addCurrenciesCache(userWalletId: UserWalletId, currencies: List<CryptoCurrency>): List<CryptoCurrency>
|
||||
|
||||
/**
|
||||
* Removes currency from a specific user wallet.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param currency The currency which must be removed.
|
||||
* @throws DataError.UserWalletError.WrongUserWallet If multi-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency)
|
||||
|
||||
/**
|
||||
* Removes currencies from a specific user wallet.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param currencies The currencies which must be removed.
|
||||
* @throws DataError.UserWalletError.WrongUserWallet If single-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
@Deprecated("Use ManageCryptoCurrenciesUseCase")
|
||||
suspend fun removeCurrencies(userWalletId: UserWalletId, currencies: List<CryptoCurrency>)
|
||||
|
||||
/**
|
||||
* Retrieves the list of cryptocurrencies within a user wallet.
|
||||
*
|
||||
|
|
@ -211,18 +159,6 @@ interface CurrenciesRepository {
|
|||
|
||||
fun isNetworkFeeZero(userWalletId: UserWalletId, network: Network): Boolean
|
||||
|
||||
/**
|
||||
* Synchronizes local tokens with remote data for a specific user wallet.
|
||||
* This method ensures that the local token list matches the remote state by fetching
|
||||
* the token data from the local cache and push it to backend.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet to sync tokens for.
|
||||
* @throws Exception if the sync request to the backend fails
|
||||
*/
|
||||
@Deprecated("Use AccountsCRUDRepository instead")
|
||||
@Throws
|
||||
suspend fun syncTokens(userWalletId: UserWalletId)
|
||||
|
||||
@Throws
|
||||
fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver?
|
||||
}
|
||||
|
|
@ -1,207 +0,0 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.error.TokenListSortingError
|
||||
import com.tangem.domain.tokens.mock.MockTokens
|
||||
import com.tangem.domain.tokens.repository.MockCurrenciesRepository
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.mockk
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
import kotlin.random.Random
|
||||
|
||||
internal class ApplyTokenListSortingUseCaseTest {
|
||||
|
||||
private val userWalletId = UserWalletId(value = null)
|
||||
|
||||
@Test
|
||||
fun `when tokens are empty then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokenListSortingError.TokenListIsEmpty.left()
|
||||
|
||||
val useCase = getUseCase()
|
||||
|
||||
// When
|
||||
val result = useCase(
|
||||
userWalletId = userWalletId,
|
||||
sortedTokensIds = emptyList(),
|
||||
isGroupedByNetwork = false,
|
||||
isSortedByBalance = false,
|
||||
)
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when tokens saving failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokenListSortingError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
|
||||
val repository = getTokensRepository(
|
||||
sortTokensResult = DataError.NetworkError.NoInternetConnection.left(),
|
||||
)
|
||||
val useCase = getUseCase(repository)
|
||||
|
||||
// When
|
||||
val result = useCase(
|
||||
userWalletId = userWalletId,
|
||||
sortedTokensIds = MockTokens.tokens.map { it.id }.sortedByDescending { it.value },
|
||||
isGroupedByNetwork = false,
|
||||
isSortedByBalance = false,
|
||||
)
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when apply sorting for sorted and grouped list then correct args should be used`() = runTest {
|
||||
// Given
|
||||
val expectedTokens = getSortedTokens()
|
||||
val expectedIsGrouped = true
|
||||
val expectedIsSorted = true
|
||||
|
||||
val repository = getTokensRepository()
|
||||
val useCase = getUseCase(repository)
|
||||
|
||||
// When
|
||||
useCase(
|
||||
userWalletId = userWalletId,
|
||||
sortedTokensIds = expectedTokens.map { it.id },
|
||||
isGroupedByNetwork = expectedIsGrouped,
|
||||
isSortedByBalance = expectedIsSorted,
|
||||
)
|
||||
|
||||
// Then
|
||||
assertEquals(expectedTokens, repository.tokensIdsAfterSortingApply)
|
||||
assertEquals(expectedIsGrouped, repository.isTokensGroupedAfterSortingApply)
|
||||
assertEquals(expectedIsSorted, repository.isTokensSortedByBalanceAfterSortingApply)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when apply sorting for unsorted and grouped list then correct args should be used`() = runTest {
|
||||
// Given
|
||||
val expectedTokens = getSortedTokens()
|
||||
val expectedIsGrouped = true
|
||||
val expectedIsSorted = false
|
||||
|
||||
val repository = getTokensRepository()
|
||||
val useCase = getUseCase(repository)
|
||||
|
||||
// When
|
||||
useCase(
|
||||
userWalletId = userWalletId,
|
||||
sortedTokensIds = expectedTokens.map { it.id },
|
||||
isGroupedByNetwork = expectedIsGrouped,
|
||||
isSortedByBalance = expectedIsSorted,
|
||||
)
|
||||
|
||||
// Then
|
||||
assertEquals(expectedTokens, repository.tokensIdsAfterSortingApply)
|
||||
assertEquals(expectedIsGrouped, repository.isTokensGroupedAfterSortingApply)
|
||||
assertEquals(expectedIsSorted, repository.isTokensSortedByBalanceAfterSortingApply)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when apply sorting for sorted and ungrouped list then correct args should be used`() = runTest {
|
||||
// Given
|
||||
val expectedTokens = getSortedTokens()
|
||||
val expectedIsGrouped = false
|
||||
val expectedIsSorted = true
|
||||
|
||||
val repository = getTokensRepository()
|
||||
val useCase = getUseCase(repository)
|
||||
|
||||
// When
|
||||
useCase(
|
||||
userWalletId = userWalletId,
|
||||
sortedTokensIds = expectedTokens.map { it.id },
|
||||
isGroupedByNetwork = expectedIsGrouped,
|
||||
isSortedByBalance = expectedIsSorted,
|
||||
)
|
||||
|
||||
// Then
|
||||
assertEquals(expectedTokens, repository.tokensIdsAfterSortingApply)
|
||||
assertEquals(expectedIsGrouped, repository.isTokensGroupedAfterSortingApply)
|
||||
assertEquals(expectedIsSorted, repository.isTokensSortedByBalanceAfterSortingApply)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when apply sorting for unsorted and ungrouped list then correct args should be used`() = runTest {
|
||||
// Given
|
||||
val expectedTokens = getSortedTokens()
|
||||
val expectedIsGrouped = false
|
||||
val expectedIsSorted = false
|
||||
|
||||
val repository = getTokensRepository()
|
||||
val useCase = getUseCase(repository)
|
||||
|
||||
// When
|
||||
useCase(
|
||||
userWalletId = userWalletId,
|
||||
sortedTokensIds = expectedTokens.map { it.id },
|
||||
isGroupedByNetwork = expectedIsGrouped,
|
||||
isSortedByBalance = expectedIsSorted,
|
||||
)
|
||||
|
||||
// Then
|
||||
assertEquals(expectedTokens, repository.tokensIdsAfterSortingApply)
|
||||
assertEquals(expectedIsGrouped, repository.isTokensGroupedAfterSortingApply)
|
||||
assertEquals(expectedIsSorted, repository.isTokensSortedByBalanceAfterSortingApply)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when sorted tokens IDs do not contain all tokens IDs then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokenListSortingError.UnableToSortTokenList.left()
|
||||
|
||||
val repository = getTokensRepository()
|
||||
val useCase = getUseCase(repository)
|
||||
|
||||
// When
|
||||
val result = useCase(
|
||||
userWalletId = userWalletId,
|
||||
sortedTokensIds = getSortedTokens().drop(n = 3).map { it.id },
|
||||
isGroupedByNetwork = false,
|
||||
isSortedByBalance = false,
|
||||
)
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
private fun getSortedTokens() = MockTokens.tokens
|
||||
.sortedBy { Random.nextInt(0, MockTokens.tokens.size) }
|
||||
|
||||
private fun getUseCase(tokensRepository: MockCurrenciesRepository = getTokensRepository()) =
|
||||
ApplyTokenListSortingUseCase(
|
||||
currenciesRepository = tokensRepository,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
multiWalletCryptoCurrenciesSupplier = mockk(),
|
||||
)
|
||||
|
||||
private fun getTokensRepository(
|
||||
sortTokensResult: Either<DataError, Unit> = Unit.right(),
|
||||
removeCurrencyResult: Either<DataError, Unit> = Unit.right(),
|
||||
tokens: Flow<Either<DataError, List<CryptoCurrency>>> = flowOf(MockTokens.tokens.right()),
|
||||
): MockCurrenciesRepository {
|
||||
return MockCurrenciesRepository(
|
||||
sortTokensResult = sortTokensResult,
|
||||
removeCurrencyResult = removeCurrencyResult,
|
||||
token = MockTokens.token1.right(),
|
||||
tokens = tokens,
|
||||
isGrouped = emptyFlow(),
|
||||
isSortedByBalance = emptyFlow(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
package com.tangem.domain.tokens.repository
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.domain.card.CardTypesResolver
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.model.FeePaidCurrency
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
internal class MockCurrenciesRepository(
|
||||
private val sortTokensResult: Either<DataError, Unit>,
|
||||
private val removeCurrencyResult: Either<DataError, Unit>,
|
||||
private val token: Either<DataError, CryptoCurrency>,
|
||||
private val tokens: Flow<Either<DataError, List<CryptoCurrency>>>,
|
||||
private val isGrouped: Flow<Either<DataError, Boolean>>,
|
||||
private val isSortedByBalance: Flow<Either<DataError, Boolean>>,
|
||||
) : CurrenciesRepository {
|
||||
|
||||
var tokensIdsAfterSortingApply: List<CryptoCurrency>? = null
|
||||
private set
|
||||
|
||||
var isTokensGroupedAfterSortingApply: Boolean? = null
|
||||
private set
|
||||
|
||||
var isTokensSortedByBalanceAfterSortingApply: Boolean? = null
|
||||
private set
|
||||
|
||||
override suspend fun saveTokens(
|
||||
userWalletId: UserWalletId,
|
||||
currencies: List<CryptoCurrency>,
|
||||
isGroupedByNetwork: Boolean,
|
||||
isSortedByBalance: Boolean,
|
||||
) {
|
||||
sortTokensResult.onLeft { throw it }
|
||||
|
||||
tokensIdsAfterSortingApply = currencies
|
||||
isTokensGroupedAfterSortingApply = isGroupedByNetwork
|
||||
isTokensSortedByBalanceAfterSortingApply = isSortedByBalance
|
||||
}
|
||||
|
||||
override suspend fun addCurrenciesCache(
|
||||
userWalletId: UserWalletId,
|
||||
currencies: List<CryptoCurrency>,
|
||||
): List<CryptoCurrency> = emptyList()
|
||||
|
||||
override suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency) {
|
||||
removeCurrencyResult.onLeft { throw it }
|
||||
}
|
||||
|
||||
override suspend fun removeCurrencies(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) = Unit
|
||||
|
||||
override fun getWalletCurrenciesUpdates(userWalletId: UserWalletId): Flow<List<CryptoCurrency>> {
|
||||
return emptyFlow()
|
||||
}
|
||||
|
||||
override suspend fun getMultiCurrencyWalletCurrenciesSync(
|
||||
userWalletId: UserWalletId,
|
||||
refresh: Boolean,
|
||||
): List<CryptoCurrency> {
|
||||
return tokens.first().getOrElse { e -> throw e }
|
||||
}
|
||||
|
||||
override suspend fun getSingleCurrencyWalletPrimaryCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
refresh: Boolean,
|
||||
): CryptoCurrency {
|
||||
return token.getOrElse { e -> throw e }
|
||||
}
|
||||
|
||||
override suspend fun getSingleCurrencyWalletWithCardCurrencies(
|
||||
userWalletId: UserWalletId,
|
||||
refresh: Boolean,
|
||||
): List<CryptoCurrency> {
|
||||
return tokens.first().getOrElse { e -> throw e }
|
||||
}
|
||||
|
||||
override suspend fun getSingleCurrencyWalletWithCardCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
): CryptoCurrency {
|
||||
return token.getOrElse { e -> throw e }
|
||||
}
|
||||
|
||||
override suspend fun getNetworkCoin(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
): CryptoCurrency.Coin {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isTokensGrouped(userWalletId: UserWalletId): Flow<Boolean> {
|
||||
return isGrouped.map { it.getOrElse { e -> throw e } }
|
||||
}
|
||||
|
||||
override fun isTokensSortedByBalance(userWalletId: UserWalletId): Flow<Boolean> {
|
||||
return isSortedByBalance.map { it.getOrElse { e -> throw e } }
|
||||
}
|
||||
|
||||
override suspend fun isSendBlockedByPendingTransactions(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override suspend fun getFeePaidCurrency(userWalletId: UserWalletId, network: Network): FeePaidCurrency {
|
||||
return FeePaidCurrency.Coin
|
||||
}
|
||||
|
||||
override fun createCoinCurrency(network: Network): CryptoCurrency.Coin {
|
||||
error("not implemented")
|
||||
}
|
||||
|
||||
override fun createTokenCurrency(cryptoCurrency: CryptoCurrency.Token, network: Network): CryptoCurrency.Token {
|
||||
return cryptoCurrency
|
||||
}
|
||||
|
||||
override suspend fun createTokenCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
contractAddress: String,
|
||||
networkId: String,
|
||||
): CryptoCurrency.Token {
|
||||
error("not implemented")
|
||||
}
|
||||
|
||||
override fun getAllWalletsCryptoCurrencies(
|
||||
currencyRawId: CryptoCurrency.RawID,
|
||||
): Flow<Map<UserWallet, List<CryptoCurrency>>> {
|
||||
return emptyFlow()
|
||||
}
|
||||
|
||||
override fun isNetworkFeeZero(userWalletId: UserWalletId, network: Network): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override suspend fun syncTokens(userWalletId: UserWalletId) {
|
||||
return Unit
|
||||
}
|
||||
|
||||
override fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver {
|
||||
error("No-op")
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,6 @@ import com.tangem.domain.models.account.DerivationIndex
|
|||
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.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.lib.crypto.derivation.AccountNodeRecognizer
|
||||
import dagger.assisted.Assisted
|
||||
|
|
@ -30,7 +29,6 @@ import timber.log.Timber
|
|||
@Suppress("LongParameterList")
|
||||
internal class CustomTokenFormUseCasesFacade @AssistedInject constructor(
|
||||
@Assisted private val userWalletId: UserWalletId,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
private val checkIsCurrencyNotAddedUseCase: CheckIsCurrencyNotAddedUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
|
|
@ -40,14 +38,10 @@ internal class CustomTokenFormUseCasesFacade @AssistedInject constructor(
|
|||
) {
|
||||
|
||||
suspend fun addCryptoCurrenciesUseCase(currency: CryptoCurrency): Either<Throwable, Unit> {
|
||||
return if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
either {
|
||||
val accountId = getAccountId(currency)
|
||||
return either {
|
||||
val accountId = getAccountId(currency)
|
||||
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, add = currency).bind()
|
||||
}
|
||||
} else {
|
||||
addCryptoCurrenciesUseCase.invoke(userWalletId = userWalletId, currency = currency)
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, add = currency).bind()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
|||
import com.tangem.domain.account.producer.SingleAccountProducer
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.account.supplier.SingleAccountSupplier
|
||||
import com.tangem.domain.managetokens.*
|
||||
import com.tangem.domain.managetokens.CheckCurrencyUnsupportedUseCase
|
||||
import com.tangem.domain.managetokens.CheckHasLinkedTokensUseCase
|
||||
import com.tangem.domain.managetokens.GetDistinctManagedCurrenciesUseCase
|
||||
import com.tangem.domain.managetokens.GetManagedTokensUseCase
|
||||
import com.tangem.domain.managetokens.model.CurrencyUnsupportedState
|
||||
import com.tangem.domain.managetokens.model.ManageTokensListConfig
|
||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
|
||||
|
|
@ -27,10 +30,8 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor(
|
|||
val getManagedTokensUseCase: GetManagedTokensUseCase,
|
||||
val getDistinctManagedTokensUseCase: GetDistinctManagedCurrenciesUseCase,
|
||||
private val checkHasLinkedTokensUseCase: CheckHasLinkedTokensUseCase,
|
||||
private val removeCustomCurrencyUseCase: RemoveCustomManagedCryptoCurrencyUseCase,
|
||||
private val checkCurrencyUnsupportedUseCase: CheckCurrencyUnsupportedUseCase,
|
||||
private val coldWalletAndHasMissedDerivationsUseCase: ColdWalletAndHasMissedDerivationsUseCase,
|
||||
private val saveManagedTokensUseCase: SaveManagedTokensUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val customTokensRepository: CustomTokensRepository,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
|
|
@ -69,10 +70,7 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor(
|
|||
|
||||
manageCryptoCurrenciesUseCase(accountId = mode.accountId, remove = currency)
|
||||
}
|
||||
is ManageTokensMode.Wallet -> removeCustomCurrencyUseCase.invoke(
|
||||
userWalletId = mode.userWalletId,
|
||||
customCurrency = customCurrency,
|
||||
)
|
||||
is ManageTokensMode.Wallet -> error("Unsupported")
|
||||
ManageTokensMode.None -> nonePortfolioError.left()
|
||||
}
|
||||
}
|
||||
|
|
@ -147,13 +145,7 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor(
|
|||
remove = currenciesToRemove.mapToCryptoCurrencies(userWalletId = mode.accountId.userWalletId),
|
||||
)
|
||||
}
|
||||
is ManageTokensMode.Wallet -> {
|
||||
saveManagedTokensUseCase.invoke(
|
||||
userWalletId = mode.userWalletId,
|
||||
currenciesToAdd = currenciesToAdd,
|
||||
currenciesToRemove = currenciesToRemove,
|
||||
)
|
||||
}
|
||||
is ManageTokensMode.Wallet -> error("Unsupported")
|
||||
ManageTokensMode.None -> nonePortfolioError.left()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
package com.tangem.features.onramp.hottokens.portfolio.model
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.onramp.hottokens.portfolio.OnrampAddToPortfolioComponent
|
||||
import com.tangem.features.onramp.hottokens.portfolio.entity.OnrampAddToPortfolioUM
|
||||
|
|
@ -21,11 +20,10 @@ import javax.inject.Inject
|
|||
/**
|
||||
* Model for adding token to portfolio
|
||||
*
|
||||
* @param paramsContainer params container
|
||||
* @property dispatchers dispatchers
|
||||
* @property derivePublicKeysUseCase use case for deriving public key
|
||||
* @property addCryptoCurrenciesUseCase use case for adding crypto currency
|
||||
* @property getUserWalletUseCase use case for getting user wallet by id
|
||||
* @param paramsContainer params container
|
||||
* @property dispatchers dispatchers
|
||||
* @property manageCryptoCurrenciesUseCase use case for managing crypto currencies
|
||||
* @property getUserWalletUseCase use case for getting user wallet by id
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
@ -33,8 +31,7 @@ import javax.inject.Inject
|
|||
internal class OnrampAddToPortfolioModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -72,21 +69,14 @@ internal class OnrampAddToPortfolioModel @Inject constructor(
|
|||
private fun onAddClick() {
|
||||
modelScope.launch {
|
||||
changeAddButtonProgressStatus(isProgress = true)
|
||||
derivePublicKeysUseCase(
|
||||
userWalletId = params.userWalletId,
|
||||
currencies = listOf(params.cryptoCurrency),
|
||||
).getOrElse { throwable ->
|
||||
Timber.e("Failed to derive public keys: $throwable")
|
||||
|
||||
changeAddButtonProgressStatus(isProgress = false)
|
||||
}
|
||||
|
||||
addCryptoCurrenciesUseCase(
|
||||
userWalletId = params.userWalletId,
|
||||
currency = params.cryptoCurrency,
|
||||
)
|
||||
val accountId = AccountId.forMainCryptoPortfolio(params.userWalletId)
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, add = params.cryptoCurrency)
|
||||
.onRight { params.onSuccessAdding(params.cryptoCurrency.id) }
|
||||
.onLeft { changeAddButtonProgressStatus(isProgress = false) }
|
||||
.onLeft { throwable ->
|
||||
Timber.e("Failed to add crypto currency: $throwable")
|
||||
changeAddButtonProgressStatus(isProgress = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.feature.referral.domain
|
||||
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
|
@ -11,7 +11,7 @@ interface ReferralInteractor {
|
|||
|
||||
suspend fun getReferralStatus(userWalletId: UserWalletId): ReferralData
|
||||
|
||||
suspend fun startReferral(portfolioId: PortfolioId): ReferralData
|
||||
suspend fun startReferral(accountId: AccountId): ReferralData
|
||||
|
||||
suspend fun getCryptoCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
|
|||
|
|
@ -1,30 +1,22 @@
|
|||
package com.tangem.feature.referral.domain
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.domain.account.producer.SingleAccountProducer
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.account.supplier.SingleAccountSupplier
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.feature.referral.domain.errors.ReferralError
|
||||
import com.tangem.feature.referral.domain.models.ReferralData
|
||||
import com.tangem.feature.referral.domain.models.TokenData
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class ReferralInteractorImpl(
|
||||
private val repository: ReferralRepository,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val singleAccountSupplier: SingleAccountSupplier,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
|
|
@ -40,64 +32,41 @@ internal class ReferralInteractorImpl(
|
|||
return referralData
|
||||
}
|
||||
|
||||
override suspend fun startReferral(portfolioId: PortfolioId): ReferralData {
|
||||
override suspend fun startReferral(accountId: AccountId): ReferralData {
|
||||
if (tokensForReferral.isEmpty()) error("Tokens for ref is empty")
|
||||
|
||||
val tokenData = tokensForReferral.first()
|
||||
val userWalletId = portfolioId.userWalletId
|
||||
val userWallet = getUserWalletUseCase(userWalletId).getOrElse {
|
||||
error("Failed to get user wallet $userWalletId: $it")
|
||||
}
|
||||
val userWalletId = accountId.userWalletId
|
||||
|
||||
val accountIndex = when (portfolioId) {
|
||||
is PortfolioId.Account -> {
|
||||
val account = singleAccountSupplier.getSyncOrNull(
|
||||
params = SingleAccountProducer.Params(accountId = portfolioId.accountId),
|
||||
)
|
||||
?: error("Account not found: ${portfolioId.accountId}")
|
||||
val account = singleAccountSupplier.getSyncOrNull(
|
||||
params = SingleAccountProducer.Params(accountId = accountId),
|
||||
)
|
||||
?: error("Account not found: $accountId")
|
||||
|
||||
when (account) {
|
||||
is Account.CryptoPortfolio -> account.derivationIndex
|
||||
is Account.Payment -> TODO("[REDACTED_JIRA]")
|
||||
}
|
||||
}
|
||||
is PortfolioId.Wallet -> null
|
||||
val accountIndex = when (account) {
|
||||
is Account.CryptoPortfolio -> account.derivationIndex
|
||||
is Account.Payment -> TODO("[REDACTED_JIRA]")
|
||||
}
|
||||
|
||||
val cryptoCurrency = getCryptoCurrency(
|
||||
userWalletId = portfolioId.userWalletId,
|
||||
userWalletId = accountId.userWalletId,
|
||||
tokenData = tokenData,
|
||||
accountIndex = accountIndex,
|
||||
)
|
||||
?: error("Failed to create crypto currency")
|
||||
|
||||
when (portfolioId) {
|
||||
is PortfolioId.Account -> {
|
||||
manageCryptoCurrenciesUseCase(
|
||||
accountId = portfolioId.accountId,
|
||||
add = cryptoCurrency,
|
||||
skipDerivationErrors = false,
|
||||
).mapLeft {
|
||||
it.mapToDomainError()
|
||||
}.onLeft { error ->
|
||||
if (error is ReferralError.UserCancelledException) {
|
||||
throw error
|
||||
}
|
||||
manageCryptoCurrenciesUseCase(
|
||||
accountId = accountId,
|
||||
add = cryptoCurrency,
|
||||
skipDerivationErrors = false,
|
||||
)
|
||||
.mapLeft { it.mapToDomainError() }
|
||||
.onLeft { error ->
|
||||
Timber.e(error)
|
||||
if (error is ReferralError.UserCancelledException) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
is PortfolioId.Wallet -> {
|
||||
derivePublicKeysUseCase(userWallet.walletId, listOf(cryptoCurrency)).getOrElse { throwable ->
|
||||
Timber.e("Failed to derive public keys: $throwable")
|
||||
throw throwable.mapToDomainError()
|
||||
}
|
||||
|
||||
addCryptoCurrenciesUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = cryptoCurrency,
|
||||
)
|
||||
}
|
||||
}
|
||||
.onLeft(Timber::e)
|
||||
|
||||
val publicAddress = walletManagersFacade.getDefaultAddress(
|
||||
userWalletId = userWalletId,
|
||||
|
|
|
|||
|
|
@ -4,10 +4,7 @@ import com.tangem.core.decompose.di.ModelComponent
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.account.supplier.SingleAccountSupplier
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.feature.referral.domain.ReferralInteractor
|
||||
import com.tangem.feature.referral.domain.ReferralInteractorImpl
|
||||
import com.tangem.feature.referral.domain.ReferralRepository
|
||||
|
|
@ -23,18 +20,12 @@ class ReferralDomainModule {
|
|||
@ModelScoped
|
||||
fun provideReferralInteractor(
|
||||
referralRepository: ReferralRepository,
|
||||
derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
getUserWalletUseCase: GetUserWalletUseCase,
|
||||
addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
singleAccountSupplier: SingleAccountSupplier,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
): ReferralInteractor {
|
||||
return ReferralInteractorImpl(
|
||||
repository = referralRepository,
|
||||
derivePublicKeysUseCase = derivePublicKeysUseCase,
|
||||
getUserWalletUseCase = getUserWalletUseCase,
|
||||
addCryptoCurrenciesUseCase = addCryptoCurrenciesUseCase,
|
||||
manageCryptoCurrenciesUseCase = manageCryptoCurrenciesUseCase,
|
||||
singleAccountSupplier = singleAccountSupplier,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.navigation.share.ShareManager
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrency
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
||||
|
|
@ -24,8 +23,6 @@ import com.tangem.domain.account.status.usecase.GetAccountCurrencyByAddressUseCa
|
|||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
|
|
@ -44,10 +41,12 @@ import com.tangem.features.account.PortfolioFetcher
|
|||
import com.tangem.features.account.PortfolioSelectorComponent
|
||||
import com.tangem.features.account.PortfolioSelectorController
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@Suppress("LongParameterList")
|
||||
@Stable
|
||||
@ModelScoped
|
||||
|
|
@ -60,7 +59,6 @@ internal class ReferralModel @Inject constructor(
|
|||
private val urlOpener: UrlOpener,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val portfolioFetcherFactory: PortfolioFetcher.Factory,
|
||||
val portfolioSelectorController: PortfolioSelectorController,
|
||||
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
|
|
@ -92,26 +90,24 @@ internal class ReferralModel @Inject constructor(
|
|||
|
||||
init {
|
||||
analyticsEventHandler.send(ReferralEvents.ReferralScreenOpened())
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
combine(
|
||||
flow = referralData.filterNotNull().onEach(::selectAccount),
|
||||
flow2 = portfolioSelectorController.isAccountMode,
|
||||
transform = { referralData, isAccountMode -> referralData to isAccountMode },
|
||||
).transformLatest { (referralData, isAccountMode) ->
|
||||
when (isAccountMode) {
|
||||
false -> showContent(referralData)
|
||||
true -> combineAccountUI(referralData)
|
||||
|
||||
combine(
|
||||
flow = referralData.filterNotNull().onEach(::selectAccount),
|
||||
flow2 = portfolioSelectorController.isAccountMode,
|
||||
transform = { referralData, isAccountMode -> referralData to isAccountMode },
|
||||
)
|
||||
.transformLatest { (referralData, isAccountMode) ->
|
||||
if (!isAccountMode) {
|
||||
showContent(referralData)
|
||||
} else {
|
||||
combineAccountUI(referralData)
|
||||
.map { referralData to it }
|
||||
.collect(::emit)
|
||||
}
|
||||
}
|
||||
.onEach { (referralData, accountAward) -> showContent(referralData, accountAward) }
|
||||
.launchIn(modelScope)
|
||||
} else {
|
||||
referralData.filterNotNull()
|
||||
.onEach(::showContent)
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
.onEach { (referralData, accountAward) -> showContent(referralData, accountAward) }
|
||||
.launchIn(modelScope)
|
||||
|
||||
loadReferralData()
|
||||
}
|
||||
|
||||
|
|
@ -123,12 +119,7 @@ internal class ReferralModel @Inject constructor(
|
|||
flow3 = getSelectedAppCurrencyUseCase.invokeOrDefault(),
|
||||
flow4 = portfolioFetcher.data,
|
||||
) { pair, isBalanceHidden, appCurrency, portfolios ->
|
||||
val selectedAccount = pair?.second ?: return@combine null
|
||||
|
||||
val cryptoPortfolio = when (selectedAccount) {
|
||||
is AccountStatus.CryptoPortfolio -> selectedAccount
|
||||
is AccountStatus.Payment -> TODO("[REDACTED_JIRA]")
|
||||
}
|
||||
val cryptoPortfolio = pair?.second ?: return@combine null
|
||||
|
||||
val awardCryptoCurrency = referralInteractor.getCryptoCurrency(
|
||||
userWalletId = params.userWalletId,
|
||||
|
|
@ -185,11 +176,8 @@ internal class ReferralModel @Inject constructor(
|
|||
val lastInfoState = uiState.referralInfoState
|
||||
uiState = uiState.copy(referralInfoState = ReferralInfoState.Loading)
|
||||
modelScope.launch {
|
||||
val portfolioId = when (accountsFeatureToggles.isFeatureEnabled) {
|
||||
true -> PortfolioId(requireNotNull(portfolioSelectorController.selectedAccountSync))
|
||||
false -> PortfolioId(params.userWalletId)
|
||||
}
|
||||
runCatching { referralInteractor.startReferral(portfolioId) }
|
||||
val accountId = requireNotNull(portfolioSelectorController.selectedAccountSync)
|
||||
runCatching { referralInteractor.startReferral(accountId) }
|
||||
.onSuccess { referral ->
|
||||
analyticsEventHandler.send(ReferralEvents.ParticipateSuccessful())
|
||||
referralData.value = referral
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import com.tangem.core.ui.HoldToConfirmButtonFeatureToggles
|
|||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
|
||||
|
|
@ -36,7 +35,6 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
|||
import com.tangem.domain.models.wallet.isHotWallet
|
||||
import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase
|
||||
import com.tangem.domain.settings.NeverShowTapHelpUseCase
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.IsAmountSubtractAvailableUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.transaction.usecase.CreateTransferTransactionUseCase
|
||||
|
|
@ -75,10 +73,8 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
|||
import com.tangem.utils.extensions.orZero
|
||||
import com.tangem.utils.extensions.stripZeroPlainString
|
||||
import com.tangem.utils.transformer.update
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
import javax.inject.Inject
|
||||
|
|
@ -100,7 +96,6 @@ internal class SendConfirmModel @Inject constructor(
|
|||
private val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase,
|
||||
private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase,
|
||||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
|
||||
private val isAmountSubtractAvailableUseCase: IsAmountSubtractAvailableUseCase,
|
||||
private val feeSelectorCheckReloadListener: FeeSelectorCheckReloadListener,
|
||||
|
|
@ -114,7 +109,6 @@ internal class SendConfirmModel @Inject constructor(
|
|||
private val feeSelectorReloadTrigger: FeeSelectorReloadTrigger,
|
||||
private val sendAmountReduceTrigger: SendAmountReduceTrigger,
|
||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val createAndSendGaslessTransactionUseCase: CreateAndSendGaslessTransactionUseCase,
|
||||
|
|
@ -466,24 +460,14 @@ internal class SendConfirmModel @Inject constructor(
|
|||
.firstOrNull { it.address == confirmData.enteredDestination }
|
||||
?: return
|
||||
|
||||
val userWalletId = receivingUserWallet.userWalletId ?: return
|
||||
val network = receivingUserWallet.network ?: return
|
||||
|
||||
modelScope.launch(dispatchers.default) {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val accountId = receivingUserWallet.accountId ?: return@launch
|
||||
val accountId = receivingUserWallet.accountId ?: return@launch
|
||||
|
||||
val tokenToAdd = currenciesRepository.createTokenCurrency(cryptoCurrency, network)
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, add = tokenToAdd)
|
||||
} else {
|
||||
withContext(NonCancellable) {
|
||||
addCryptoCurrenciesUseCase(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
network = network,
|
||||
)
|
||||
}
|
||||
}.onLeft(Timber::e)
|
||||
val tokenToAdd = currenciesRepository.createTokenCurrency(cryptoCurrency, network)
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, add = tokenToAdd)
|
||||
.onLeft(Timber::e)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
private val getExploreUrlUseCase: GetExploreUrlUseCase,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
private val removeCurrencyUseCase: RemoveCurrencyUseCase,
|
||||
private val isCryptoCurrencyCoinCouldHideUseCase: IsCryptoCurrencyCoinCouldHideUseCase,
|
||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val getCurrencyWarningsUseCase: GetCurrencyWarningsUseCase,
|
||||
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
|
||||
|
|
@ -758,8 +758,12 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonRemoveToken(cryptoCurrency.symbol))
|
||||
|
||||
modelScope.launch {
|
||||
val hasLinkedTokens = removeCurrencyUseCase.hasLinkedTokens(userWalletId, cryptoCurrency)
|
||||
internalUiState.value = if (hasLinkedTokens) {
|
||||
val canHide = cryptoCurrency is CryptoCurrency.Coin && isCryptoCurrencyCoinCouldHideUseCase(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencyCoin = cryptoCurrency,
|
||||
)
|
||||
|
||||
internalUiState.value = if (!canHide) {
|
||||
stateFactory.getStateWithLinkedTokensDialog(cryptoCurrency)
|
||||
} else {
|
||||
stateFactory.getStateWithConfirmHideTokenDialog(cryptoCurrency)
|
||||
|
|
@ -769,18 +773,14 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
|
||||
override fun onHideConfirmed() {
|
||||
modelScope.launch {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val accountId = account?.accountId
|
||||
val accountId = account?.accountId
|
||||
|
||||
if (accountId == null) {
|
||||
Timber.e("Account ID is null, cannot hide currency ${cryptoCurrency.id}")
|
||||
return@launch
|
||||
}
|
||||
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, remove = cryptoCurrency)
|
||||
} else {
|
||||
removeCurrencyUseCase(userWalletId, cryptoCurrency)
|
||||
if (accountId == null) {
|
||||
Timber.e("Account ID is null, cannot hide currency ${cryptoCurrency.id}")
|
||||
return@launch
|
||||
}
|
||||
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, remove = cryptoCurrency)
|
||||
.onLeft { Timber.e(it) }
|
||||
.onRight { router.popBackStack() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.tangem.common.ui.expressStatus.state.ExpressTransactionsBlockState
|
|||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.datasource.local.swap.ExpressAnalyticsStatus
|
||||
import com.tangem.datasource.local.swap.SwapTransactionStatusStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
|
|
@ -14,7 +13,6 @@ import com.tangem.domain.models.currency.CryptoCurrency
|
|||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.model.analytics.TokenExchangeAnalyticsEvent
|
||||
import com.tangem.feature.swap.domain.SwapTransactionRepository
|
||||
import com.tangem.feature.swap.domain.api.SwapRepository
|
||||
|
|
@ -38,8 +36,6 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
|
|||
private val swapTransactionRepository: SwapTransactionRepository,
|
||||
private val swapRepository: SwapRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val swapTransactionStatusStore: SwapTransactionStatusStore,
|
||||
|
|
@ -117,30 +113,22 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
|
|||
ifRight = { statusModel ->
|
||||
sendStatusUpdateAnalytics(statusModel, provider)
|
||||
|
||||
val accountId = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = cryptoCurrency,
|
||||
)
|
||||
.map { it.account.accountId }
|
||||
.getOrNull()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val accountId = getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = cryptoCurrency,
|
||||
)
|
||||
.map { it.account.accountId }
|
||||
.getOrNull()
|
||||
|
||||
val refundTokenCurrency = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
if (accountId != null) {
|
||||
addRefundCurrencyIfNeededNew(
|
||||
accountId = accountId,
|
||||
status = statusModel,
|
||||
type = provider.type,
|
||||
)
|
||||
} else {
|
||||
Timber.e("Account ID is null, cannot add refund currency ${cryptoCurrency.id}")
|
||||
null
|
||||
}
|
||||
val refundTokenCurrency = if (accountId != null) {
|
||||
addRefundCurrencyIfNeeded(
|
||||
accountId = accountId,
|
||||
status = statusModel,
|
||||
type = provider.type,
|
||||
)
|
||||
} else {
|
||||
addRefundCurrencyIfNeededLegacy(status = statusModel, type = provider.type)
|
||||
Timber.e("Account ID is null, cannot add refund currency ${cryptoCurrency.id}")
|
||||
null
|
||||
}
|
||||
|
||||
swapTransactionRepository.storeTransactionState(
|
||||
|
|
@ -170,28 +158,7 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For now do it only for dex-bridge provider
|
||||
*/
|
||||
private suspend fun addRefundCurrencyIfNeededLegacy(
|
||||
status: ExchangeStatusModel?,
|
||||
type: ExchangeProviderType,
|
||||
): CryptoCurrency? {
|
||||
status ?: return null
|
||||
if (type != ExchangeProviderType.DEX_BRIDGE) return null
|
||||
val refundNetwork = status.refundNetwork
|
||||
val refundContractAddress = status.refundContractAddress
|
||||
if (refundNetwork != null && refundContractAddress != null) {
|
||||
return addCryptoCurrenciesUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
contractAddress = refundContractAddress,
|
||||
networkId = refundNetwork,
|
||||
).getOrNull()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private suspend fun addRefundCurrencyIfNeededNew(
|
||||
private suspend fun addRefundCurrencyIfNeeded(
|
||||
accountId: AccountId,
|
||||
status: ExchangeStatusModel?,
|
||||
type: ExchangeProviderType,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig
|
|||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.datasource.local.swap.ExpressAnalyticsStatus
|
||||
import com.tangem.datasource.local.swap.SwapTransactionStatusStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
|
|
@ -13,7 +12,6 @@ import com.tangem.domain.models.currency.CryptoCurrency
|
|||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.model.analytics.TokenExchangeAnalyticsEvent
|
||||
import com.tangem.feature.swap.domain.SwapTransactionRepository
|
||||
import com.tangem.feature.swap.domain.api.SwapRepository
|
||||
|
|
@ -39,8 +37,6 @@ internal class TokenDetailsExchangeStatusFactory @AssistedInject constructor(
|
|||
private val swapTransactionRepository: SwapTransactionRepository,
|
||||
private val swapRepository: SwapRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val swapTransactionStatusStore: SwapTransactionStatusStore,
|
||||
|
|
@ -118,30 +114,22 @@ internal class TokenDetailsExchangeStatusFactory @AssistedInject constructor(
|
|||
ifRight = { statusModel ->
|
||||
sendStatusUpdateAnalytics(statusModel, provider)
|
||||
|
||||
val accountId = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = cryptoCurrency,
|
||||
)
|
||||
.map { it.account.accountId }
|
||||
.getOrNull()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val accountId = getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = cryptoCurrency,
|
||||
)
|
||||
.map { it.account.accountId }
|
||||
.getOrNull()
|
||||
|
||||
val refundTokenCurrency = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
if (accountId != null) {
|
||||
addRefundCurrencyIfNeededNew(
|
||||
accountId = accountId,
|
||||
status = statusModel,
|
||||
type = provider.type,
|
||||
)
|
||||
} else {
|
||||
Timber.e("Account ID is null, cannot add refund currency ${cryptoCurrency.id}")
|
||||
null
|
||||
}
|
||||
val refundTokenCurrency = if (accountId != null) {
|
||||
addRefundCurrencyIfNeeded(
|
||||
accountId = accountId,
|
||||
status = statusModel,
|
||||
type = provider.type,
|
||||
)
|
||||
} else {
|
||||
addRefundCurrencyIfNeededLegacy(status = statusModel, type = provider.type)
|
||||
Timber.e("Account ID is null, cannot add refund currency ${cryptoCurrency.id}")
|
||||
null
|
||||
}
|
||||
|
||||
swapTransactionRepository.storeTransactionState(
|
||||
|
|
@ -171,28 +159,7 @@ internal class TokenDetailsExchangeStatusFactory @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For now do it only for dex-bridge provider
|
||||
*/
|
||||
private suspend fun addRefundCurrencyIfNeededLegacy(
|
||||
status: ExchangeStatusModel?,
|
||||
type: ExchangeProviderType,
|
||||
): CryptoCurrency? {
|
||||
status ?: return null
|
||||
if (type != ExchangeProviderType.DEX_BRIDGE) return null
|
||||
val refundNetwork = status.refundNetwork
|
||||
val refundContractAddress = status.refundContractAddress
|
||||
if (refundNetwork != null && refundContractAddress != null) {
|
||||
return addCryptoCurrenciesUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
contractAddress = refundContractAddress,
|
||||
networkId = refundNetwork,
|
||||
).getOrNull()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private suspend fun addRefundCurrencyIfNeededNew(
|
||||
private suspend fun addRefundCurrencyIfNeeded(
|
||||
accountId: AccountId,
|
||||
status: ExchangeStatusModel?,
|
||||
type: ExchangeProviderType,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue