diff --git a/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt b/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt index 7cee3bcfd9..10c14744b2 100644 --- a/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt @@ -1,48 +1,49 @@ package com.tangem.tap.domain import com.tangem.common.services.Result +import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.domain.common.ThrottlerWithValues -import com.tangem.datasource.api.tangemTech.TangemTechService import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.store +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.withContext import java.math.BigDecimal -//TODO: refactoring: move to domain -class RatesRepository { - - private val tangemTechService: TangemTechService - get() = store.state.domainNetworks.tangemTechService - +class RatesRepository( + private val tangemTechApi: TangemTechApi, + private val dispatchers: CoroutineDispatcherProvider, +) { private val throttler = ThrottlerWithValues?>(60000) - suspend fun loadFiatRate(currencyId: String, coinsList: List): Result { -// get and submit previous result of equivalents. - val throttledResult = coinsList.filter { throttler.isStillThrottled(it) }.map { - Pair(it, throttler.geValue(it)) - } - - val currenciesToUpdate = coinsList.filter { !throttler.isStillThrottled(it) } - val coinIds = currenciesToUpdate.mapNotNull { it.coinId }.distinct() - if (coinIds.isEmpty()) return handleFiatRatesResult(throttledResult.toMap()) - - return when (val result = tangemTechService.rates(currencyId, coinIds)) { - is Result.Success -> { - val ratesResultList: Map> = result.data.rates.mapValues { - Result.Success(it.value.toBigDecimal()) - } - val updatedCurrencies = throttledResult.toMap().toMutableMap() - coinsList.forEach { currency -> - ratesResultList[currency.coinId]?.let { - updatedCurrencies[currency] = it - throttler.updateThrottlingTo(currency) - throttler.setValue(currency, it) - } - } - handleFiatRatesResult(updatedCurrencies) + suspend fun loadFiatRate(currencyId: String, coinsList: List): Result = + withContext(dispatchers.io) { + // get and submit previous result of equivalents. + val throttledResult = coinsList.filter { throttler.isStillThrottled(it) }.map { + Pair(it, throttler.geValue(it)) } - is Result.Failure -> Result.Failure(result.error) + + val currenciesToUpdate = coinsList.filter { !throttler.isStillThrottled(it) } + val coinIds = currenciesToUpdate.mapNotNull { it.coinId }.distinct() + if (coinIds.isEmpty()) return@withContext handleFiatRatesResult(throttledResult.toMap()) + + runCatching { tangemTechApi.getRates(currencyId.lowercase(), coinIds.joinToString(",")) } + .onSuccess { response -> + val ratesResultList: Map> = response.rates.mapValues { + Result.Success(it.value.toBigDecimal()) + } + val updatedCurrencies = throttledResult.toMap().toMutableMap() + coinsList.forEach { currency -> + ratesResultList[currency.coinId]?.let { + updatedCurrencies[currency] = it + throttler.updateThrottlingTo(currency) + throttler.setValue(currency, it) + } + } + return@withContext handleFiatRatesResult(updatedCurrencies) + } + .onFailure { Result.Failure(it) } + + throw IllegalStateException("Unreachable code because runCatching must return result") } - } private fun handleFiatRatesResult(rates: Map?>): Result.Success { val success = mutableMapOf() diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index ea26d15848..12ee35a3a9 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -36,6 +36,7 @@ import com.tangem.tap.store import com.tangem.tap.tangemSdkManager import com.tangem.tap.userTokensRepository import com.tangem.tap.walletStoresManager +import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import timber.log.Timber @@ -43,7 +44,14 @@ import timber.log.Timber class TapWalletManager { val walletManagerFactory: WalletManagerFactory by lazy { WalletManagerFactory(blockchainSdkConfig) } - val rates: RatesRepository = RatesRepository() + + // TODO("After adding DI") get dependencies by DI + val rates: RatesRepository by lazy { + RatesRepository( + tangemTechApi = store.state.domainNetworks.tangemTechService.api, + dispatchers = AppCoroutineDispatcherProvider(), + ) + } private val blockchainSdkConfig by lazy { store.state.globalState.configManager?.config?.blockchainSdkConfig ?: BlockchainSdkConfig() diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/di/RepositoryProvider.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/di/RepositoryProvider.kt index 7fc7ba38e7..d89d4ea6aa 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/di/RepositoryProvider.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/di/RepositoryProvider.kt @@ -8,6 +8,7 @@ import com.tangem.tap.domain.walletStores.repository.WalletStoresRepository import com.tangem.tap.domain.walletStores.repository.implementation.DefaultWalletAmountsRepository import com.tangem.tap.domain.walletStores.repository.implementation.DefaultWalletManagersRepository import com.tangem.tap.domain.walletStores.repository.implementation.DefaultWalletStoresRepository +import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider fun WalletStoresRepository.Companion.provideDefaultImplementation(): WalletStoresRepository { return DefaultWalletStoresRepository() @@ -22,5 +23,9 @@ fun WalletManagersRepository.Companion.provideDefaultImplementation( fun WalletAmountsRepository.Companion.provideDefaultImplementation( tangemTechService: TangemTechService, ): WalletAmountsRepository { - return DefaultWalletAmountsRepository(tangemTechService) + // TODO("After adding DI") get dependencies by DI + return DefaultWalletAmountsRepository( + tangemTechApi = tangemTechService.api, + dispatchers = AppCoroutineDispatcherProvider(), + ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt index 640c08fe67..0c7b19fb4b 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt @@ -14,8 +14,7 @@ import com.tangem.common.flatMap import com.tangem.common.flatMapOnFailure import com.tangem.common.fold import com.tangem.common.map -import com.tangem.common.services.Result -import com.tangem.datasource.api.tangemTech.TangemTechService +import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.util.UserWalletId import com.tangem.tap.common.entities.FiatCurrency @@ -34,10 +33,12 @@ import com.tangem.tap.domain.walletStores.repository.implementation.utils.update import com.tangem.tap.domain.walletStores.repository.implementation.utils.updateWithUnreachable import com.tangem.tap.domain.walletStores.storage.WalletManagerStorage import com.tangem.tap.domain.walletStores.storage.WalletStoresStorage +import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.PendingTransactionType import com.tangem.tap.features.wallet.models.filterByCoin import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.network.NetworkConnectivity +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -47,7 +48,8 @@ import timber.log.Timber import java.math.BigDecimal internal class DefaultWalletAmountsRepository( - private val tangemTechService: TangemTechService, + private val tangemTechApi: TangemTechApi, + private val dispatchers: CoroutineDispatcherProvider, ) : WalletAmountsRepository { private val walletStoresStorage = WalletStoresStorage private val walletManagersStorage = WalletManagerStorage @@ -119,39 +121,31 @@ internal class DefaultWalletAmountsRepository( val coinsIds = currencies.mapNotNull { it.coinId }.distinct().toList() - val fiatRatesResult = withContext(Dispatchers.IO) { - tangemTechService.rates( - currency = fiatCurrency.code, - ids = coinsIds, - ) - } + return withContext(dispatchers.io) { + runCatching { tangemTechApi.getRates(fiatCurrency.code.lowercase(), coinsIds.joinToString(",")) } + .onSuccess { + updateWalletStoresWithFiatRates(walletStores = walletStores, fiatRates = it.rates) + return@withContext CompletionResult.Success(Unit) + } + .onFailure { + val error = WalletStoresError.FetchFiatRatesError( + currencies = currencies.map(Currency::currencySymbol).toList(), + cause = it, + ) - return when (fiatRatesResult) { - is Result.Success -> { - updateWalletStoresWithFiatRates( - walletStores = walletStores, - fiatRates = fiatRatesResult.data.rates, - ) - - CompletionResult.Success(Unit) - } - is Result.Failure -> { - val error = WalletStoresError.FetchFiatRatesError( - currencies = currencies.map { it.currencySymbol }.toList(), - cause = fiatRatesResult.error, - ) - - Timber.e( - error, - """ + Timber.e( + error, + """ Unable to fetch fiat rates |- User wallets ids: $walletsIds |- Coins ids: $coinsIds """.trimIndent(), - ) + ) - CompletionResult.Failure(error) - } + return@withContext CompletionResult.Failure(error) + } + + throw IllegalStateException("Unreachable code because runCatching must return result") } } diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt index 2dfe10dd02..e42f069cac 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt @@ -26,7 +26,7 @@ interface TangemTechApi { ): CoinsResponse @GET("rates") - suspend fun rates( + suspend fun getRates( @Query("currencyId") currencyId: String, @Query("coinIds") coinIds: String, ): RatesResponse diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt index 136a9abcf7..f1d66ce518 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt @@ -41,15 +41,6 @@ class TangemTechService( } } - suspend fun rates( - currency: String, - ids: List, - ): Result = withContext(Dispatchers.IO) { - performRequest { - api.rates(currency.lowercase(), ids.joinToString(",")) - } - } - fun addHeaderInterceptors(interceptors: List) { headerInterceptors.removeAll(interceptors) headerInterceptors.addAll(interceptors)