Updated on 2026-08-14
This commit is contained in:
parent
bee2be0994
commit
b32a182053
16 changed files with 81 additions and 92 deletions
|
|
@ -3,6 +3,7 @@ package com.tangem.datasource.api.tangemTech
|
|||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.YieldMarketsResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.YieldTokenStatusResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.YieldTokenChartResponse
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
|
||||
|
|
@ -13,4 +14,7 @@ interface YieldSupplyApi {
|
|||
|
||||
@GET("api/v1/yield/token/{tokenAddress}")
|
||||
suspend fun getYieldTokenStatus(@Path("tokenAddress") tokenAddress: String): ApiResponse<YieldTokenStatusResponse>
|
||||
|
||||
@GET("api/v1/yield/token/{tokenAddress}/chart")
|
||||
suspend fun getYieldTokenChart(@Path("tokenAddress") tokenAddress: String): ApiResponse<YieldTokenChartResponse>
|
||||
}
|
||||
|
|
@ -16,14 +16,6 @@ data class YieldMarketsResponse(
|
|||
@Json(name = "tokenSymbol") val tokenSymbol: String,
|
||||
@Json(name = "tokenName") val tokenName: String,
|
||||
@Json(name = "apy") val apy: BigDecimal,
|
||||
@Json(name = "totalSupplied") val totalSupplied: String,
|
||||
@Json(name = "totalBorrowed") val totalBorrowed: String,
|
||||
@Json(name = "liquidityRate") val liquidityRate: String,
|
||||
@Json(name = "borrowRate") val borrowRate: String,
|
||||
@Json(name = "utilizationRate") val utilizationRate: BigDecimal,
|
||||
@Json(name = "isActive") val isActive: Boolean,
|
||||
@Json(name = "ltv") val ltv: BigDecimal,
|
||||
@Json(name = "liquidationThreshold") val liquidationThreshold: BigDecimal,
|
||||
@Json(name = "decimals") val decimals: Int,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.datasource.api.tangemTech.models
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import java.math.BigDecimal
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class YieldTokenChartResponse(
|
||||
@Json(name = "underlying") val underlying: String,
|
||||
@Json(name = "market") val market: String,
|
||||
@Json(name = "bucketSizeDays") val bucketSizeDays: Int,
|
||||
@Json(name = "period") val period: String,
|
||||
@Json(name = "data") val data: List<DataPoint>,
|
||||
@Json(name = "avr") val averageApy: BigDecimal,
|
||||
) {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DataPoint(
|
||||
@Json(name = "bucketIndex") val bucketIndex: Int,
|
||||
@Json(name = "avgApy") val avgApy: BigDecimal,
|
||||
)
|
||||
}
|
||||
|
|
@ -10,17 +10,5 @@ data class YieldTokenStatusResponse(
|
|||
@Json(name = "tokenSymbol") val tokenSymbol: String,
|
||||
@Json(name = "tokenName") val tokenName: String,
|
||||
@Json(name = "apy") val apy: BigDecimal,
|
||||
@Json(name = "totalSupplied") val totalSupplied: String,
|
||||
@Json(name = "totalBorrowed") val totalBorrowed: String,
|
||||
@Json(name = "liquidityRate") val liquidityRate: String,
|
||||
@Json(name = "borrowRate") val borrowRate: String,
|
||||
@Json(name = "utilizationRate") val utilizationRate: Double,
|
||||
@Json(name = "isActive") val isActive: Boolean,
|
||||
@Json(name = "ltv") val ltv: Int,
|
||||
@Json(name = "liquidationThreshold") val liquidationThreshold: Int,
|
||||
@Json(name = "decimals") val decimals: Int,
|
||||
@Json(name = "chainId") val chainId: Int,
|
||||
@Json(name = "priority") val priority: Int,
|
||||
@Json(name = "isEnabled") val isEnabled: Boolean,
|
||||
@Json(name = "lastUpdatedAt") val lastUpdatedAt: String,
|
||||
)
|
||||
|
|
@ -5,9 +5,10 @@ import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
|
|||
import com.tangem.data.yield.supply.converters.YieldMarketTokenConverter
|
||||
import com.tangem.datasource.api.tangemTech.YieldSupplyApi
|
||||
import com.tangem.data.yield.supply.converters.YieldTokenStatusConverter
|
||||
import com.tangem.data.yield.supply.converters.YieldTokenChartConverter
|
||||
import com.tangem.domain.yield.supply.YieldSupplyMarketRepository
|
||||
import com.tangem.domain.yield.supply.models.YieldMarketToken
|
||||
import com.tangem.domain.yield.supply.models.YieldTokenStatus
|
||||
import com.tangem.domain.yield.supply.models.YieldSupplyMarketChartData
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -31,8 +32,13 @@ internal class DefaultYieldSupplyMarketRepository(
|
|||
|
||||
override fun getMarketsFlow(): Flow<List<YieldMarketToken>> = store.get()
|
||||
|
||||
override suspend fun getTokenStatus(contractAddress: String): YieldTokenStatus {
|
||||
override suspend fun getTokenStatus(contractAddress: String): YieldMarketToken {
|
||||
val response = yieldSupplyApi.getYieldTokenStatus(contractAddress).getOrThrow()
|
||||
return YieldTokenStatusConverter.convert(response)
|
||||
}
|
||||
|
||||
override suspend fun getTokenChart(contractAddress: String): YieldSupplyMarketChartData {
|
||||
val response = yieldSupplyApi.getYieldTokenChart(contractAddress).getOrThrow()
|
||||
return YieldTokenChartConverter.convert(response)
|
||||
}
|
||||
}
|
||||
|
|
@ -11,14 +11,7 @@ internal object YieldMarketTokenConverter : Converter<YieldMarketsResponse.Marke
|
|||
tokenSymbol = value.tokenSymbol,
|
||||
tokenName = value.tokenName,
|
||||
apy = value.apy,
|
||||
totalSupplied = value.totalSupplied,
|
||||
totalBorrowed = value.totalBorrowed,
|
||||
liquidityRate = value.liquidityRate,
|
||||
borrowRate = value.borrowRate,
|
||||
utilizationRate = value.utilizationRate,
|
||||
isActive = value.isActive,
|
||||
ltv = value.ltv,
|
||||
liquidationThreshold = value.liquidationThreshold,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.data.yield.supply.converters
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.YieldTokenChartResponse
|
||||
import com.tangem.domain.yield.supply.models.YieldSupplyMarketChartData
|
||||
|
||||
internal object YieldTokenChartConverter {
|
||||
|
||||
fun convert(response: YieldTokenChartResponse): YieldSupplyMarketChartData {
|
||||
val y = response.data.map { it.avgApy.toDouble() }
|
||||
val x = response.data.map { it.bucketIndex.toDouble() }
|
||||
val avr = response.averageApy.toDouble()
|
||||
return YieldSupplyMarketChartData(y = y, x = x, avr = avr)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,17 @@
|
|||
package com.tangem.data.yield.supply.converters
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.YieldTokenStatusResponse
|
||||
import com.tangem.domain.yield.supply.models.YieldTokenStatus
|
||||
import com.tangem.domain.yield.supply.models.YieldMarketToken
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
internal object YieldTokenStatusConverter : Converter<YieldTokenStatusResponse, YieldTokenStatus> {
|
||||
override fun convert(value: YieldTokenStatusResponse): YieldTokenStatus {
|
||||
return YieldTokenStatus(
|
||||
internal object YieldTokenStatusConverter : Converter<YieldTokenStatusResponse, YieldMarketToken> {
|
||||
override fun convert(value: YieldTokenStatusResponse): YieldMarketToken {
|
||||
return YieldMarketToken(
|
||||
tokenAddress = value.tokenAddress,
|
||||
tokenSymbol = value.tokenSymbol,
|
||||
tokenName = value.tokenName,
|
||||
apy = value.apy,
|
||||
totalSupplied = value.totalSupplied,
|
||||
totalBorrowed = value.totalBorrowed,
|
||||
liquidityRate = value.liquidityRate,
|
||||
borrowRate = value.borrowRate,
|
||||
utilizationRate = value.utilizationRate,
|
||||
isActive = value.isActive,
|
||||
ltv = value.ltv,
|
||||
liquidationThreshold = value.liquidationThreshold,
|
||||
decimals = value.decimals,
|
||||
chainId = value.chainId,
|
||||
priority = value.priority,
|
||||
isEnabled = value.isEnabled,
|
||||
lastUpdatedAt = value.lastUpdatedAt,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -12,12 +12,5 @@ data class YieldMarketToken(
|
|||
val tokenSymbol: String,
|
||||
val tokenName: String,
|
||||
val apy: SerializedBigDecimal,
|
||||
val totalSupplied: String,
|
||||
val totalBorrowed: String,
|
||||
val liquidityRate: String,
|
||||
val borrowRate: String,
|
||||
val utilizationRate: SerializedBigDecimal,
|
||||
val isActive: Boolean,
|
||||
val ltv: SerializedBigDecimal,
|
||||
val liquidationThreshold: SerializedBigDecimal,
|
||||
)
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.domain.yield.supply.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class YieldSupplyMarketChartData(
|
||||
val y: List<Double>,
|
||||
val x: List<Double>,
|
||||
val avr: Double,
|
||||
)
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
package com.tangem.domain.yield.supply.models
|
||||
|
||||
import com.tangem.domain.models.serialization.SerializedBigDecimal
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Domain model representing yield market status for a specific token.
|
||||
*/
|
||||
@Serializable
|
||||
data class YieldTokenStatus(
|
||||
val tokenAddress: String,
|
||||
val tokenSymbol: String,
|
||||
val tokenName: String,
|
||||
val apy: SerializedBigDecimal,
|
||||
val totalSupplied: String,
|
||||
val totalBorrowed: String,
|
||||
val liquidityRate: String,
|
||||
val borrowRate: String,
|
||||
val utilizationRate: Double,
|
||||
val isActive: Boolean,
|
||||
val ltv: Int,
|
||||
val liquidationThreshold: Int,
|
||||
val decimals: Int,
|
||||
val chainId: Int,
|
||||
val priority: Int,
|
||||
val isEnabled: Boolean,
|
||||
val lastUpdatedAt: String,
|
||||
)
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.domain.yield.supply
|
||||
|
||||
import com.tangem.domain.yield.supply.models.YieldMarketToken
|
||||
import com.tangem.domain.yield.supply.models.YieldTokenStatus
|
||||
import com.tangem.domain.yield.supply.models.YieldSupplyMarketChartData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface YieldSupplyMarketRepository {
|
||||
|
|
@ -26,5 +26,11 @@ interface YieldSupplyMarketRepository {
|
|||
* Get yield token status by contract address.
|
||||
*/
|
||||
@Throws
|
||||
suspend fun getTokenStatus(contractAddress: String): YieldTokenStatus
|
||||
suspend fun getTokenStatus(contractAddress: String): YieldMarketToken
|
||||
|
||||
/**
|
||||
* Get yield token APY chart by contract address.
|
||||
*/
|
||||
@Throws
|
||||
suspend fun getTokenChart(contractAddress: String): YieldSupplyMarketChartData
|
||||
}
|
||||
|
|
@ -3,13 +3,13 @@ package com.tangem.domain.yield.supply.usecase
|
|||
import arrow.core.Either
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.yield.supply.YieldSupplyMarketRepository
|
||||
import com.tangem.domain.yield.supply.models.YieldTokenStatus
|
||||
import com.tangem.domain.yield.supply.models.YieldMarketToken
|
||||
|
||||
class YieldSupplyGetTokenStatusUseCase(
|
||||
private val yieldSupplyMarketRepository: YieldSupplyMarketRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(token: CryptoCurrency.Token): Either<Throwable, YieldTokenStatus> = Either.catch {
|
||||
suspend operator fun invoke(token: CryptoCurrency.Token): Either<Throwable, YieldMarketToken> = Either.catch {
|
||||
yieldSupplyMarketRepository.getTokenStatus(token.contractAddress)
|
||||
}
|
||||
}
|
||||
|
|
@ -14,23 +14,24 @@ internal sealed class YieldSupplyChartUM {
|
|||
data class Error(val onRetry: () -> Unit) : YieldSupplyChartUM()
|
||||
|
||||
@Immutable
|
||||
data class Data(val chartData: YieldSupplyMarketChartData) : YieldSupplyChartUM()
|
||||
data class Data(val chartData: YieldSupplyMarketChartDataUM) : YieldSupplyChartUM()
|
||||
}
|
||||
|
||||
@Immutable
|
||||
internal data class YieldSupplyMarketChartData(
|
||||
internal data class YieldSupplyMarketChartDataUM(
|
||||
val y: ImmutableList<Double>,
|
||||
val x: ImmutableList<Double>,
|
||||
val avr: Double,
|
||||
) {
|
||||
companion object {
|
||||
@Suppress("MagicNumber")
|
||||
fun mock(): YieldSupplyMarketChartData {
|
||||
fun mock(): YieldSupplyMarketChartDataUM {
|
||||
// TODO [REDACTED_TASK_KEY] replace mock values with real APY series
|
||||
val y = listOf(
|
||||
4.6, 4.0, 4.2, 3.3, 2.5, 5.6, 4.2, 6.7, 3.5, 2.5, 4.5, 3.4,
|
||||
).toImmutableList()
|
||||
val x = List(y.size) { 1.0 }.toImmutableList()
|
||||
return YieldSupplyMarketChartData(y = y, x = x)
|
||||
return YieldSupplyMarketChartDataUM(y = y, x = x, avr = 5.15)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import com.tangem.core.decompose.di.ModelScoped
|
|||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.features.yield.supply.impl.chart.entity.YieldSupplyChartUM
|
||||
import com.tangem.features.yield.supply.impl.chart.entity.YieldSupplyMarketChartData
|
||||
import com.tangem.features.yield.supply.impl.chart.entity.YieldSupplyMarketChartDataUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
|
@ -30,7 +30,7 @@ internal class YieldSupplyChartModel @Inject constructor(
|
|||
|
||||
init {
|
||||
// TODO [REDACTED_TASK_KEY]
|
||||
val chartData = YieldSupplyMarketChartData.mock()
|
||||
val chartData = YieldSupplyMarketChartDataUM.mock()
|
||||
uiState.update { YieldSupplyChartUM.Data(chartData = chartData) }
|
||||
}
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ import com.tangem.core.ui.extensions.stringResourceSafe
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.yield.supply.impl.chart.entity.YieldSupplyChartUM
|
||||
import com.tangem.features.yield.supply.impl.chart.entity.YieldSupplyMarketChartData
|
||||
import com.tangem.features.yield.supply.impl.chart.entity.YieldSupplyMarketChartDataUM
|
||||
|
||||
@Composable
|
||||
internal fun YieldSupplyChartContent(state: YieldSupplyChartUM, modifier: Modifier = Modifier) {
|
||||
|
|
@ -199,7 +199,7 @@ private class YieldSupplyChartPreviewProvider : PreviewParameterProvider<YieldSu
|
|||
get() = sequenceOf(
|
||||
YieldSupplyChartUM.Loading,
|
||||
YieldSupplyChartUM.Error(onRetry = {}),
|
||||
YieldSupplyChartUM.Data(chartData = YieldSupplyMarketChartData.mock()),
|
||||
YieldSupplyChartUM.Data(chartData = YieldSupplyMarketChartDataUM.mock()),
|
||||
)
|
||||
}
|
||||
// endregion
|
||||
Loading…
Add table
Add a link
Reference in a new issue