From 6a477bb4714cc3415dd897cb6a7a82e06997114c Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 26 Sep 2025 01:17:53 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../datasource/api/common/config/ApiConfig.kt | 2 + .../api/common/config/YieldSupply.kt | 81 +++++++++++++++++++ .../api/tangemTech/TangemTechApi.kt | 8 -- .../api/tangemTech/YieldSupplyApi.kt | 16 ++++ .../tangemTech/models/YieldMarketsResponse.kt | 5 +- .../com/tangem/datasource/di/NetworkModule.kt | 10 +++ .../DefaultYieldSupplyMarketRepository.kt | 6 +- .../yield/supply/di/YieldSupplyDataModule.kt | 6 +- 8 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 core/datasource/src/main/java/com/tangem/datasource/api/common/config/YieldSupply.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/YieldSupplyApi.kt diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/ApiConfig.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/ApiConfig.kt index 58df8bc70a..cac3e4c967 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/ApiConfig.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/ApiConfig.kt @@ -26,6 +26,7 @@ sealed class ApiConfig { StakeKit, TangemPay, BlockAid, + YieldSupply, } private fun initializeId(): ID { @@ -35,6 +36,7 @@ sealed class ApiConfig { is StakeKit -> ID.StakeKit is TangemPay -> ID.TangemPay is BlockAid -> ID.BlockAid + is YieldSupply -> ID.YieldSupply } } diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/YieldSupply.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/YieldSupply.kt new file mode 100644 index 0000000000..774d36cf67 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/YieldSupply.kt @@ -0,0 +1,81 @@ +package com.tangem.datasource.api.common.config + +import com.tangem.datasource.BuildConfig +import com.tangem.datasource.api.common.AuthProvider +import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage +import com.tangem.datasource.utils.RequestHeader +import com.tangem.utils.ProviderSuspend +import com.tangem.utils.info.AppInfoProvider +import com.tangem.utils.version.AppVersionProvider + +/** YieldSupply [ApiConfig] */ +internal class YieldSupply( + private val environmentConfigStorage: EnvironmentConfigStorage, + private val appVersionProvider: AppVersionProvider, + private val authProvider: AuthProvider, + private val appInfoProvider: AppInfoProvider, +) : ApiConfig() { + + override val defaultEnvironment: ApiEnvironment = getInitialEnvironment() + + override val environmentConfigs = listOf( + createDevEnvironment(), + createStageEnvironment(), + createMockedEnvironment(), + createProdEnvironment(), + ) + + private fun getInitialEnvironment(): ApiEnvironment { + return when (BuildConfig.BUILD_TYPE) { + MOCKED_BUILD_TYPE, + -> ApiEnvironment.MOCK + DEBUG_BUILD_TYPE, + INTERNAL_BUILD_TYPE, + EXTERNAL_BUILD_TYPE, + RELEASE_BUILD_TYPE, + -> ApiEnvironment.PROD + else -> error("Unknown build type [${BuildConfig.BUILD_TYPE}]") + } + } + + private fun createDevEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig( + environment = ApiEnvironment.DEV, + baseUrl = "[REDACTED_ENV_URL]", + headers = createHeaders(ApiEnvironment.DEV), + ) + + private fun createStageEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig( + environment = ApiEnvironment.STAGE, + baseUrl = "[REDACTED_ENV_URL]", + headers = createHeaders(ApiEnvironment.STAGE), + ) + + private fun createMockedEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig( + environment = ApiEnvironment.MOCK, + baseUrl = "[REDACTED_ENV_URL]", + headers = createHeaders(ApiEnvironment.MOCK), + ) + + private fun createProdEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig( + environment = ApiEnvironment.PROD, + baseUrl = "https://yield.tangem.org/", + headers = createHeaders(ApiEnvironment.PROD), + ) + + private fun createHeaders(apiEnvironment: ApiEnvironment) = buildMap { + put(key = "api-key", value = ProviderSuspend { getApiKey(apiEnvironment) }) + putAll(from = RequestHeader.AppVersionPlatformHeaders(appVersionProvider, appInfoProvider).values) + putAll(from = RequestHeader.AuthenticationHeader(authProvider).values) + } + + private fun getApiKey(apiEnvironment: ApiEnvironment): String { + return when (apiEnvironment) { + ApiEnvironment.MOCK, + ApiEnvironment.DEV, + ApiEnvironment.DEV_2, + -> environmentConfigStorage.getConfigSync().tangemApiKeyDev + ApiEnvironment.STAGE -> environmentConfigStorage.getConfigSync().tangemApiKeyStage + ApiEnvironment.PROD -> environmentConfigStorage.getConfigSync().tangemApiKey + } ?: error("No tangem tech api config provided") + } +} \ No newline at end of file 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 c6cc91adbf..3b08465384 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 @@ -144,14 +144,6 @@ interface TangemTechApi { suspend fun activatePromoCode(@Body body: PromocodeActivationBody): ApiResponse // endregion - // region yield - @GET("v1/yield/markets") - suspend fun getYieldMarkets(): ApiResponse - - @GET("v1/yield/token/{tokenAddress}") - suspend fun getYieldTokenStatus(@Path("tokenAddress") tokenAddress: String): ApiResponse - // endregion - // region account @GET("/v1/wallets/{walletId}/accounts") suspend fun getWalletAccounts( diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/YieldSupplyApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/YieldSupplyApi.kt new file mode 100644 index 0000000000..cc41d91e89 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/YieldSupplyApi.kt @@ -0,0 +1,16 @@ +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 retrofit2.http.GET +import retrofit2.http.Path + +interface YieldSupplyApi { + + @GET("v1/yield/markets") + suspend fun getYieldMarkets(): ApiResponse + + @GET("v1/yield/token/{tokenAddress}") + suspend fun getYieldTokenStatus(@Path("tokenAddress") tokenAddress: String): ApiResponse +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldMarketsResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldMarketsResponse.kt index 184bb71951..7f816f3161 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldMarketsResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldMarketsResponse.kt @@ -6,8 +6,8 @@ import java.math.BigDecimal @JsonClass(generateAdapter = true) data class YieldMarketsResponse( - @Json(name = "markets") val marketDtos: List, - @Json(name = "lastUpdated") val lastUpdated: String, + @Json(name = "tokens") val marketDtos: List, + @Json(name = "lastUpdatedAt") val lastUpdated: String, ) { @JsonClass(generateAdapter = true) @@ -24,5 +24,6 @@ data class YieldMarketsResponse( @Json(name = "isActive") val isActive: Boolean, @Json(name = "ltv") val ltv: BigDecimal, @Json(name = "liquidationThreshold") val liquidationThreshold: BigDecimal, + @Json(name = "decimals") val decimals: Int, ) } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt index 6c8dc4b626..9a0bed416c 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt @@ -15,6 +15,7 @@ import com.tangem.datasource.api.onramp.OnrampApi import com.tangem.datasource.api.pay.TangemPayApi import com.tangem.datasource.api.stakekit.StakeKitApi import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.api.tangemTech.YieldSupplyApi import com.tangem.datasource.di.utils.RetrofitApiBuilder import com.tangem.datasource.di.utils.RetrofitApiBuilder.Timeouts import com.tangem.datasource.local.preferences.AppPreferencesStore @@ -88,6 +89,15 @@ internal object NetworkModule { ) } + @Provides + @Singleton + fun provideYieldSupplyApi(retrofitApiBuilder: RetrofitApiBuilder): YieldSupplyApi { + return retrofitApiBuilder.build( + apiConfigId = ApiConfig.ID.YieldSupply, + applyTimeoutAnnotations = true, + ) + } + @Provides @Singleton fun provideTangemTechMarketsApi(retrofitApiBuilder: RetrofitApiBuilder): TangemTechMarketsApi { diff --git a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyMarketRepository.kt b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyMarketRepository.kt index cde574a4d8..8291229a65 100644 --- a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyMarketRepository.kt +++ b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyMarketRepository.kt @@ -1,9 +1,9 @@ package com.tangem.data.yield.supply import com.tangem.datasource.api.common.response.getOrThrow -import com.tangem.datasource.api.tangemTech.TangemTechApi 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.domain.yield.supply.YieldSupplyMarketRepository import com.tangem.domain.yield.supply.models.YieldMarketToken import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.withContext internal class DefaultYieldSupplyMarketRepository( - private val techApi: TangemTechApi, + private val yieldSupplyApi: YieldSupplyApi, private val store: YieldMarketsStore, private val dispatchers: CoroutineDispatcherProvider, ) : YieldSupplyMarketRepository { @@ -21,7 +21,7 @@ internal class DefaultYieldSupplyMarketRepository( } override suspend fun updateMarkets(): List = withContext(dispatchers.io) { - val response = techApi.getYieldMarkets().getOrThrow() + val response = yieldSupplyApi.getYieldMarkets().getOrThrow() val domain = response.marketDtos.map(YieldMarketTokenConverter::convert) store.store(domain) domain diff --git a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/di/YieldSupplyDataModule.kt b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/di/YieldSupplyDataModule.kt index 9afb654ca1..4aec69a8ad 100644 --- a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/di/YieldSupplyDataModule.kt +++ b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/di/YieldSupplyDataModule.kt @@ -2,7 +2,7 @@ package com.tangem.data.yield.supply.di import com.tangem.data.yield.supply.DefaultYieldSupplyMarketRepository import com.tangem.data.yield.supply.DefaultYieldSupplyTransactionRepository -import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.api.tangemTech.YieldSupplyApi import com.tangem.datasource.local.yieldsupply.YieldMarketsStore import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.yield.supply.YieldSupplyMarketRepository @@ -33,12 +33,12 @@ internal object YieldSupplyDataModule { @Provides @Singleton fun provideYieldSupplyMarketRepository( - techApi: TangemTechApi, + yieldSupplyApi: YieldSupplyApi, store: YieldMarketsStore, dispatchers: CoroutineDispatcherProvider, ): YieldSupplyMarketRepository { return DefaultYieldSupplyMarketRepository( - techApi = techApi, + yieldSupplyApi = yieldSupplyApi, store = store, dispatchers = dispatchers, )