Updated on 2026-08-14
This commit is contained in:
parent
f3e8deb60a
commit
e378b8b80d
12 changed files with 137 additions and 6 deletions
|
|
@ -26,6 +26,15 @@ internal object TokensDomainModule {
|
|||
return GetTokenListUseCase(currenciesRepository, quotesRepository, networksRepository, dispatchers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideRemoveCurrencyUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): RemoveCurrencyUseCase {
|
||||
return RemoveCurrencyUseCase(currenciesRepository, dispatchers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetCurrencyUseCase(
|
||||
|
|
|
|||
|
|
@ -53,6 +53,22 @@ internal class DefaultCurrenciesRepository(
|
|||
storeAndPushTokens(userWalletId, response)
|
||||
}
|
||||
|
||||
override suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency) =
|
||||
withContext(dispatchers.io) {
|
||||
val savedCurrencies = requireNotNull(
|
||||
value = userTokensStore.getSyncOrNull(userWalletId),
|
||||
lazyMessage = { "Saved tokens empty. Can not perform remove currency action" },
|
||||
)
|
||||
|
||||
val token = userTokensResponseFactory.createResponseToken(currency)
|
||||
storeAndPushTokens(
|
||||
userWalletId = userWalletId,
|
||||
response = savedCurrencies.copy(
|
||||
tokens = savedCurrencies.tokens.filter { it != token },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getSingleCurrencyWalletPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency {
|
||||
return withContext(dispatchers.io) {
|
||||
val userWallet = getUserWallet(userWalletId)
|
||||
|
|
@ -78,6 +94,21 @@ internal class DefaultCurrenciesRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getMultiCurrencyWalletCurrenciesSync(
|
||||
userWalletId: UserWalletId,
|
||||
refresh: Boolean,
|
||||
): List<CryptoCurrency> {
|
||||
val userWallet = getUserWallet(userWalletId)
|
||||
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true)
|
||||
|
||||
fetchTokensIfCacheExpired(userWallet, refresh)
|
||||
val storedTokens = requireNotNull(userTokensStore.getSyncOrNull(userWallet.walletId))
|
||||
return responseCurrenciesFactory.createCurrencies(
|
||||
response = storedTokens,
|
||||
card = userWallet.scanResponse.card,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getMultiCurrencyWalletCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ internal class UserTokensResponseFactory {
|
|||
)
|
||||
}
|
||||
|
||||
private fun createResponseToken(currency: CryptoCurrency): UserTokensResponse.Token {
|
||||
fun createResponseToken(currency: CryptoCurrency): UserTokensResponse.Token {
|
||||
val blockchain = getBlockchain(currency.network.id)
|
||||
|
||||
return UserTokensResponse.Token(
|
||||
|
|
|
|||
|
|
@ -73,8 +73,6 @@ data class Network(
|
|||
}
|
||||
|
||||
/** Represents a network that does not adhere to a predefined standard type. */
|
||||
class Unspecified(val networkName: String) : StandardType() {
|
||||
override val name: String = networkName
|
||||
}
|
||||
data class Unspecified(override val name: String) : StandardType()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.domain.tokens.models.remove
|
||||
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
|
||||
sealed class RemoveCurrencyError : Throwable() {
|
||||
data class HasLinkedTokens(val currency: CryptoCurrency) : RemoveCurrencyError()
|
||||
data class DataError(override val cause: Throwable) : RemoveCurrencyError()
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.raise.ensure
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.remove.RemoveCurrencyError
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
||||
class RemoveCurrencyUseCase(
|
||||
internal val currenciesRepository: CurrenciesRepository,
|
||||
internal val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
currency: CryptoCurrency,
|
||||
): Either<RemoveCurrencyError, Unit> {
|
||||
return either {
|
||||
ensure(
|
||||
condition = !currency.hasLinkedTokens(userWalletId),
|
||||
raise = { RemoveCurrencyError.HasLinkedTokens(currency) },
|
||||
)
|
||||
catch(
|
||||
block = { currenciesRepository.removeCurrency(userWalletId, currency) },
|
||||
catch = { raise(RemoveCurrencyError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun CryptoCurrency.hasLinkedTokens(userWalletId: UserWalletId): Boolean {
|
||||
val walletCurrencies = currenciesRepository
|
||||
.getMultiCurrencyWalletCurrenciesSync(userWalletId = userWalletId, refresh = false)
|
||||
|
||||
return this is CryptoCurrency.Coin && walletCurrencies.any { it != this && it.network.id == this.network.id }
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,16 @@ interface CurrenciesRepository {
|
|||
isSortedByBalance: Boolean,
|
||||
)
|
||||
|
||||
/**
|
||||
* 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 com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If multi-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency)
|
||||
|
||||
/**
|
||||
* Retrieves the primary cryptocurrency for a specific single-currency user wallet.
|
||||
*
|
||||
|
|
@ -48,6 +58,17 @@ interface CurrenciesRepository {
|
|||
*/
|
||||
fun getMultiCurrencyWalletCurrencies(userWalletId: UserWalletId, refresh: Boolean): Flow<List<CryptoCurrency>>
|
||||
|
||||
/**
|
||||
* Retrieves the list of cryptocurrencies within a multi-currency wallet.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param refresh A boolean flag indicating whether the data should be refreshed.
|
||||
* @return A list of [CryptoCurrency].
|
||||
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If single-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
suspend fun getMultiCurrencyWalletCurrenciesSync(userWalletId: UserWalletId, refresh: Boolean): List<CryptoCurrency>
|
||||
|
||||
/**
|
||||
* Retrieves the cryptocurrency for a specific multi-currency user wallet.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -190,8 +190,16 @@ internal class ApplyTokenListSortingUseCaseTest {
|
|||
|
||||
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, MockTokens.token1.right(), tokens, emptyFlow(), emptyFlow())
|
||||
return MockCurrenciesRepository(
|
||||
sortTokensResult = sortTokensResult,
|
||||
removeCurrencyResult = removeCurrencyResult,
|
||||
token = MockTokens.token1.right(),
|
||||
tokens = tokens,
|
||||
isGrouped = emptyFlow(),
|
||||
isSortedByBalance = emptyFlow(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -150,12 +150,14 @@ internal class GetPrimaryCurrencyUseCaseTest {
|
|||
|
||||
private fun getUseCase(
|
||||
token: Either<DataError, CryptoCurrency> = MockTokens.token1.right(),
|
||||
removeCurrencyResult: Either<DataError, Unit> = Unit.right(),
|
||||
quotes: Flow<Either<DataError, Set<Quote>>> = flowOf(MockQuotes.quotes.right()),
|
||||
statuses: Flow<Either<DataError, Set<NetworkStatus>>> = flowOf(MockNetworks.verifiedNetworksStatuses.right()),
|
||||
) = GetPrimaryCurrencyUseCase(
|
||||
dispatchers = dispatchers,
|
||||
currenciesRepository = MockCurrenciesRepository(
|
||||
sortTokensResult = Unit.right(),
|
||||
removeCurrencyResult = removeCurrencyResult,
|
||||
token = token,
|
||||
tokens = flowOf(),
|
||||
isGrouped = flowOf(),
|
||||
|
|
|
|||
|
|
@ -342,6 +342,7 @@ internal class GetTokenListUseCaseTest {
|
|||
dispatchers = dispatchers,
|
||||
currenciesRepository = MockCurrenciesRepository(
|
||||
sortTokensResult = Unit.right(),
|
||||
removeCurrencyResult = Unit.right(),
|
||||
token = MockTokens.token1.right(),
|
||||
tokens = tokens,
|
||||
isGrouped = isGrouped,
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@ import com.tangem.domain.core.error.DataError
|
|||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
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>>,
|
||||
|
|
@ -38,6 +40,17 @@ internal class MockCurrenciesRepository(
|
|||
isTokensSortedByBalanceAfterSortingApply = isSortedByBalance
|
||||
}
|
||||
|
||||
override suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency) {
|
||||
removeCurrencyResult.onLeft { throw it }
|
||||
}
|
||||
|
||||
override suspend fun getMultiCurrencyWalletCurrenciesSync(
|
||||
userWalletId: UserWalletId,
|
||||
refresh: Boolean,
|
||||
): List<CryptoCurrency> {
|
||||
return tokens.first().getOrElse { e -> throw e }
|
||||
}
|
||||
|
||||
override suspend fun getSingleCurrencyWalletPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency {
|
||||
return token.getOrElse { e -> throw e }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ okHttp-prettyLogging = "3.1.0"
|
|||
# endregion Other libraries
|
||||
|
||||
# region Tangem
|
||||
tangemBlockchainSdk = "develop-330"
|
||||
tangemBlockchainSdk = "develop-331"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "develop-289"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue