Updated on 2026-08-14
This commit is contained in:
parent
dd186d6fbc
commit
3f5f3ef68b
23 changed files with 351 additions and 128 deletions
|
|
@ -6,4 +6,9 @@ sealed class DataError : Exception() {
|
|||
|
||||
object NoInternetConnection : NetworkError()
|
||||
}
|
||||
|
||||
sealed class UserWalletError : DataError() {
|
||||
|
||||
data class WrongUserWallet(override val message: String) : UserWalletError()
|
||||
}
|
||||
}
|
||||
|
|
@ -9,14 +9,14 @@ import arrow.core.toNonEmptySetOrNull
|
|||
import com.tangem.domain.tokens.error.TokenListSortingError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.repository.TokensRepository
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class ApplyTokenListSortingUseCase(
|
||||
private val tokensRepository: TokensRepository,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
|
|
@ -67,7 +67,9 @@ class ApplyTokenListSortingUseCase(
|
|||
|
||||
private suspend fun Raise<TokenListSortingError>.getCurrencies(userWalletId: UserWalletId): Set<CryptoCurrency> {
|
||||
val tokens = catch(
|
||||
block = { tokensRepository.getMultiCurrencyWalletCurrencies(userWalletId, refresh = false).firstOrNull() },
|
||||
block = {
|
||||
currenciesRepository.getMultiCurrencyWalletCurrencies(userWalletId, refresh = false).firstOrNull()
|
||||
},
|
||||
catch = { raise(TokenListSortingError.DataError(it)) },
|
||||
)
|
||||
|
||||
|
|
@ -83,7 +85,7 @@ class ApplyTokenListSortingUseCase(
|
|||
isSortedByBalance: Boolean,
|
||||
) = withContext(dispatchers.io) {
|
||||
catch(
|
||||
block = { tokensRepository.saveTokens(userWalletId, tokens, isGrouped, isSortedByBalance) },
|
||||
block = { currenciesRepository.saveTokens(userWalletId, tokens, isGrouped, isSortedByBalance) },
|
||||
catch = { raise(TokenListSortingError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.recover
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.tokens.error.CurrencyError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToTokenError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
|
||||
/**
|
||||
* Use case for fetching the status of a specific cryptocurrency associated with a user wallet.
|
||||
*
|
||||
* @property currenciesRepository Repository for managing and fetching cryptocurrencies.
|
||||
* @property quotesRepository Repository for managing and fetching cryptocurrency quotes.
|
||||
* @property networksRepository Repository for managing and fetching information related to blockchain networks.
|
||||
* @property dispatchers Provides coroutine dispatchers.
|
||||
*/
|
||||
class GetCurrencyUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Invokes the use case.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @param currencyId The unique identifier of the cryptocurrency.
|
||||
* @param refresh A boolean flag indicating whether the data should be refreshed.
|
||||
* @return A [Flow] emitting either a [CurrencyError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
|
||||
*/
|
||||
operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
refresh: Boolean = false,
|
||||
): Flow<Either<CurrencyError, CryptoCurrencyStatus>> {
|
||||
return channelFlow {
|
||||
recover(
|
||||
block = {
|
||||
getCurrency(userWalletId, currencyId, refresh).collectLatest { currencyStatus ->
|
||||
send(currencyStatus.right())
|
||||
}
|
||||
},
|
||||
recover = { error ->
|
||||
send(error.left())
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun Raise<CurrencyError>.getCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
refresh: Boolean,
|
||||
): Flow<CryptoCurrencyStatus> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
networksRepository = networksRepository,
|
||||
userWalletId = userWalletId,
|
||||
refresh = refresh,
|
||||
dispatchers = dispatchers,
|
||||
raise = this,
|
||||
transformError = CurrenciesStatusesOperations.Error::mapToTokenError,
|
||||
)
|
||||
|
||||
return operations.getCurrencyStatusFlow(currencyId)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,35 +5,50 @@ import arrow.core.left
|
|||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.recover
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.tokens.error.TokenError
|
||||
import com.tangem.domain.tokens.error.CurrencyError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToTokenError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.tokens.repository.TokensRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
|
||||
/**
|
||||
* Use case for fetching the status of the primary cryptocurrency associated with a user wallet.
|
||||
*
|
||||
* @property currenciesRepository Repository for managing and fetching cryptocurrencies.
|
||||
* @property quotesRepository Repository for managing and fetching cryptocurrency quotes.
|
||||
* @property networksRepository Repository for managing and fetching information related to blockchain networks.
|
||||
* @property dispatchers Provides coroutine dispatchers.
|
||||
*/
|
||||
class GetPrimaryCurrencyUseCase(
|
||||
private val tokensRepository: TokensRepository,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Invokes the use case.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @param refresh A boolean flag indicating whether the data should be refreshed.
|
||||
* @return A [Flow] emitting either a [CurrencyError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
|
||||
*/
|
||||
operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
refresh: Boolean = false,
|
||||
): Flow<Either<TokenError, CryptoCurrencyStatus>> {
|
||||
): Flow<Either<CurrencyError, CryptoCurrencyStatus>> {
|
||||
return channelFlow {
|
||||
recover(
|
||||
block = {
|
||||
getToken(userWalletId, refresh).collectLatest { token ->
|
||||
send(token.right())
|
||||
getCurrency(userWalletId, refresh).collectLatest { currencyStatus ->
|
||||
send(currencyStatus.right())
|
||||
}
|
||||
},
|
||||
recover = { error ->
|
||||
|
|
@ -43,12 +58,12 @@ class GetPrimaryCurrencyUseCase(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun Raise<TokenError>.getToken(
|
||||
private suspend fun Raise<CurrencyError>.getCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
refresh: Boolean,
|
||||
): Flow<CryptoCurrencyStatus> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
tokensRepository = tokensRepository,
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
networksRepository = networksRepository,
|
||||
userWalletId = userWalletId,
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
import com.tangem.domain.tokens.operations.TokenListOperations
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.tokens.repository.TokensRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -22,7 +22,7 @@ import kotlinx.coroutines.flow.collectLatest
|
|||
import kotlinx.coroutines.flow.flatMapConcat
|
||||
|
||||
class GetTokenListUseCase(
|
||||
internal val tokensRepository: TokensRepository,
|
||||
internal val currenciesRepository: CurrenciesRepository,
|
||||
internal val quotesRepository: QuotesRepository,
|
||||
internal val networksRepository: NetworksRepository,
|
||||
internal val dispatchers: CoroutineDispatcherProvider,
|
||||
|
|
@ -60,7 +60,7 @@ class GetTokenListUseCase(
|
|||
transformError = CurrenciesStatusesOperations.Error::mapToTokenListError,
|
||||
)
|
||||
|
||||
return operations.getMultiCurrencyWalletStatusesFlow()
|
||||
return operations.getCurrenciesStatusesFlow()
|
||||
}
|
||||
|
||||
private fun Raise<TokenListError>.createTokenList(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.domain.tokens.error
|
||||
|
||||
sealed class CurrencyError {
|
||||
|
||||
object UnableToCreateCurrency : CurrencyError()
|
||||
|
||||
data class DataError(val cause: Throwable) : CurrencyError()
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
package com.tangem.domain.tokens.error
|
||||
|
||||
sealed class TokenError {
|
||||
|
||||
object UnableToCreateToken : TokenError()
|
||||
|
||||
data class DataError(val cause: Throwable) : TokenError()
|
||||
}
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
package com.tangem.domain.tokens.error.mapper
|
||||
|
||||
import com.tangem.domain.tokens.error.TokenError
|
||||
import com.tangem.domain.tokens.error.CurrencyError
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
|
||||
internal fun CurrenciesStatusesOperations.Error.mapToTokenError(): TokenError {
|
||||
internal fun CurrenciesStatusesOperations.Error.mapToTokenError(): CurrencyError {
|
||||
return when (this) {
|
||||
is CurrenciesStatusesOperations.Error.DataError -> TokenError.DataError(this.cause)
|
||||
is CurrenciesStatusesOperations.Error.DataError -> CurrencyError.DataError(this.cause)
|
||||
is CurrenciesStatusesOperations.Error.EmptyNetworksStatuses,
|
||||
is CurrenciesStatusesOperations.Error.EmptyQuotes,
|
||||
is CurrenciesStatusesOperations.Error.EmptyCurrencies,
|
||||
is CurrenciesStatusesOperations.Error.UnableToCreateCurrencyStatus,
|
||||
-> TokenError.UnableToCreateToken
|
||||
-> CurrencyError.UnableToCreateCurrency
|
||||
}
|
||||
}
|
||||
|
|
@ -7,9 +7,9 @@ import com.tangem.domain.core.raise.DelegatedRaise
|
|||
import com.tangem.domain.tokens.GetTokenListUseCase
|
||||
import com.tangem.domain.tokens.model.*
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.tokens.repository.TokensRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
|
@ -17,7 +17,7 @@ import kotlinx.coroutines.withContext
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class CurrenciesStatusesOperations<E>(
|
||||
private val tokensRepository: TokensRepository,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val userWalletId: UserWalletId,
|
||||
|
|
@ -34,7 +34,7 @@ internal class CurrenciesStatusesOperations<E>(
|
|||
raise: Raise<E>,
|
||||
transformError: (Error) -> E,
|
||||
) : this(
|
||||
tokensRepository = useCase.tokensRepository,
|
||||
currenciesRepository = useCase.currenciesRepository,
|
||||
quotesRepository = useCase.quotesRepository,
|
||||
networksRepository = useCase.networksRepository,
|
||||
userWalletId = userWalletId,
|
||||
|
|
@ -44,7 +44,7 @@ internal class CurrenciesStatusesOperations<E>(
|
|||
transformError = transformError,
|
||||
)
|
||||
|
||||
fun getMultiCurrencyWalletStatusesFlow(): Flow<Set<CryptoCurrencyStatus>> {
|
||||
fun getCurrenciesStatusesFlow(): Flow<Set<CryptoCurrencyStatus>> {
|
||||
return getMultiCurrencyWalletCurrencies().flatMapConcat {
|
||||
val currencies = it.toNonEmptySetOrNull()
|
||||
|
||||
|
|
@ -68,9 +68,19 @@ internal class CurrenciesStatusesOperations<E>(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun getCurrencyStatusFlow(currencyId: CryptoCurrency.ID): Flow<CryptoCurrencyStatus> {
|
||||
val currency = getMultiCurrencyWalletCurrency(currencyId)
|
||||
|
||||
return getCurrencyStatusFlow(currency)
|
||||
}
|
||||
|
||||
suspend fun getPrimaryCurrencyStatusFlow(): Flow<CryptoCurrencyStatus> {
|
||||
val currency = getPrimaryCurrency()
|
||||
|
||||
return getCurrencyStatusFlow(currency)
|
||||
}
|
||||
|
||||
private fun getCurrencyStatusFlow(currency: CryptoCurrency): Flow<CryptoCurrencyStatus> {
|
||||
val quoteFlow = getQuotes(nonEmptySetOf(currency.id))
|
||||
.map { quotes ->
|
||||
quotes.singleOrNull { it.currencyId == currency.id }
|
||||
|
|
@ -116,34 +126,36 @@ internal class CurrenciesStatusesOperations<E>(
|
|||
return currencyStatusOperations.createTokenStatus()
|
||||
}
|
||||
|
||||
private suspend fun getMultiCurrencyWalletCurrency(currencyId: CryptoCurrency.ID): CryptoCurrency {
|
||||
return catch(
|
||||
block = { currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, currencyId) },
|
||||
catch = { raise(Error.DataError(it)) },
|
||||
)
|
||||
}
|
||||
|
||||
private fun getMultiCurrencyWalletCurrencies(): Flow<Set<CryptoCurrency>> {
|
||||
return tokensRepository.getMultiCurrencyWalletCurrencies(userWalletId, refresh)
|
||||
return currenciesRepository.getMultiCurrencyWalletCurrencies(userWalletId, refresh)
|
||||
.catch { raise(Error.DataError(it)) }
|
||||
.onEmpty { raise(Error.EmptyCurrencies) }
|
||||
.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
private suspend fun getPrimaryCurrency(): CryptoCurrency {
|
||||
return withContext(dispatchers.io) {
|
||||
catch(
|
||||
block = { tokensRepository.getPrimaryCurrency(userWalletId) },
|
||||
catch = { raise(Error.DataError(it)) },
|
||||
)
|
||||
}
|
||||
return catch(
|
||||
block = { currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(userWalletId) },
|
||||
catch = { raise(Error.DataError(it)) },
|
||||
)
|
||||
}
|
||||
|
||||
private fun getQuotes(tokensIds: NonEmptySet<CryptoCurrency.ID>): Flow<Set<Quote>> {
|
||||
return quotesRepository.getQuotes(tokensIds, refresh)
|
||||
.catch { raise(Error.DataError(it)) }
|
||||
.onEmpty { raise(Error.EmptyQuotes) }
|
||||
.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
private fun getNetworksStatues(networks: NonEmptySet<Network.ID>): Flow<Set<NetworkStatus>> {
|
||||
return networksRepository.getNetworkStatuses(userWalletId, networks, refresh)
|
||||
.catch { raise(Error.DataError(it)) }
|
||||
.onEmpty { raise(Error.EmptyNetworksStatuses) }
|
||||
.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
sealed class Error {
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import com.tangem.domain.tokens.GetTokenListUseCase
|
|||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.TokensRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
|
@ -19,7 +19,7 @@ import kotlinx.coroutines.withContext
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class TokenListOperations<E>(
|
||||
private val tokensRepository: TokensRepository,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val userWalletId: UserWalletId,
|
||||
private val tokens: Set<CryptoCurrencyStatus>,
|
||||
|
|
@ -35,7 +35,7 @@ internal class TokenListOperations<E>(
|
|||
raise: Raise<E>,
|
||||
transform: (Error) -> E,
|
||||
) : this(
|
||||
tokensRepository = useCase.tokensRepository,
|
||||
currenciesRepository = useCase.currenciesRepository,
|
||||
networksRepository = useCase.networksRepository,
|
||||
userWalletId = userWalletId,
|
||||
tokens = tokens,
|
||||
|
|
@ -149,14 +149,14 @@ internal class TokenListOperations<E>(
|
|||
}
|
||||
|
||||
private fun getIsGrouped(): Flow<Boolean> {
|
||||
return tokensRepository.isTokensGrouped(userWalletId)
|
||||
return currenciesRepository.isTokensGrouped(userWalletId)
|
||||
.catch { raise(Error.DataError(it)) }
|
||||
.onEmpty { emit(value = false) }
|
||||
.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
private fun getIsSortedByBalance(): Flow<Boolean> {
|
||||
return tokensRepository.isTokensSortedByBalance(userWalletId)
|
||||
return currenciesRepository.isTokensSortedByBalance(userWalletId)
|
||||
.catch { raise(Error.DataError(it)) }
|
||||
.onEmpty { emit(value = false) }
|
||||
.flowOn(dispatchers.io)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow
|
|||
/**
|
||||
* Repository for everything related to the tokens of user wallet
|
||||
* */
|
||||
interface TokensRepository {
|
||||
interface CurrenciesRepository {
|
||||
|
||||
/**
|
||||
* Saves the given set of cryptocurrencies, along with the preferences for grouping and sorting, for a specific
|
||||
|
|
@ -17,6 +17,8 @@ interface TokensRepository {
|
|||
* @param currencies The set 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 com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If single-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
suspend fun saveTokens(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -30,8 +32,10 @@ interface TokensRepository {
|
|||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @return The primary cryptocurrency associated with the user wallet.
|
||||
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If multi-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
suspend fun getPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency
|
||||
suspend fun getSingleCurrencyWalletPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency
|
||||
|
||||
/**
|
||||
* Retrieves the set of cryptocurrencies within a multi-currency wallet.
|
||||
|
|
@ -39,14 +43,29 @@ interface TokensRepository {
|
|||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param refresh A boolean flag indicating whether the data should be refreshed.
|
||||
* @return A [Flow] emitting the set of cryptocurrencies associated with the user wallet.
|
||||
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If single-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
fun getMultiCurrencyWalletCurrencies(userWalletId: UserWalletId, refresh: Boolean): Flow<Set<CryptoCurrency>>
|
||||
|
||||
/**
|
||||
* Retrieves the cryptocurrency for a specific multi-currency user wallet.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param id The unique identifier of the cryptocurrency to be retrieved.
|
||||
* @return The cryptocurrency associated with the user wallet and ID.
|
||||
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If single-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
suspend fun getMultiCurrencyWalletCurrency(userWalletId: UserWalletId, id: CryptoCurrency.ID): CryptoCurrency
|
||||
|
||||
/**
|
||||
* Determines whether the tokens within a specific multi-currency user wallet are grouped.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @return A [Flow] emitting a boolean value indicating whether the tokens are grouped.
|
||||
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If single-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
fun isTokensGrouped(userWalletId: UserWalletId): Flow<Boolean>
|
||||
|
||||
|
|
@ -55,6 +74,8 @@ interface TokensRepository {
|
|||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @return A [Flow] emitting a boolean value indicating whether the tokens are sorted by balance.
|
||||
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If single-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
fun isTokensSortedByBalance(userWalletId: UserWalletId): Flow<Boolean>
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ import com.tangem.domain.core.error.DataError
|
|||
import com.tangem.domain.tokens.error.TokenListSortingError
|
||||
import com.tangem.domain.tokens.mock.MockTokens
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.repository.MockTokensRepository
|
||||
import com.tangem.domain.tokens.repository.MockCurrenciesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import junit.framework.TestCase.assertEquals
|
||||
|
|
@ -183,16 +183,16 @@ internal class ApplyTokenListSortingUseCaseTest {
|
|||
.sortedBy { Random.nextInt(0, MockTokens.tokens.size) }
|
||||
.toSet()
|
||||
|
||||
private fun getUseCase(tokensRepository: MockTokensRepository = getTokensRepository()) =
|
||||
private fun getUseCase(tokensRepository: MockCurrenciesRepository = getTokensRepository()) =
|
||||
ApplyTokenListSortingUseCase(
|
||||
tokensRepository = tokensRepository,
|
||||
currenciesRepository = tokensRepository,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
||||
private fun getTokensRepository(
|
||||
sortTokensResult: Either<DataError, Unit> = Unit.right(),
|
||||
tokens: Flow<Either<DataError, Set<CryptoCurrency>>> = flowOf(MockTokens.tokens.right()),
|
||||
): MockTokensRepository {
|
||||
return MockTokensRepository(sortTokensResult, MockTokens.token1.right(), tokens, emptyFlow(), emptyFlow())
|
||||
): MockCurrenciesRepository {
|
||||
return MockCurrenciesRepository(sortTokensResult, MockTokens.token1.right(), tokens, emptyFlow(), emptyFlow())
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import arrow.core.Either
|
|||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import com.tangem.domain.tokens.error.TokenError
|
||||
import com.tangem.domain.tokens.error.CurrencyError
|
||||
import com.tangem.domain.tokens.mock.MockNetworks
|
||||
import com.tangem.domain.tokens.mock.MockQuotes
|
||||
import com.tangem.domain.tokens.mock.MockTokens
|
||||
|
|
@ -13,9 +13,9 @@ import com.tangem.domain.tokens.model.CryptoCurrency
|
|||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.tokens.model.Quote
|
||||
import com.tangem.domain.tokens.repository.MockCurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.MockNetworksRepository
|
||||
import com.tangem.domain.tokens.repository.MockQuotesRepository
|
||||
import com.tangem.domain.tokens.repository.MockTokensRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import junit.framework.TestCase.assertEquals
|
||||
|
|
@ -47,7 +47,7 @@ internal class GetPrimaryCurrencyUseCaseTest {
|
|||
@Test
|
||||
fun `when token getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokenError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
val expectedResult = CurrencyError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
|
||||
val useCase = getUseCase(token = DataError.NetworkError.NoInternetConnection.left())
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ internal class GetPrimaryCurrencyUseCaseTest {
|
|||
@Test
|
||||
fun `when quotes getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokenError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
val expectedResult = CurrencyError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
|
||||
val useCase = getUseCase(quotes = flowOf(DataError.NetworkError.NoInternetConnection.left()))
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ internal class GetPrimaryCurrencyUseCaseTest {
|
|||
@Test
|
||||
fun `when networks statuses getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokenError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
val expectedResult = CurrencyError.DataError(DataError.NetworkError.NoInternetConnection).left()
|
||||
|
||||
val useCase = getUseCase(statuses = flowOf(DataError.NetworkError.NoInternetConnection.left()))
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ internal class GetPrimaryCurrencyUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun `when networks statuses flow is empty then error should be received`() = runTest {
|
||||
val expectedResult = TokenError.UnableToCreateToken.left()
|
||||
val expectedResult = CurrencyError.UnableToCreateCurrency.left()
|
||||
|
||||
val useCase = getUseCase(statuses = flowOf())
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ internal class GetPrimaryCurrencyUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun `when quotes flow is empty then error should be received`() = runTest {
|
||||
val expectedResult = TokenError.UnableToCreateToken.left()
|
||||
val expectedResult = CurrencyError.UnableToCreateCurrency.left()
|
||||
|
||||
val useCase = getUseCase(quotes = flowOf())
|
||||
|
||||
|
|
@ -154,7 +154,7 @@ internal class GetPrimaryCurrencyUseCaseTest {
|
|||
statuses: Flow<Either<DataError, Set<NetworkStatus>>> = flowOf(MockNetworks.verifiedNetworksStatuses.right()),
|
||||
) = GetPrimaryCurrencyUseCase(
|
||||
dispatchers = dispatchers,
|
||||
tokensRepository = MockTokensRepository(
|
||||
currenciesRepository = MockCurrenciesRepository(
|
||||
sortTokensResult = Unit.right(),
|
||||
token = token,
|
||||
tokens = flowOf(),
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ import com.tangem.domain.tokens.model.CryptoCurrency
|
|||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.tokens.model.Quote
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.repository.MockCurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.MockNetworksRepository
|
||||
import com.tangem.domain.tokens.repository.MockQuotesRepository
|
||||
import com.tangem.domain.tokens.repository.MockTokensRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import junit.framework.TestCase.assertEquals
|
||||
|
|
@ -326,7 +326,7 @@ internal class GetTokenListUseCaseTest {
|
|||
isSortedByBalance: Flow<Either<DataError, Boolean>> = flowOf(MockTokenLists.isSortedByBalance.right()),
|
||||
) = GetTokenListUseCase(
|
||||
dispatchers = dispatchers,
|
||||
tokensRepository = MockTokensRepository(
|
||||
currenciesRepository = MockCurrenciesRepository(
|
||||
sortTokensResult = Unit.right(),
|
||||
token = MockTokens.token1.right(),
|
||||
tokens = tokens,
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
internal class MockTokensRepository(
|
||||
internal class MockCurrenciesRepository(
|
||||
private val sortTokensResult: Either<DataError, Unit>,
|
||||
private val token: Either<DataError, CryptoCurrency>,
|
||||
private val tokens: Flow<Either<DataError, Set<CryptoCurrency>>>,
|
||||
private val isGrouped: Flow<Either<DataError, Boolean>>,
|
||||
private val isSortedByBalance: Flow<Either<DataError, Boolean>>,
|
||||
) : TokensRepository {
|
||||
) : CurrenciesRepository {
|
||||
|
||||
var tokensIdsAfterSortingApply: Set<CryptoCurrency>? = null
|
||||
private set
|
||||
|
|
@ -38,7 +38,7 @@ internal class MockTokensRepository(
|
|||
isTokensSortedByBalanceAfterSortingApply = isSortedByBalance
|
||||
}
|
||||
|
||||
override suspend fun getPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency {
|
||||
override suspend fun getSingleCurrencyWalletPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency {
|
||||
return token.getOrElse { e -> throw e }
|
||||
}
|
||||
|
||||
|
|
@ -49,6 +49,17 @@ internal class MockTokensRepository(
|
|||
return tokens.map { it.getOrElse { e -> throw e } }
|
||||
}
|
||||
|
||||
override suspend fun getMultiCurrencyWalletCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
): CryptoCurrency {
|
||||
val token = token.getOrElse { e -> throw e }
|
||||
|
||||
require(token.id == id)
|
||||
|
||||
return token
|
||||
}
|
||||
|
||||
override fun isTokensGrouped(userWalletId: UserWalletId): Flow<Boolean> {
|
||||
return isGrouped.map { it.getOrElse { e -> throw e } }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue