Updated on 2026-08-14

This commit is contained in:
Tangem 2024-08-19 13:32:09 +05:00
commit e7bbd950dd
18 changed files with 217 additions and 158 deletions

View file

@ -376,15 +376,12 @@ class DefaultWalletManagersFacade(
return walletManagersStore.getAllSync(userWalletId)
}
@Deprecated(
"Use NetworkAddress from CryptoCurrencyStatus",
ReplaceWith("cryptoCurrencyStatus.value.networkAddress"),
)
override suspend fun getAddress(userWalletId: UserWalletId, network: Network): List<Address> {
return getAddresses(userWalletId, network).sortedBy { it.type }
override suspend fun getDefaultAddress(userWalletId: UserWalletId, network: Network): String? {
return getAddresses(userWalletId, network)
.firstOrNull { it.type == AddressType.Default }
?.value
}
@Deprecated("Use NetworkAddress from CryptoCurrencyStatus")
override suspend fun getAddresses(userWalletId: UserWalletId, network: Network): Set<Address> {
val manager = getOrCreateWalletManager(
userWalletId = userWalletId,

View file

@ -117,20 +117,18 @@ interface WalletManagersFacade {
suspend fun getStoredWalletManagers(userWalletId: UserWalletId): List<WalletManager>
/**
* Returns ordered list of addresses for selected wallet for given currency
* Returns default network address for selected wallet in given network
*
* @param userWalletId selected wallet id
* @param network network of currency
*/
@Deprecated("Use NetworkAddress from CryptoCurrencyStatus")
suspend fun getAddress(userWalletId: UserWalletId, network: Network): List<Address>
suspend fun getDefaultAddress(userWalletId: UserWalletId, network: Network): String?
/** Returns list of all addresses for all currencies in selected wallet
*
* @param userWalletId selected wallet id
* @param network required to create wallet manager
*/
@Deprecated("Use NetworkAddress from CryptoCurrencyStatus")
suspend fun getAddresses(userWalletId: UserWalletId, network: Network): Set<Address>
/**

View file

@ -6,7 +6,7 @@ import arrow.core.raise.either
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.model.CryptoCurrencyAddress
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
class FetchStakingYieldBalanceUseCase(
@ -16,7 +16,7 @@ class FetchStakingYieldBalanceUseCase(
suspend operator fun invoke(
userWalletId: UserWalletId,
address: CryptoCurrencyAddress,
cryptoCurrency: CryptoCurrency,
refresh: Boolean = false,
): Either<StakingError, Unit> {
return either {
@ -24,7 +24,7 @@ class FetchStakingYieldBalanceUseCase(
block = {
stakingRepository.fetchSingleYieldBalance(
userWalletId = userWalletId,
address = address,
cryptoCurrency = cryptoCurrency,
refresh = refresh,
)
},

View file

@ -8,7 +8,7 @@ import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.model.stakekit.YieldBalance
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.model.CryptoCurrencyAddress
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.map
@ -20,11 +20,11 @@ class GetStakingYieldBalanceUseCase(
operator fun invoke(
userWalletId: UserWalletId,
address: CryptoCurrencyAddress,
cryptoCurrency: CryptoCurrency,
): EitherFlow<StakingError, YieldBalance> {
return stakingRepository.getSingleYieldBalanceFlow(
userWalletId = userWalletId,
address = address,
cryptoCurrency = cryptoCurrency,
).map<YieldBalance, Either<StakingError, YieldBalance>> { it.right() }
.catch { emit(stakingErrorResolver.resolve(it).left()) }
}

View file

@ -15,7 +15,6 @@ import com.tangem.domain.staking.model.stakekit.transaction.ActionParams
import com.tangem.domain.staking.model.stakekit.transaction.StakingGasEstimate
import com.tangem.domain.staking.model.stakekit.transaction.StakingTransaction
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyAddress
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow
@ -38,33 +37,33 @@ interface StakingRepository {
suspend fun fetchSingleYieldBalance(
userWalletId: UserWalletId,
address: CryptoCurrencyAddress,
cryptoCurrency: CryptoCurrency,
refresh: Boolean = false,
)
fun getSingleYieldBalanceFlow(userWalletId: UserWalletId, address: CryptoCurrencyAddress): Flow<YieldBalance>
fun getSingleYieldBalanceFlow(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Flow<YieldBalance>
suspend fun getSingleYieldBalanceSync(userWalletId: UserWalletId, address: CryptoCurrencyAddress): YieldBalance
suspend fun getSingleYieldBalanceSync(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): YieldBalance
suspend fun fetchMultiYieldBalance(
userWalletId: UserWalletId,
addresses: List<CryptoCurrencyAddress>,
cryptoCurrencies: List<CryptoCurrency>,
refresh: Boolean = false,
)
fun getMultiYieldBalanceFlow(
userWalletId: UserWalletId,
addresses: List<CryptoCurrencyAddress>,
cryptoCurrencies: List<CryptoCurrency>,
): Flow<YieldBalanceList>
fun getMultiYieldBalanceLce(
userWalletId: UserWalletId,
addresses: List<CryptoCurrencyAddress>,
cryptoCurrencies: List<CryptoCurrency>,
): LceFlow<Throwable, YieldBalanceList>
suspend fun getMultiYieldBalanceSync(
userWalletId: UserWalletId,
addresses: List<CryptoCurrencyAddress>,
cryptoCurrencies: List<CryptoCurrency>,
): YieldBalanceList
suspend fun createAction(userWalletId: UserWalletId, network: Network, params: ActionParams): StakingAction

View file

@ -44,6 +44,7 @@ class FetchCardTokenListUseCase(
val yieldBalances = async {
fetchYieldBalances(
userWalletId = userWalletId,
currencies = currencies,
refresh = refresh,
)
}
@ -77,10 +78,13 @@ class FetchCardTokenListUseCase(
)
}
private suspend fun fetchYieldBalances(userWalletId: UserWalletId, refresh: Boolean) {
val networkAddresses = networksRepository.getNetworkAddresses(userWalletId)
private suspend fun fetchYieldBalances(
userWalletId: UserWalletId,
currencies: List<CryptoCurrency>,
refresh: Boolean,
) {
catch(
block = { stakingRepository.fetchMultiYieldBalance(userWalletId, networkAddresses, refresh) },
block = { stakingRepository.fetchMultiYieldBalance(userWalletId, currencies, refresh) },
catch = { /* Ignore error */ },
)
}

View file

@ -4,6 +4,7 @@ import arrow.core.Either
import arrow.core.raise.Raise
import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
@ -29,6 +30,7 @@ class FetchCurrencyStatusUseCase(
private val currenciesRepository: CurrenciesRepository,
private val networksRepository: NetworksRepository,
private val quotesRepository: QuotesRepository,
private val stakingRepository: StakingRepository,
) {
/**
@ -80,8 +82,11 @@ class FetchCurrencyStatusUseCase(
val fetchQuote = async {
fetchQuote(currency.id, refresh)
}
val fetchStakingBalance = async {
fetchStakingBalance(userWalletId, currency, refresh)
}
awaitAll(fetchStatus, fetchQuote)
awaitAll(fetchStatus, fetchQuote, fetchStakingBalance)
}
private suspend fun Raise<CurrencyStatusError>.getCurrency(
@ -122,4 +127,16 @@ class FetchCurrencyStatusUseCase(
raise(CurrencyStatusError.DataError(it))
}
}
private suspend fun Raise<CurrencyStatusError>.fetchStakingBalance(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
refresh: Boolean,
) {
catch(
block = { stakingRepository.fetchSingleYieldBalance(userWalletId, cryptoCurrency, refresh) },
) {
raise(CurrencyStatusError.DataError(it))
}
}
}

View file

@ -69,11 +69,10 @@ internal class CurrenciesStatusesLceOperations(
val (networks, currenciesIds) = getIds(nonEmptyCurrencies)
val addresses = networksRepository.getNetworkAddresses(userWalletId)
combine(
getQuotes(currenciesIds),
getNetworksStatuses(userWalletId, networks),
getYieldBalances(userWalletId, addresses),
getYieldBalances(userWalletId, nonEmptyCurrencies),
) { maybeQuotes, maybeNetworksStatuses, maybeYieldBalances ->
val statuses = createCurrenciesStatuses(
currencies = nonEmptyCurrencies,
@ -196,11 +195,11 @@ internal class CurrenciesStatusesLceOperations(
private fun getYieldBalances(
userWalletId: UserWalletId,
addresses: List<CryptoCurrencyAddress>,
cryptoCurrencies: List<CryptoCurrency>,
): LceFlow<TokenListError, YieldBalanceList> {
return stakingRepository.getMultiYieldBalanceLce(
userWalletId = userWalletId,
addresses = addresses,
cryptoCurrencies = cryptoCurrencies,
).map { maybeBalances ->
maybeBalances.mapError { TokenListError.DataError(it) }
}

View file

@ -11,7 +11,6 @@ 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 kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
// FIXME: Refactor - [REDACTED_JIRA]
@ -35,7 +34,7 @@ internal class CurrenciesStatusesOperations(
val quotes = quotesRepository.getQuotesSync(currenciesIds, false).right()
val networkStatuses =
networksRepository.getNetworkStatusesSync(userWalletId, networks, false).right()
val yieldBalances = getYieldBalancesSync()
val yieldBalances = getYieldBalancesSync(nonEmptyCurrencies)
return createCurrenciesStatuses(nonEmptyCurrencies, quotes, networkStatuses, yieldBalances)
},
@ -147,7 +146,7 @@ internal class CurrenciesStatusesOperations(
val currenciesFlow = combine(
getQuotes(currenciesIds),
getNetworksStatuses(networks),
getYieldBalances(),
getYieldBalances(nonEmptyCurrencies),
) { maybeQuotes, maybeNetworksStatuses, maybeYieldBalances ->
createCurrenciesStatuses(nonEmptyCurrencies, maybeQuotes, maybeNetworksStatuses, maybeYieldBalances)
}
@ -385,25 +384,23 @@ internal class CurrenciesStatusesOperations(
.onEmpty { emit(Error.EmptyNetworksStatuses.left()) }
}
@OptIn(ExperimentalCoroutinesApi::class)
private fun getYieldBalances(): EitherFlow<Error, YieldBalanceList> {
return networksRepository.getNetworkAddressesFlow(userWalletId).flatMapLatest { addresses ->
stakingRepository.getMultiYieldBalanceFlow(
userWalletId = userWalletId,
addresses = addresses,
).map<YieldBalanceList, Either<Error, YieldBalanceList>> { it.right() }
.catch { emit(Error.DataError(it).left()) }
.onEmpty { emit(Error.EmptyYieldBalances.left()) }
}
private fun getYieldBalances(cryptoCurrencies: List<CryptoCurrency>): Flow<Either<Error, YieldBalanceList>> {
return stakingRepository.getMultiYieldBalanceFlow(
userWalletId = userWalletId,
cryptoCurrencies = cryptoCurrencies,
).map<YieldBalanceList, Either<Error, YieldBalanceList>> { it.right() }
.catch { emit(Error.DataError(it).left()) }
.onEmpty { emit(Error.EmptyYieldBalances.left()) }
}
private suspend fun getYieldBalancesSync(): Either<Error.EmptyYieldBalances, YieldBalanceList> {
private suspend fun getYieldBalancesSync(
cryptoCurrencies: List<CryptoCurrency>,
): Either<Error.EmptyYieldBalances, YieldBalanceList> {
return catch(
block = {
val networkAddresses = networksRepository.getNetworkAddresses(userWalletId)
stakingRepository.getMultiYieldBalanceSync(
userWalletId,
networkAddresses,
cryptoCurrencies,
).right()
},
catch = {
@ -417,10 +414,9 @@ internal class CurrenciesStatusesOperations(
): Either<Error.EmptyYieldBalances, YieldBalance> {
return catch(
block = {
val address = networksRepository.getNetworkAddress(userWalletId, cryptoCurrency)
stakingRepository.getSingleYieldBalanceSync(
userWalletId,
address,
cryptoCurrency,
).right()
},
catch = {
@ -429,19 +425,13 @@ internal class CurrenciesStatusesOperations(
)
}
@OptIn(ExperimentalCoroutinesApi::class)
private fun getYieldBalance(cryptoCurrency: CryptoCurrency): EitherFlow<Error, YieldBalance> {
return networksRepository.getNetworkAddressFlow(
userWalletId,
cryptoCurrency,
).flatMapLatest { address ->
stakingRepository.getSingleYieldBalanceFlow(
userWalletId = userWalletId,
address = address,
).map<YieldBalance, Either<Error, YieldBalance>> { it.right() }
.catch { emit(Error.DataError(it).left()) }
.onEmpty { emit(Error.EmptyYieldBalances.left()) }
}
return stakingRepository.getSingleYieldBalanceFlow(
userWalletId = userWalletId,
cryptoCurrency = cryptoCurrency,
).map<YieldBalance, Either<Error, YieldBalance>> { it.right() }
.catch { emit(Error.DataError(it).left()) }
.onEmpty { emit(Error.EmptyYieldBalances.left()) }
}
private fun getIds(

View file

@ -16,7 +16,6 @@ import com.tangem.domain.staking.model.stakekit.action.StakingActionType
import com.tangem.domain.staking.model.stakekit.transaction.*
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyAddress
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow
@ -118,7 +117,7 @@ class MockStakingRepository : StakingRepository {
override suspend fun fetchSingleYieldBalance(
userWalletId: UserWalletId,
address: CryptoCurrencyAddress,
cryptoCurrency: CryptoCurrency,
refresh: Boolean,
) {
/* no-op */
@ -126,19 +125,19 @@ class MockStakingRepository : StakingRepository {
override fun getSingleYieldBalanceFlow(
userWalletId: UserWalletId,
address: CryptoCurrencyAddress,
cryptoCurrency: CryptoCurrency,
): Flow<YieldBalance> = channelFlow {
send(YieldBalance.Error)
}
override suspend fun getSingleYieldBalanceSync(
userWalletId: UserWalletId,
address: CryptoCurrencyAddress,
cryptoCurrency: CryptoCurrency,
): YieldBalance = YieldBalance.Error
override suspend fun fetchMultiYieldBalance(
userWalletId: UserWalletId,
addresses: List<CryptoCurrencyAddress>,
cryptoCurrencies: List<CryptoCurrency>,
refresh: Boolean,
) {
/* no-op */
@ -146,7 +145,7 @@ class MockStakingRepository : StakingRepository {
override fun getMultiYieldBalanceFlow(
userWalletId: UserWalletId,
addresses: List<CryptoCurrencyAddress>,
cryptoCurrencies: List<CryptoCurrency>,
): Flow<YieldBalanceList> = channelFlow {
send(
YieldBalanceList.Data(
@ -157,7 +156,7 @@ class MockStakingRepository : StakingRepository {
override fun getMultiYieldBalanceLce(
userWalletId: UserWalletId,
addresses: List<CryptoCurrencyAddress>,
cryptoCurrencies: List<CryptoCurrency>,
): LceFlow<Throwable, YieldBalanceList> = lceFlow {
send(
YieldBalanceList.Data(
@ -168,7 +167,7 @@ class MockStakingRepository : StakingRepository {
override suspend fun getMultiYieldBalanceSync(
userWalletId: UserWalletId,
addresses: List<CryptoCurrencyAddress>,
cryptoCurrencies: List<CryptoCurrency>,
): YieldBalanceList = YieldBalanceList.Data(
balances = listOf(YieldBalance.Error),
)