Updated on 2026-08-14

This commit is contained in:
Tangem 2025-05-14 15:06:35 +03:00
parent 8009743fb9
commit a72837204d
35 changed files with 628 additions and 132 deletions

View file

@ -37,6 +37,7 @@ dependencies {
// endregion
// region Others dependencies
implementation(deps.androidx.datastore)
implementation(deps.kotlin.coroutines)
implementation(deps.jodatime)
implementation(deps.moshi)

View file

@ -27,7 +27,9 @@ import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.pagination.*
import com.tangem.pagination.fetcher.LimitOffsetBatchFetcher
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
import java.math.BigDecimal
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicLong
@ -41,6 +43,7 @@ internal class DefaultMarketsTokenRepository(
private val excludedBlockchains: ExcludedBlockchains,
private val cacheRegistry: CacheRegistry,
private val tokenExchangesStore: RuntimeStateStore<List<TokenMarketExchangesResponse.Exchange>>,
private val maxApyStore: RuntimeStateStore<BigDecimal?>,
) : MarketsTokenRepository {
private val tokenMarketInfoConverter: TokenMarketInfoConverter = TokenMarketInfoConverter(excludedBlockchains)
@ -88,8 +91,12 @@ internal class DefaultMarketsTokenRepository(
val last = res.tokens.size < request.limit
val tokenMarketListWithMaxApy = TokenMarketListConverter.convert(res)
maxApyStore.store(tokenMarketListWithMaxApy.maxApy)
return BatchFetchResult.Success(
data = TokenMarketListConverter.convert(res),
data = tokenMarketListWithMaxApy.tokens,
last = last,
empty = res.tokens.isEmpty(),
)
@ -275,6 +282,10 @@ internal class DefaultMarketsTokenRepository(
}
}
override suspend fun getMaxApy(): Flow<BigDecimal?> {
return maxApyStore.get()
}
inline fun <T> catchListErrorAndSendEvent(block: () -> T): T {
return catchErrorAndSendEvent(block, ::createListErrorEvent)
}

View file

@ -15,6 +15,7 @@ internal fun TokenMarketListConfig.Order.toRequestParam(): String = when (this)
TokenMarketListConfig.Order.Buyers -> "buyers"
TokenMarketListConfig.Order.TopGainers -> "gainers"
TokenMarketListConfig.Order.TopLosers -> "losers"
TokenMarketListConfig.Order.Staking -> "staking"
}
internal fun PriceChangeInterval.toRequestParam(): String = when (this) {

View file

@ -2,22 +2,29 @@ package com.tangem.data.markets.converters
import com.tangem.datasource.api.markets.models.response.TokenMarketListResponse
import com.tangem.domain.markets.TokenMarket
import com.tangem.domain.markets.TokenMarketListWithMaxApy
import com.tangem.domain.markets.TokenQuotesShort
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.utils.converter.Converter
import com.tangem.utils.extensions.isPositive
internal object TokenMarketListConverter : Converter<TokenMarketListResponse, List<TokenMarket>> {
internal object TokenMarketListConverter : Converter<TokenMarketListResponse, TokenMarketListWithMaxApy> {
override fun convert(value: TokenMarketListResponse): List<TokenMarket> {
override fun convert(value: TokenMarketListResponse): TokenMarketListWithMaxApy {
val imageHost = value.imageHost ?: run {
if (value.tokens.isEmpty()) {
return emptyList()
return TokenMarketListWithMaxApy(emptyList(), null)
} else {
error("imageHost cannot be null")
}
}
return value.tokens.map { token ->
val tokens = value.tokens.map { token ->
val stakingRate = token.stakingOpportunities
?.mapNotNull { it.apy }
?.max()
.takeIf { it?.isPositive() == true }
TokenMarket(
id = CryptoCurrency.RawID(token.id),
name = token.name,
@ -33,7 +40,9 @@ internal object TokenMarketListConverter : Converter<TokenMarketListResponse, Li
monthChangePercent = token.priceChangePercentage?.day30?.movePointLeft(2),
),
tokenCharts = TokenMarket.Charts(h24 = null, week = null, month = null),
stakingRate = stakingRate,
)
}
return TokenMarketListWithMaxApy(tokens, value.summary?.maxApy)
}
}

View file

@ -22,7 +22,7 @@ internal object MarketsDataModule {
@Provides
@Singleton
fun provideMarketsRepository(
fun provideMarketsTokenRepository(
marketsApi: TangemTechMarketsApi,
tangemTechApi: TangemTechApi,
userWalletsStore: UserWalletsStore,
@ -40,6 +40,7 @@ internal object MarketsDataModule {
cacheRegistry = cacheRegistry,
tokenExchangesStore = RuntimeStateStore(defaultValue = emptyList()),
excludedBlockchains = excludedBlockchains,
maxApyStore = RuntimeStateStore(defaultValue = null),
)
}
}