Updated on 2026-08-14
This commit is contained in:
commit
00805c1380
268 changed files with 6515 additions and 1380 deletions
|
|
@ -33,6 +33,7 @@ dependencies {
|
|||
|
||||
// region Others dependencies
|
||||
implementation(deps.kotlin.coroutines)
|
||||
implementation(deps.jodatime)
|
||||
implementation(deps.moshi)
|
||||
implementation(deps.moshi.kotlin)
|
||||
implementation(deps.timber)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.blockchainsdk.compatibility.applyL2Compatibility
|
|||
import com.tangem.blockchainsdk.compatibility.getTokenIdIfL2Network
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.common.cache.CacheRegistry
|
||||
import com.tangem.data.common.currency.CryptoCurrencyFactory
|
||||
import com.tangem.data.common.currency.getNetwork
|
||||
import com.tangem.data.common.utils.retryOnError
|
||||
|
|
@ -13,8 +14,10 @@ import com.tangem.data.markets.converters.*
|
|||
import com.tangem.datasource.api.common.response.ApiResponseError
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.markets.TangemTechMarketsApi
|
||||
import com.tangem.datasource.api.markets.models.response.TokenMarketExchangesResponse
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi.Companion.marketsQuoteFields
|
||||
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.markets.*
|
||||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
|
|
@ -27,12 +30,15 @@ import kotlinx.coroutines.withContext
|
|||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class DefaultMarketsTokenRepository(
|
||||
private val marketsApi: TangemTechMarketsApi,
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val userWalletsStore: UserWalletsStore,
|
||||
private val dispatcherProvider: CoroutineDispatcherProvider,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val cacheRegistry: CacheRegistry,
|
||||
private val tokenExchangesStore: RuntimeStateStore<List<TokenMarketExchangesResponse.Exchange>>,
|
||||
) : MarketsTokenRepository {
|
||||
|
||||
private fun createTokenMarketsFetcher(firstBatchSize: Int, nextBatchSize: Int) = LimitOffsetBatchFetcher(
|
||||
|
|
@ -266,9 +272,13 @@ internal class DefaultMarketsTokenRepository(
|
|||
|
||||
override suspend fun getTokenExchanges(tokenId: String): List<TokenMarketExchange> {
|
||||
return withContext(dispatcherProvider.io) {
|
||||
val response = marketsApi.getCoinExchanges(coinId = tokenId).getOrThrow()
|
||||
cacheRegistry.invokeOnExpire(key = "coins/$tokenId/exchanges", skipCache = false) {
|
||||
val response = marketsApi.getCoinExchanges(coinId = tokenId).getOrThrow()
|
||||
|
||||
TokenMarketExchangeConverter.convertList(input = response.exchanges)
|
||||
tokenExchangesStore.store(value = response.exchanges)
|
||||
}
|
||||
|
||||
TokenMarketExchangeConverter.convertList(input = tokenExchangesStore.get().value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package com.tangem.data.markets.di
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.data.common.cache.CacheRegistry
|
||||
import com.tangem.data.markets.DefaultMarketsTokenRepository
|
||||
import com.tangem.datasource.api.markets.TangemTechMarketsApi
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -25,6 +27,7 @@ internal object MarketsDataModule {
|
|||
userWalletsStore: UserWalletsStore,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
analyticsEventHandler: AnalyticsEventHandler,
|
||||
cacheRegistry: CacheRegistry,
|
||||
): MarketsTokenRepository {
|
||||
return DefaultMarketsTokenRepository(
|
||||
marketsApi = marketsApi,
|
||||
|
|
@ -32,6 +35,8 @@ internal object MarketsDataModule {
|
|||
dispatcherProvider = dispatchers,
|
||||
userWalletsStore = userWalletsStore,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
cacheRegistry = cacheRegistry,
|
||||
tokenExchangesStore = RuntimeStateStore(defaultValue = emptyList()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,19 +4,29 @@ import com.tangem.data.onramp.converters.CountryConverter
|
|||
import com.tangem.data.onramp.converters.CurrencyConverter
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.onramp.OnrampApi
|
||||
import com.tangem.datasource.api.onramp.models.response.model.OnrampCountryDTO
|
||||
import com.tangem.datasource.api.onramp.models.response.model.OnrampCurrencyDTO
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.datasource.local.preferences.utils.getObject
|
||||
import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
|
||||
import com.tangem.datasource.local.preferences.utils.storeObject
|
||||
import com.tangem.domain.onramp.model.OnrampCountry
|
||||
import com.tangem.domain.onramp.model.OnrampCurrency
|
||||
import com.tangem.domain.onramp.repositories.OnrampRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
internal class DefaultOnrampRepository(
|
||||
private val onrampApi: OnrampApi,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
) : OnrampRepository {
|
||||
|
||||
private val currencyConverter = CurrencyConverter()
|
||||
private val countryConverter = CountryConverter()
|
||||
private val countryConverter = CountryConverter(currencyConverter)
|
||||
|
||||
override suspend fun getCurrencies(): List<OnrampCurrency> = withContext(dispatchers.io) {
|
||||
onrampApi.getCurrencies()
|
||||
|
|
@ -29,4 +39,48 @@ internal class DefaultOnrampRepository(
|
|||
.getOrThrow()
|
||||
.map(countryConverter::convert)
|
||||
}
|
||||
|
||||
override suspend fun getCountryByIp(): OnrampCountry = withContext(dispatchers.io) {
|
||||
onrampApi.getCountryByIp()
|
||||
.getOrThrow()
|
||||
.let(countryConverter::convert)
|
||||
}
|
||||
|
||||
override suspend fun saveDefaultCurrency(currency: OnrampCurrency) = withContext(dispatchers.io) {
|
||||
appPreferencesStore.storeObject<OnrampCurrencyDTO>(
|
||||
key = PreferencesKeys.ONRAMP_DEFAULT_CURRENCY,
|
||||
value = currencyConverter.convertBack(currency),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getDefaultCurrencySync(): OnrampCurrency? = withContext(dispatchers.io) {
|
||||
appPreferencesStore
|
||||
.getObjectSyncOrNull<OnrampCurrencyDTO>(PreferencesKeys.ONRAMP_DEFAULT_CURRENCY)
|
||||
?.let(currencyConverter::convert)
|
||||
}
|
||||
|
||||
override fun getDefaultCurrency(): Flow<OnrampCurrency?> {
|
||||
return appPreferencesStore
|
||||
.getObject<OnrampCurrencyDTO>(PreferencesKeys.ONRAMP_DEFAULT_CURRENCY)
|
||||
.map { it?.let(currencyConverter::convert) }
|
||||
}
|
||||
|
||||
override suspend fun saveDefaultCountry(country: OnrampCountry) = withContext(dispatchers.io) {
|
||||
appPreferencesStore.storeObject<OnrampCountryDTO>(
|
||||
key = PreferencesKeys.ONRAMP_DEFAULT_COUNTRY,
|
||||
value = countryConverter.convertBack(country),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getDefaultCountrySync(): OnrampCountry? = withContext(dispatchers.io) {
|
||||
appPreferencesStore
|
||||
.getObjectSyncOrNull<OnrampCountryDTO>(PreferencesKeys.ONRAMP_DEFAULT_COUNTRY)
|
||||
?.let(countryConverter::convert)
|
||||
}
|
||||
|
||||
override fun getDefaultCountry(): Flow<OnrampCountry?> {
|
||||
return appPreferencesStore
|
||||
.getObject<OnrampCountryDTO>(PreferencesKeys.ONRAMP_DEFAULT_COUNTRY)
|
||||
.map { it?.let(countryConverter::convert) }
|
||||
}
|
||||
}
|
||||
|
|
@ -2,13 +2,14 @@ package com.tangem.data.onramp.converters
|
|||
|
||||
import com.tangem.datasource.api.onramp.models.response.model.OnrampCountryDTO
|
||||
import com.tangem.domain.onramp.model.OnrampCountry
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.converter.TwoWayConverter
|
||||
|
||||
internal class CountryConverter : Converter<OnrampCountryDTO, OnrampCountry> {
|
||||
|
||||
private val currencyConverter = CurrencyConverter()
|
||||
internal class CountryConverter(
|
||||
private val currencyConverter: CurrencyConverter,
|
||||
) : TwoWayConverter<OnrampCountryDTO, OnrampCountry> {
|
||||
|
||||
override fun convert(value: OnrampCountryDTO) = OnrampCountry(
|
||||
id = "${value.alpha3}-${value.name}",
|
||||
name = value.name,
|
||||
code = value.code,
|
||||
image = value.image,
|
||||
|
|
@ -17,4 +18,14 @@ internal class CountryConverter : Converter<OnrampCountryDTO, OnrampCountry> {
|
|||
defaultCurrency = currencyConverter.convert(value.defaultCurrency),
|
||||
onrampAvailable = value.onrampAvailable,
|
||||
)
|
||||
|
||||
override fun convertBack(value: OnrampCountry): OnrampCountryDTO = OnrampCountryDTO(
|
||||
name = value.name,
|
||||
code = value.code,
|
||||
image = value.image,
|
||||
alpha3 = value.alpha3,
|
||||
continent = value.continent,
|
||||
defaultCurrency = currencyConverter.convertBack(value.defaultCurrency),
|
||||
onrampAvailable = value.onrampAvailable,
|
||||
)
|
||||
}
|
||||
|
|
@ -2,9 +2,9 @@ package com.tangem.data.onramp.converters
|
|||
|
||||
import com.tangem.datasource.api.onramp.models.response.model.OnrampCurrencyDTO
|
||||
import com.tangem.domain.onramp.model.OnrampCurrency
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.converter.TwoWayConverter
|
||||
|
||||
internal class CurrencyConverter : Converter<OnrampCurrencyDTO, OnrampCurrency> {
|
||||
internal class CurrencyConverter : TwoWayConverter<OnrampCurrencyDTO, OnrampCurrency> {
|
||||
|
||||
override fun convert(value: OnrampCurrencyDTO) = OnrampCurrency(
|
||||
name = value.name,
|
||||
|
|
@ -12,4 +12,11 @@ internal class CurrencyConverter : Converter<OnrampCurrencyDTO, OnrampCurrency>
|
|||
image = value.image,
|
||||
precision = value.precision,
|
||||
)
|
||||
|
||||
override fun convertBack(value: OnrampCurrency): OnrampCurrencyDTO = OnrampCurrencyDTO(
|
||||
name = value.name,
|
||||
code = value.code,
|
||||
image = value.image,
|
||||
precision = value.precision,
|
||||
)
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.data.onramp.di
|
|||
|
||||
import com.tangem.data.onramp.DefaultOnrampRepository
|
||||
import com.tangem.datasource.api.onramp.OnrampApi
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.domain.onramp.repositories.OnrampRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
|
|
@ -16,10 +17,15 @@ internal object OnrampDataModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOnrampRepository(onrampApi: OnrampApi, dispatchers: CoroutineDispatcherProvider): OnrampRepository {
|
||||
fun provideOnrampRepository(
|
||||
onrampApi: OnrampApi,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
): OnrampRepository {
|
||||
return DefaultOnrampRepository(
|
||||
onrampApi = onrampApi,
|
||||
dispatchers = dispatchers,
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -48,7 +48,6 @@ import com.tangem.domain.tokens.model.Network
|
|||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
|
||||
import com.tangem.lib.crypto.BlockchainUtils.isSolana
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.orZero
|
||||
|
|
@ -67,7 +66,6 @@ internal class DefaultStakingRepository(
|
|||
private val stakingBalanceStore: StakingBalanceStore,
|
||||
private val cacheRegistry: CacheRegistry,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val stakingFeatureToggle: StakingFeatureToggles,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
moshi: Moshi,
|
||||
|
|
@ -322,8 +320,6 @@ internal class DefaultStakingRepository(
|
|||
cryptoCurrency: CryptoCurrency,
|
||||
refresh: Boolean,
|
||||
) = withContext(dispatchers.io) {
|
||||
if (!stakingFeatureToggle.isStakingEnabled) return@withContext
|
||||
|
||||
cacheRegistry.invokeOnExpire(
|
||||
key = getYieldBalancesKey(userWalletId),
|
||||
skipCache = refresh,
|
||||
|
|
@ -363,30 +359,26 @@ internal class DefaultStakingRepository(
|
|||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
): Flow<YieldBalance> = channelFlow {
|
||||
if (!stakingFeatureToggle.isStakingEnabled) {
|
||||
send(YieldBalance.Empty)
|
||||
} else {
|
||||
launch(dispatchers.io) {
|
||||
val address = walletManagersFacade.getDefaultAddress(userWalletId, cryptoCurrency.network).orEmpty()
|
||||
val integrationId = integrationIdMap[getIntegrationKey(cryptoCurrency.id)]
|
||||
?: error("Could not get integrationId")
|
||||
stakingBalanceStore.get(userWalletId, address, integrationId)
|
||||
.distinctUntilChanged()
|
||||
.collectLatest {
|
||||
if (it != null) {
|
||||
send(yieldBalanceConverter.convert(it))
|
||||
} else {
|
||||
error("No yield balance available for currency ${cryptoCurrency.id.value}")
|
||||
}
|
||||
launch(dispatchers.io) {
|
||||
val address = walletManagersFacade.getDefaultAddress(userWalletId, cryptoCurrency.network).orEmpty()
|
||||
val integrationId = integrationIdMap[getIntegrationKey(cryptoCurrency.id)]
|
||||
?: error("Could not get integrationId")
|
||||
stakingBalanceStore.get(userWalletId, address, integrationId)
|
||||
.distinctUntilChanged()
|
||||
.collectLatest {
|
||||
if (it != null) {
|
||||
send(yieldBalanceConverter.convert(it))
|
||||
} else {
|
||||
error("No yield balance available for currency ${cryptoCurrency.id.value}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
withContext(dispatchers.io) {
|
||||
fetchSingleYieldBalance(
|
||||
userWalletId,
|
||||
cryptoCurrency,
|
||||
)
|
||||
}
|
||||
withContext(dispatchers.io) {
|
||||
fetchSingleYieldBalance(
|
||||
userWalletId,
|
||||
cryptoCurrency,
|
||||
)
|
||||
}
|
||||
}.cancellable()
|
||||
|
||||
|
|
@ -394,21 +386,17 @@ internal class DefaultStakingRepository(
|
|||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
): YieldBalance = withContext(dispatchers.io) {
|
||||
if (!stakingFeatureToggle.isStakingEnabled) {
|
||||
YieldBalance.Empty
|
||||
} else {
|
||||
fetchSingleYieldBalance(userWalletId, cryptoCurrency)
|
||||
fetchSingleYieldBalance(userWalletId, cryptoCurrency)
|
||||
|
||||
val address = walletManagersFacade.getDefaultAddress(userWalletId, cryptoCurrency.network).orEmpty()
|
||||
val address = walletManagersFacade.getDefaultAddress(userWalletId, cryptoCurrency.network).orEmpty()
|
||||
|
||||
val integrationId = integrationIdMap[getIntegrationKey(cryptoCurrency.id)]
|
||||
?: error("Could not get integrationId")
|
||||
val integrationId = integrationIdMap[getIntegrationKey(cryptoCurrency.id)]
|
||||
?: error("Could not get integrationId")
|
||||
|
||||
val result = stakingBalanceStore.getSyncOrNull(userWalletId, address, integrationId)
|
||||
?: return@withContext YieldBalance.Error
|
||||
val result = stakingBalanceStore.getSyncOrNull(userWalletId, address, integrationId)
|
||||
?: return@withContext YieldBalance.Error
|
||||
|
||||
yieldBalanceConverter.convert(result)
|
||||
}
|
||||
yieldBalanceConverter.convert(result)
|
||||
}
|
||||
|
||||
override suspend fun fetchMultiYieldBalance(
|
||||
|
|
@ -416,8 +404,6 @@ internal class DefaultStakingRepository(
|
|||
cryptoCurrencies: List<CryptoCurrency>,
|
||||
refresh: Boolean,
|
||||
) = withContext(dispatchers.io) {
|
||||
if (!stakingFeatureToggle.isStakingEnabled) return@withContext
|
||||
|
||||
cacheRegistry.invokeOnExpire(
|
||||
key = getYieldBalancesKey(userWalletId),
|
||||
skipCache = refresh,
|
||||
|
|
@ -474,19 +460,15 @@ internal class DefaultStakingRepository(
|
|||
userWalletId: UserWalletId,
|
||||
cryptoCurrencies: List<CryptoCurrency>,
|
||||
): Flow<YieldBalanceList> = channelFlow {
|
||||
if (!stakingFeatureToggle.isStakingEnabled) {
|
||||
send(YieldBalanceList.Empty)
|
||||
} else {
|
||||
stakingBalanceStore.get(userWalletId)
|
||||
.onEach {
|
||||
val balances = yieldBalanceListConverter.convert(it)
|
||||
send(balances)
|
||||
}
|
||||
.launchIn(scope = this + dispatchers.io)
|
||||
|
||||
withContext(dispatchers.io) {
|
||||
fetchMultiYieldBalance(userWalletId, cryptoCurrencies, refresh = false)
|
||||
stakingBalanceStore.get(userWalletId)
|
||||
.onEach {
|
||||
val balances = yieldBalanceListConverter.convert(it)
|
||||
send(balances)
|
||||
}
|
||||
.launchIn(scope = this + dispatchers.io)
|
||||
|
||||
withContext(dispatchers.io) {
|
||||
fetchMultiYieldBalance(userWalletId, cryptoCurrencies, refresh = false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -494,13 +476,9 @@ internal class DefaultStakingRepository(
|
|||
userWalletId: UserWalletId,
|
||||
cryptoCurrencies: List<CryptoCurrency>,
|
||||
): YieldBalanceList = withContext(dispatchers.io) {
|
||||
if (!stakingFeatureToggle.isStakingEnabled) {
|
||||
YieldBalanceList.Empty
|
||||
} else {
|
||||
fetchMultiYieldBalance(userWalletId, cryptoCurrencies)
|
||||
val result = stakingBalanceStore.getSyncOrNull(userWalletId) ?: return@withContext YieldBalanceList.Error
|
||||
yieldBalanceListConverter.convert(result)
|
||||
}
|
||||
fetchMultiYieldBalance(userWalletId, cryptoCurrencies)
|
||||
val result = stakingBalanceStore.getSyncOrNull(userWalletId) ?: return@withContext YieldBalanceList.Error
|
||||
yieldBalanceListConverter.convert(result)
|
||||
}
|
||||
|
||||
override suspend fun isAnyTokenStaked(userWalletId: UserWalletId): Boolean {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import com.tangem.datasource.local.token.StakingYieldsStore
|
|||
import com.tangem.domain.staking.repositories.*
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -38,7 +37,6 @@ internal object StakingDataModule {
|
|||
stakingBalanceStore: StakingBalanceStore,
|
||||
cacheRegistry: CacheRegistry,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
stakingFeatureToggle: StakingFeatureToggles,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
getUserWalletUseCase: GetUserWalletUseCase,
|
||||
@NetworkMoshi moshi: Moshi,
|
||||
|
|
@ -49,7 +47,6 @@ internal object StakingDataModule {
|
|||
stakingBalanceStore = stakingBalanceStore,
|
||||
cacheRegistry = cacheRegistry,
|
||||
dispatchers = dispatchers,
|
||||
stakingFeatureToggle = stakingFeatureToggle,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
getUserWalletUseCase = getUserWalletUseCase,
|
||||
moshi = moshi,
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@ package com.tangem.data.tokens.di
|
|||
|
||||
import com.tangem.data.common.cache.CacheRegistry
|
||||
import com.tangem.data.tokens.repository.*
|
||||
import com.tangem.datasource.api.express.TangemExpressApi
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.exchangeservice.swap.SwapServiceLoader
|
||||
import com.tangem.datasource.local.network.NetworksStatusesStore
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.quote.QuotesStore
|
||||
import com.tangem.datasource.local.token.ExpressAssetsStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.tokens.repository.*
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
|
|
@ -26,23 +25,21 @@ internal object TokensDataModule {
|
|||
@Singleton
|
||||
fun provideCurrenciesRepository(
|
||||
tangemTechApi: TangemTechApi,
|
||||
tangemExpressApi: TangemExpressApi,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
userWalletsStore: UserWalletsStore,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
expressAssetsStore: ExpressAssetsStore,
|
||||
cacheRegistry: CacheRegistry,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
swapServiceLoader: SwapServiceLoader,
|
||||
): CurrenciesRepository {
|
||||
return DefaultCurrenciesRepository(
|
||||
tangemTechApi = tangemTechApi,
|
||||
tangemExpressApi = tangemExpressApi,
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
userWalletsStore = userWalletsStore,
|
||||
expressAssetsStore = expressAssetsStore,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
cacheRegistry = cacheRegistry,
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
dispatchers = dispatchers,
|
||||
swapServiceLoader = swapServiceLoader,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -84,15 +81,6 @@ internal object TokensDataModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideDefaultMarketCoinsRepository(
|
||||
expressAssetsStore: ExpressAssetsStore,
|
||||
coroutineDispatcherProvider: CoroutineDispatcherProvider,
|
||||
): MarketCryptoCurrencyRepository {
|
||||
return DefaultMarketCryptoCurrencyRepository(expressAssetsStore, coroutineDispatcherProvider)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideCurrencyChecksRepository(
|
||||
|
|
|
|||
|
|
@ -12,18 +12,14 @@ import com.tangem.data.tokens.utils.CustomTokensMerger
|
|||
import com.tangem.data.tokens.utils.UserTokensBackwardCompatibility
|
||||
import com.tangem.datasource.api.common.response.ApiResponseError
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.express.TangemExpressApi
|
||||
import com.tangem.datasource.api.express.models.TangemExpressValues.EMPTY_CONTRACT_ADDRESS_VALUE
|
||||
import com.tangem.datasource.api.express.models.request.AssetsRequestBody
|
||||
import com.tangem.datasource.api.express.models.request.LeastTokenInfo
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.exchangeservice.swap.SwapServiceLoader
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.datasource.local.preferences.utils.getObject
|
||||
import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
|
||||
import com.tangem.datasource.local.preferences.utils.storeObject
|
||||
import com.tangem.datasource.local.token.ExpressAssetsStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import com.tangem.domain.demo.DemoConfig
|
||||
|
|
@ -46,12 +42,11 @@ import com.tangem.blockchain.common.FeePaidCurrency as FeePaidSdkCurrency
|
|||
@Suppress("LargeClass", "LongParameterList", "TooManyFunctions")
|
||||
internal class DefaultCurrenciesRepository(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val tangemExpressApi: TangemExpressApi,
|
||||
private val userWalletsStore: UserWalletsStore,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val expressAssetsStore: ExpressAssetsStore,
|
||||
private val cacheRegistry: CacheRegistry,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val swapServiceLoader: SwapServiceLoader,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : CurrenciesRepository {
|
||||
|
||||
|
|
@ -565,27 +560,7 @@ internal class DefaultCurrenciesRepository(
|
|||
userWalletId: UserWalletId,
|
||||
userTokens: UserTokensResponse,
|
||||
) {
|
||||
try {
|
||||
val tokensList = userTokens.tokens
|
||||
.map {
|
||||
LeastTokenInfo(
|
||||
contractAddress = it.contractAddress ?: EMPTY_CONTRACT_ADDRESS_VALUE,
|
||||
network = it.networkId,
|
||||
)
|
||||
}
|
||||
|
||||
if (tokensList.isNotEmpty()) {
|
||||
val response = tangemExpressApi.getAssets(
|
||||
AssetsRequestBody(
|
||||
tokensList = tokensList,
|
||||
),
|
||||
)
|
||||
|
||||
expressAssetsStore.store(userWalletId, response.getOrThrow())
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "Unable to fetch assets for: ${userWalletId.stringValue}")
|
||||
}
|
||||
swapServiceLoader.update(userWalletId, userTokens)
|
||||
}
|
||||
|
||||
private suspend fun handleFetchTokensError(userWallet: UserWallet, e: ApiResponseError): UserTokensResponse {
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
package com.tangem.data.tokens.repository
|
||||
|
||||
import com.tangem.datasource.api.express.models.TangemExpressValues.EMPTY_CONTRACT_ADDRESS_VALUE
|
||||
import com.tangem.datasource.local.token.ExpressAssetsStore
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.repository.MarketCryptoCurrencyRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class DefaultMarketCryptoCurrencyRepository(
|
||||
private val expressAssetsStore: ExpressAssetsStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : MarketCryptoCurrencyRepository {
|
||||
|
||||
override suspend fun isExchangeable(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean {
|
||||
return getExchangeableFlag(userWalletId, cryptoCurrency) && !cryptoCurrency.isCustom
|
||||
}
|
||||
|
||||
private suspend fun getExchangeableFlag(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean {
|
||||
return withContext(dispatchers.io) {
|
||||
val contractAddress =
|
||||
(cryptoCurrency as? CryptoCurrency.Token)?.contractAddress ?: EMPTY_CONTRACT_ADDRESS_VALUE
|
||||
|
||||
val asset = expressAssetsStore.getSyncOrNull(userWalletId)?.find {
|
||||
it.network == cryptoCurrency.network.backendId &&
|
||||
it.contractAddress.equals(contractAddress, ignoreCase = true)
|
||||
}
|
||||
|
||||
asset?.exchangeAvailable ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue