Updated on 2026-08-14

This commit is contained in:
Tangem 2025-08-08 15:26:34 +04:00
parent e4921c6dc6
commit fcdaf5acfc
5 changed files with 221 additions and 383 deletions

View file

@ -1,17 +0,0 @@
package com.tangem.datasource.api.tangemTech
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.tangemTech.models.v2.UserTokensResponseV2
import retrofit2.http.*
interface TangemTechApiV2 {
@GET("user-tokens/{wallet_id}")
suspend fun getUserTokens(@Path("wallet_id") walletId: String): ApiResponse<UserTokensResponseV2>
@PUT("user-tokens/{wallet_id}")
suspend fun saveUserTokens(
@Path("wallet_id") walletId: String,
@Body userTokens: UserTokensResponseV2,
): ApiResponse<Unit>
}

View file

@ -1,26 +0,0 @@
package com.tangem.datasource.api.tangemTech.models.v2
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
@JsonClass(generateAdapter = true)
data class UserTokensResponseV2(
@Json(name = "accounts")
val accounts: List<TokensAccount>,
) {
@JsonClass(generateAdapter = true)
data class TokensAccount(
@Json(name = "id")
val id: Int,
@Json(name = "title")
val title: String,
@Json(name = "tokens")
val tokens: List<UserTokensResponse.Token>? = null,
@Json(name = "tokensCount")
val tokensCount: Int? = null,
@Json(name = "archived")
val isArchived: Boolean,
)
}

View file

@ -1,8 +1,5 @@
package com.tangem.datasource.di
import android.content.Context
import com.squareup.moshi.Moshi
import com.tangem.core.analytics.api.AnalyticsErrorHandler
import com.tangem.datasource.BuildConfig
import com.tangem.datasource.api.common.blockaid.BlockAidApi
import com.tangem.datasource.api.common.config.ApiConfig
@ -12,44 +9,29 @@ import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
import com.tangem.datasource.api.common.config.managers.DevApiConfigsManager
import com.tangem.datasource.api.common.config.managers.MockApiConfigsManager
import com.tangem.datasource.api.common.config.managers.ProdApiConfigsManager
import com.tangem.datasource.api.common.response.ApiResponseCallAdapterFactory
import com.tangem.datasource.api.express.TangemExpressApi
import com.tangem.datasource.api.markets.TangemTechMarketsApi
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.TangemTechApiV2
import com.tangem.datasource.local.logs.AppLogsStore
import com.tangem.datasource.di.utils.RetrofitApiBuilder
import com.tangem.datasource.di.utils.RetrofitApiBuilder.Timeouts
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.utils.*
import com.tangem.datasource.utils.RequestHeader.AppVersionPlatformHeaders
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.info.AppInfoProvider
import com.tangem.utils.version.AppVersionProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import java.util.concurrent.TimeUnit
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object NetworkModule {
private const val PROD_V2_TANGEM_TECH_BASE_URL = "https://api.tangem-tech.com/v2/"
private const val TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS = 60L
private const val STAKE_KIT_API_TIMEOUT_SECONDS = 60L
private val excludedApiForLogging: Set<ApiConfig.ID> = setOf(
ApiConfig.ID.StakeKit,
)
@Provides
@Singleton
fun provideApiConfigManager(
@ -66,286 +48,76 @@ internal object NetworkModule {
@Provides
@Singleton
fun provideExpressApi(
@NetworkMoshi moshi: Moshi,
@ApplicationContext context: Context,
analyticsErrorHandler: AnalyticsErrorHandler,
apiConfigsManager: ApiConfigsManager,
appLogsStore: AppLogsStore,
): TangemExpressApi {
return createApi(
id = ApiConfig.ID.Express,
moshi = moshi,
context = context,
apiConfigsManager = apiConfigsManager,
analyticsErrorHandler = analyticsErrorHandler,
clientBuilder = {
addInterceptor(
NetworkLogsSaveInterceptor(appLogsStore),
)
},
fun provideExpressApi(retrofitApiBuilder: RetrofitApiBuilder): TangemExpressApi {
return retrofitApiBuilder.build(
apiConfigId = ApiConfig.ID.Express,
applyTimeoutAnnotations = false,
)
}
@Provides
@Singleton
fun provideStakeKitApi(
@NetworkMoshi moshi: Moshi,
@ApplicationContext context: Context,
apiConfigsManager: ApiConfigsManager,
analyticsErrorHandler: AnalyticsErrorHandler,
appLogsStore: AppLogsStore,
): StakeKitApi {
return createApi(
id = ApiConfig.ID.StakeKit,
moshi = moshi,
context = context,
apiConfigsManager = apiConfigsManager,
analyticsErrorHandler = analyticsErrorHandler,
fun provideStakeKitApi(retrofitApiBuilder: RetrofitApiBuilder): StakeKitApi {
return retrofitApiBuilder.build(
apiConfigId = ApiConfig.ID.StakeKit,
applyTimeoutAnnotations = false,
timeouts = Timeouts(
callTimeoutSeconds = STAKE_KIT_API_TIMEOUT_SECONDS,
connectTimeoutSeconds = STAKE_KIT_API_TIMEOUT_SECONDS,
readTimeoutSeconds = STAKE_KIT_API_TIMEOUT_SECONDS,
writeTimeoutSeconds = STAKE_KIT_API_TIMEOUT_SECONDS,
),
clientBuilder = {
addInterceptor(
NetworkLogsSaveInterceptor(appLogsStore),
)
},
)
}
@Provides
@Singleton
fun provideOnrampApi(
@NetworkMoshi moshi: Moshi,
@ApplicationContext context: Context,
analyticsErrorHandler: AnalyticsErrorHandler,
apiConfigsManager: ApiConfigsManager,
appLogsStore: AppLogsStore,
): OnrampApi {
return createApi(
id = ApiConfig.ID.Express,
moshi = moshi,
context = context,
apiConfigsManager = apiConfigsManager,
analyticsErrorHandler = analyticsErrorHandler,
clientBuilder = {
addInterceptor(
NetworkLogsSaveInterceptor(appLogsStore),
)
},
fun provideOnrampApi(retrofitApiBuilder: RetrofitApiBuilder): OnrampApi {
return retrofitApiBuilder.build(
apiConfigId = ApiConfig.ID.Express,
applyTimeoutAnnotations = false,
)
}
@Provides
@Singleton
fun provideTangemTechApi(
@NetworkMoshi moshi: Moshi,
@ApplicationContext context: Context,
analyticsErrorHandler: AnalyticsErrorHandler,
apiConfigsManager: ApiConfigsManager,
): TangemTechApi {
return createApi(
id = ApiConfig.ID.TangemTech,
moshi = moshi,
context = context,
apiConfigsManager = apiConfigsManager,
analyticsErrorHandler = analyticsErrorHandler,
clientBuilder = { applyTimeoutAnnotations() },
)
}
// TODO: It will be deleted in the future or refactored using ApiConfig
@Provides
@Singleton
fun provideTangemTechApiV2(
@NetworkMoshi moshi: Moshi,
@ApplicationContext context: Context,
analyticsErrorHandler: AnalyticsErrorHandler,
appVersionProvider: AppVersionProvider,
appInfoProvider: AppInfoProvider,
): TangemTechApiV2 {
return provideTangemTechApiInternal(
moshi = moshi,
context = context,
appVersionProvider = appVersionProvider,
baseUrl = PROD_V2_TANGEM_TECH_BASE_URL,
analyticsErrorHandler = analyticsErrorHandler,
appInfoProvider = appInfoProvider,
fun provideTangemTechApi(retrofitApiBuilder: RetrofitApiBuilder): TangemTechApi {
return retrofitApiBuilder.build(
apiConfigId = ApiConfig.ID.TangemTech,
applyTimeoutAnnotations = true,
)
}
@Provides
@Singleton
fun provideTangemTechMarketsApi(
@NetworkMoshi moshi: Moshi,
@ApplicationContext context: Context,
analyticsErrorHandler: AnalyticsErrorHandler,
apiConfigsManager: ApiConfigsManager,
): TangemTechMarketsApi {
return createApi(
id = ApiConfig.ID.TangemTech,
moshi = moshi,
context = context,
apiConfigsManager = apiConfigsManager,
analyticsErrorHandler = analyticsErrorHandler,
clientBuilder = {
this.callTimeout(TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.connectTimeout(TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.readTimeout(TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.applyTimeoutAnnotations()
},
fun provideTangemTechMarketsApi(retrofitApiBuilder: RetrofitApiBuilder): TangemTechMarketsApi {
return retrofitApiBuilder.build(
apiConfigId = ApiConfig.ID.TangemTech,
applyTimeoutAnnotations = false,
timeouts = Timeouts(
callTimeoutSeconds = TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS,
connectTimeoutSeconds = TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS,
readTimeoutSeconds = TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS,
),
logsSaving = false,
)
}
@Provides
@Singleton
fun provideTangemVisaApi(
@NetworkMoshi moshi: Moshi,
@ApplicationContext context: Context,
analyticsErrorHandler: AnalyticsErrorHandler,
apiConfigsManager: ApiConfigsManager,
appLogsStore: AppLogsStore,
): TangemPayApi {
return createApi<TangemPayApi>(
id = ApiConfig.ID.TangemPay,
moshi = moshi,
context = context,
apiConfigsManager = apiConfigsManager,
analyticsErrorHandler = analyticsErrorHandler,
clientBuilder = {
addInterceptor(
NetworkLogsSaveInterceptor(appLogsStore),
).applyTimeoutAnnotations()
},
fun provideTangemVisaApi(retrofitApiBuilder: RetrofitApiBuilder): TangemPayApi {
return retrofitApiBuilder.build(
apiConfigId = ApiConfig.ID.TangemPay,
applyTimeoutAnnotations = false,
)
}
@Suppress("LongParameterList")
@Deprecated("use createApi instead")
private inline fun <reified T> provideTangemTechApiInternal(
moshi: Moshi,
context: Context,
appVersionProvider: AppVersionProvider,
appInfoProvider: AppInfoProvider,
baseUrl: String,
analyticsErrorHandler: AnalyticsErrorHandler,
timeouts: Timeouts = Timeouts(),
requestHeaders: List<RequestHeader> = listOf(AppVersionPlatformHeaders(appVersionProvider, appInfoProvider)),
): T {
val client = OkHttpClient.Builder()
.applyTimeoutAnnotations()
.let { builder ->
var b = builder
if (timeouts.callTimeoutSeconds != null) {
b = b.callTimeout(timeouts.callTimeoutSeconds, TimeUnit.SECONDS)
}
if (timeouts.connectTimeoutSeconds != null) {
b = b.connectTimeout(timeouts.connectTimeoutSeconds, TimeUnit.SECONDS)
}
if (timeouts.readTimeoutSeconds != null) {
b = b.readTimeout(timeouts.readTimeoutSeconds, TimeUnit.SECONDS)
}
if (timeouts.writeTimeoutSeconds != null) {
b = b.writeTimeout(timeouts.writeTimeoutSeconds, TimeUnit.SECONDS)
}
b
}
.addHeaders(
*requestHeaders.toTypedArray(),
// TODO("refactor header init") get auth data after biometric auth to avoid race condition
// AuthenticationHeader(authProvider),
)
.addLoggers(context)
.build()
return Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.addCallAdapterFactory(ApiResponseCallAdapterFactory.create(analyticsErrorHandler))
.baseUrl(baseUrl)
.client(client)
.build()
.create(T::class.java)
}
@Provides
@Singleton
fun provideBlockAidApi(
@NetworkMoshi moshi: Moshi,
@ApplicationContext context: Context,
analyticsErrorHandler: AnalyticsErrorHandler,
apiConfigsManager: ApiConfigsManager,
appLogsStore: AppLogsStore,
): BlockAidApi {
return createApi<BlockAidApi>(
id = ApiConfig.ID.BlockAid,
moshi = moshi,
context = context,
apiConfigsManager = apiConfigsManager,
analyticsErrorHandler = analyticsErrorHandler,
clientBuilder = {
addInterceptor(
NetworkLogsSaveInterceptor(appLogsStore),
).applyTimeoutAnnotations()
},
fun provideBlockAidApi(retrofitApiBuilder: RetrofitApiBuilder): BlockAidApi {
return retrofitApiBuilder.build(
apiConfigId = ApiConfig.ID.BlockAid,
applyTimeoutAnnotations = false,
)
}
private inline fun <reified T> createApi(
id: ApiConfig.ID,
moshi: Moshi,
context: Context,
apiConfigsManager: ApiConfigsManager,
analyticsErrorHandler: AnalyticsErrorHandler,
timeouts: Timeouts = Timeouts(),
clientBuilder: OkHttpClient.Builder.() -> OkHttpClient.Builder = { this },
): T {
val environmentConfig = apiConfigsManager.getEnvironmentConfig(id)
return Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.addCallAdapterFactory(ApiResponseCallAdapterFactory.create(analyticsErrorHandler))
.baseUrl(environmentConfig.baseUrl)
.client(
OkHttpClient.Builder()
.applyApiConfig(id, apiConfigsManager)
.applyTimeoutAnnotations()
.let { builder ->
var b = builder
if (timeouts.callTimeoutSeconds != null) {
b = b.callTimeout(timeouts.callTimeoutSeconds, TimeUnit.SECONDS)
}
if (timeouts.connectTimeoutSeconds != null) {
b = b.connectTimeout(timeouts.connectTimeoutSeconds, TimeUnit.SECONDS)
}
if (timeouts.readTimeoutSeconds != null) {
b = b.readTimeout(timeouts.readTimeoutSeconds, TimeUnit.SECONDS)
}
if (timeouts.writeTimeoutSeconds != null) {
b = b.writeTimeout(timeouts.writeTimeoutSeconds, TimeUnit.SECONDS)
}
b
}
.addLoggers(context = context, id = id)
.clientBuilder()
.build(),
)
.build()
.create(T::class.java)
}
private fun OkHttpClient.Builder.addLoggers(context: Context, id: ApiConfig.ID): OkHttpClient.Builder {
if (id in excludedApiForLogging) return this
return addLoggers(context)
}
private data class Timeouts(
val callTimeoutSeconds: Long? = null,
val connectTimeoutSeconds: Long? = null,
val readTimeoutSeconds: Long? = null,
val writeTimeoutSeconds: Long? = null,
)
}

View file

@ -0,0 +1,185 @@
package com.tangem.datasource.di.utils
import android.content.Context
import com.chuckerteam.chucker.api.ChuckerInterceptor
import com.squareup.moshi.Moshi
import com.tangem.core.analytics.api.AnalyticsErrorHandler
import com.tangem.datasource.BuildConfig
import com.tangem.datasource.api.common.SwitchEnvironmentInterceptor
import com.tangem.datasource.api.common.config.ApiConfig
import com.tangem.datasource.api.common.config.ApiConfig.Companion.MOCKED_BUILD_TYPE
import com.tangem.datasource.api.common.config.ApiEnvironmentConfig
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
import com.tangem.datasource.api.common.createNetworkLoggingInterceptor
import com.tangem.datasource.api.common.response.ApiResponseCallAdapterFactory
import com.tangem.datasource.api.utils.ConnectTimeout
import com.tangem.datasource.api.utils.ReadTimeout
import com.tangem.datasource.api.utils.WriteTimeout
import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.local.logs.AppLogsStore
import com.tangem.datasource.utils.NetworkLogsSaveInterceptor
import com.tangem.datasource.utils.addHeaders
import dagger.hilt.android.qualifiers.ApplicationContext
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.Invocation
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
/**
* A builder class for creating Retrofit API instances
*
* @property apiConfigsManager manages API configurations for different environments
* @property moshi moshi
* @property analyticsErrorHandler handles analytics-related errors
* @property context application context
* @property appLogsStore application logs store
*
[REDACTED_AUTHOR]
*/
@Singleton
internal class RetrofitApiBuilder @Inject constructor(
private val apiConfigsManager: ApiConfigsManager,
@NetworkMoshi private val moshi: Moshi,
private val analyticsErrorHandler: AnalyticsErrorHandler,
@ApplicationContext private val context: Context,
private val appLogsStore: AppLogsStore,
) {
/**
* Builds a Retrofit API instance for the specified API configuration ID
*
* @param apiConfigId the ID of the API configuration to use
* @param applyTimeoutAnnotations whether to apply timeout annotations to the requests. See [ReadTimeout], etc.
* @param timeouts optional timeouts for the requests
* @param logsSaving whether to enable logs saving
*
* @return an instance [T] of the specified API interface
*/
inline fun <reified T> build(
apiConfigId: ApiConfig.ID,
applyTimeoutAnnotations: Boolean,
timeouts: Timeouts? = null,
logsSaving: Boolean = true,
): T {
val environmentConfig = apiConfigsManager.getEnvironmentConfig(apiConfigId)
return Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.addCallAdapterFactory(ApiResponseCallAdapterFactory.create(analyticsErrorHandler))
.baseUrl(environmentConfig.baseUrl)
.client(
OkHttpClient.Builder()
.applyApiConfig(apiConfigId = apiConfigId, environmentConfig = environmentConfig)
.let {
if (applyTimeoutAnnotations) it.applyTimeoutAnnotations() else it
}
.applyTimeouts(timeouts = timeouts)
.let {
if (logsSaving) it.applyLogsSaving() else it
}
.addLoggers(apiConfigId = apiConfigId, context = context)
.build(),
)
.build()
.create(T::class.java)
}
data class Timeouts(
val callTimeoutSeconds: Long? = null,
val connectTimeoutSeconds: Long? = null,
val readTimeoutSeconds: Long? = null,
val writeTimeoutSeconds: Long? = null,
)
private fun OkHttpClient.Builder.applyApiConfig(
apiConfigId: ApiConfig.ID,
environmentConfig: ApiEnvironmentConfig,
): OkHttpClient.Builder {
return if (BuildConfig.TESTER_MENU_ENABLED || BuildConfig.BUILD_TYPE == MOCKED_BUILD_TYPE) {
addInterceptor(
interceptor = SwitchEnvironmentInterceptor(id = apiConfigId, apiConfigsManager = apiConfigsManager),
)
} else {
val headers = environmentConfig.headers
this.addHeaders(headers)
}
}
private fun OkHttpClient.Builder.applyTimeouts(timeouts: Timeouts?): OkHttpClient.Builder {
if (timeouts == null) return this
var b = this
if (timeouts.callTimeoutSeconds != null) {
b = b.callTimeout(timeouts.callTimeoutSeconds, TimeUnit.SECONDS)
}
if (timeouts.connectTimeoutSeconds != null) {
b = b.connectTimeout(timeouts.connectTimeoutSeconds, TimeUnit.SECONDS)
}
if (timeouts.readTimeoutSeconds != null) {
b = b.readTimeout(timeouts.readTimeoutSeconds, TimeUnit.SECONDS)
}
if (timeouts.writeTimeoutSeconds != null) {
b = b.writeTimeout(timeouts.writeTimeoutSeconds, TimeUnit.SECONDS)
}
return b
}
/**
* Apply timeout annotations [Interceptor].
* Add this [Interceptor] to [OkHttpClient] if use timeout annotations for retrofit requests.
*/
private fun OkHttpClient.Builder.applyTimeoutAnnotations(): OkHttpClient.Builder {
return addInterceptor(
Interceptor { chain ->
val request = chain.request()
val tag = request.tag(Invocation::class.java)
val connectionTimeout = tag?.method()?.getAnnotation(ConnectTimeout::class.java)
val readTimeout = tag?.method()?.getAnnotation(ReadTimeout::class.java)
val writeTimeout = tag?.method()?.getAnnotation(WriteTimeout::class.java)
chain
.run {
connectionTimeout?.let { withConnectTimeout(timeout = it.duration, unit = it.unit) } ?: this
}
.run {
readTimeout?.let { withReadTimeout(timeout = it.duration, unit = it.unit) } ?: this
}
.run {
writeTimeout?.let { withWriteTimeout(timeout = it.duration, unit = it.unit) } ?: this
}
.proceed(request)
},
)
}
private fun OkHttpClient.Builder.applyLogsSaving(): OkHttpClient.Builder {
return addInterceptor(
interceptor = NetworkLogsSaveInterceptor(appLogsStore),
)
}
private fun OkHttpClient.Builder.addLoggers(apiConfigId: ApiConfig.ID, context: Context): OkHttpClient.Builder {
if (apiConfigId in excludedApiForLogging) return this
return if (BuildConfig.LOG_ENABLED) {
addInterceptor(interceptor = ChuckerInterceptor(context))
addInterceptor(interceptor = createNetworkLoggingInterceptor())
} else {
this
}
}
private companion object {
val excludedApiForLogging: Set<ApiConfig.ID> = setOf(
// ApiConfig.ID.StakeKit,
)
}
}

View file

@ -1,21 +1,9 @@
package com.tangem.datasource.utils
import android.content.Context
import com.chuckerteam.chucker.api.ChuckerInterceptor
import com.tangem.datasource.BuildConfig
import com.tangem.datasource.api.common.SwitchEnvironmentInterceptor
import com.tangem.datasource.api.common.config.ApiConfig
import com.tangem.datasource.api.common.config.ApiConfig.Companion.MOCKED_BUILD_TYPE
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
import com.tangem.datasource.api.common.createNetworkLoggingInterceptor
import com.tangem.datasource.api.utils.ConnectTimeout
import com.tangem.datasource.api.utils.ReadTimeout
import com.tangem.datasource.api.utils.WriteTimeout
import com.tangem.utils.ProviderSuspend
import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.Invocation
/** Extension for adding headers [requestHeaders] to every [OkHttpClient] request */
internal fun OkHttpClient.Builder.addHeaders(vararg requestHeaders: RequestHeader): OkHttpClient.Builder {
@ -24,30 +12,6 @@ internal fun OkHttpClient.Builder.addHeaders(vararg requestHeaders: RequestHeade
)
}
/**
* Apply timeout annotations [Interceptor].
* Add this [Interceptor] to [OkHttpClient] if use timeout annotations for retrofit requests.
*/
internal fun OkHttpClient.Builder.applyTimeoutAnnotations(): OkHttpClient.Builder {
return addInterceptor(
Interceptor { chain ->
val request = chain.request()
val tag = request.tag(Invocation::class.java)
val connectionTimeout = tag?.method()?.getAnnotation(ConnectTimeout::class.java)
val readTimeout = tag?.method()?.getAnnotation(ReadTimeout::class.java)
val writeTimeout = tag?.method()?.getAnnotation(WriteTimeout::class.java)
chain.run {
connectionTimeout?.let { withConnectTimeout(timeout = it.duration, unit = it.unit) } ?: this
}.run {
readTimeout?.let { withReadTimeout(timeout = it.duration, unit = it.unit) } ?: this
}.run {
writeTimeout?.let { withWriteTimeout(timeout = it.duration, unit = it.unit) } ?: this
}.proceed(request)
},
)
}
/** Extension for adding headers [requestHeaders] to every [OkHttpClient] request */
internal fun OkHttpClient.Builder.addHeaders(
requestHeaders: Map<String, ProviderSuspend<String>>,
@ -66,44 +30,4 @@ internal fun OkHttpClient.Builder.addHeaders(
chain.proceed(request)
},
)
}
/**
* Extension for logging each [OkHttpClient] request
*
* @param context context
*/
internal fun OkHttpClient.Builder.addLoggers(context: Context? = null): OkHttpClient.Builder {
return if (BuildConfig.LOG_ENABLED) {
context?.let {
addInterceptor(interceptor = ChuckerInterceptor(it))
}
addInterceptor(interceptor = createNetworkLoggingInterceptor())
} else {
this
}
}
/**
* Apply api config
*
* @param id class of [ApiConfig]
* @param apiConfigsManager api configs manager
*/
internal fun OkHttpClient.Builder.applyApiConfig(
id: ApiConfig.ID,
apiConfigsManager: ApiConfigsManager,
): OkHttpClient.Builder {
return if (BuildConfig.TESTER_MENU_ENABLED || BuildConfig.BUILD_TYPE == MOCKED_BUILD_TYPE) {
addInterceptor(
interceptor = SwitchEnvironmentInterceptor(
id = id,
apiConfigsManager = apiConfigsManager,
),
)
} else {
val headers = apiConfigsManager.getEnvironmentConfig(id).headers
this.addHeaders(headers)
}
}