Updated on 2026-08-14

This commit is contained in:
Tangem 2023-06-26 19:37:57 +03:00
parent 407337ed00
commit 144876bd4b
12 changed files with 79 additions and 49 deletions

View file

@ -0,0 +1,16 @@
package com.tangem.tap.network.auth
import com.tangem.common.extensions.toHexString
import com.tangem.lib.auth.LazyAuthProvider
import com.tangem.tap.proxy.AppStateHolder
class LazyAuthProviderImpl(private val appStateHolder: AppStateHolder) : LazyAuthProvider {
override fun getCardPublicKeyProvider(): () -> String {
return { appStateHolder.getActualCard()?.cardPublicKey?.toHexString() ?: "" }
}
override fun getCardIdProvider(): () -> String {
return { appStateHolder.getActualCard()?.cardId ?: "" }
}
}

View file

@ -1,12 +0,0 @@
package com.tangem.tap.network.auth
import com.tangem.lib.auth.BasicAuthProvider
class TangemBasicAuthProvider(private val credentials: String?) : BasicAuthProvider {
override fun getCredentials(): Map<String, String> = if (credentials == null) {
mapOf()
} else {
mapOf("Authorization" to "Basic $credentials")
}
}

View file

@ -1,10 +1,9 @@
package com.tangem.tap.network.auth.di
import com.tangem.datasource.config.ConfigManager
import com.tangem.lib.auth.AuthProvider
import com.tangem.lib.auth.BasicAuthProvider
import com.tangem.lib.auth.LazyAuthProvider
import com.tangem.tap.network.auth.AuthProviderImpl
import com.tangem.tap.network.auth.TangemBasicAuthProvider
import com.tangem.tap.network.auth.LazyAuthProviderImpl
import com.tangem.tap.proxy.AppStateHolder
import dagger.Module
import dagger.Provides
@ -24,7 +23,7 @@ class AuthModule {
@Provides
@Singleton
fun provideTangemBasicAuthProvider(configManager: ConfigManager): BasicAuthProvider {
return TangemBasicAuthProvider(configManager.config.tangemComAuthorization)
fun provideLazyAuthProvider(appStateHolder: AppStateHolder): LazyAuthProvider {
return LazyAuthProviderImpl(appStateHolder)
}
}

View file

@ -24,6 +24,6 @@ interface PromotionApi {
@POST("promotion/validate")
suspend fun validate(@Body request: ValidateRequestBody): ValidateResponse
@GET("promotion/award")
@POST("promotion/award")
suspend fun requestAward(@Body request: AwardRequestBody): AwardResponse
}

View file

@ -13,6 +13,6 @@ abstract class AbstractPromotionResponse {
data class Error(
@Json(name = "code") val code: Int,
@Json(name = "description") val description: String,
@Json(name = "description") val message: String,
)
}

View file

@ -7,5 +7,6 @@ import com.squareup.moshi.Json
*/
data class AwardRequestBody(
@Json(name = "walletId") val walletId: String,
@Json(name = "address") val address: String,
@Json(name = "programName") val programName: String,
)

View file

@ -7,9 +7,9 @@ import com.squareup.moshi.Json
*/
data class PromotionInfoResponse(
@Json(name = "status") val status: Status?,
@Json(name = "awardForNewCard") val awardForNewCard: Float?,
@Json(name = "awardForOldCard") val awardForOldCard: Float?,
@Json(name = "awardPaymentToken") val awardPaymentToken: TokenInfo?,
@Json(name = "awardForNewCard") val awardForNewCard: Double?,
@Json(name = "awardForOldCard") val awardForOldCard: Double?,
@Json(name = "awardPaymentToken") val awardPaymentToken: TokenData?,
@Json(name = "error") override val error: Error? = null,
) : AbstractPromotionResponse() {
@ -24,18 +24,13 @@ data class PromotionInfoResponse(
FINISHED("finished"),
}
data class TokenInfo(
data class TokenData(
@Json(name = "id") val id: String,
@Json(name = "name") val name: String,
@Json(name = "symbol") val symbol: String,
@Json(name = "active") val active: Boolean,
@Json(name = "networks") val networks: List<Network>,
) {
data class Network(
@Json(name = "networkId") val networkId: String,
@Json(name = "exchangeable") val exchangeable: Boolean,
@Json(name = "contractAddress") val contractAddress: String,
@Json(name = "decimalCount") val decimalCount: Int,
)
}
@Json(name = "networkId") val networkId: String,
@Json(name = "contractAddress") val contractAddress: String,
@Json(name = "decimalCount") val decimalCount: Int,
)
}

View file

@ -4,10 +4,13 @@ import com.squareup.moshi.Moshi
import com.tangem.datasource.api.paymentology.PaymentologyApi
import com.tangem.datasource.api.promotion.PromotionApi
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.utils.LazyRequestHeader
import com.tangem.datasource.utils.RequestHeader.*
import com.tangem.datasource.utils.addHeaders
import com.tangem.datasource.utils.addLazyHeaders
import com.tangem.datasource.utils.allowLogging
import com.tangem.lib.auth.AuthProvider
import com.tangem.lib.auth.BuildConfig
import com.tangem.lib.auth.LazyAuthProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -60,10 +63,10 @@ class NetworkModule {
@Provides
@Singleton
@PromotionOneInch
fun providePromotionOneInchApi(authProvider: AuthProvider, @NetworkMoshi moshi: Moshi): PromotionApi {
fun providePromotionOneInchApi(authProvider: LazyAuthProvider, @NetworkMoshi moshi: Moshi): PromotionApi {
val okClient = OkHttpClient.Builder()
.addHeaders(
AuthenticationHeader(authProvider),
.addLazyHeaders(
LazyRequestHeader.LazyAuthenticationHeader(authProvider),
)
.allowLogging()
.callTimeout(API_ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
@ -77,7 +80,7 @@ class NetworkModule {
private fun createBasePromotionRetrofit(okHttpClient: OkHttpClient, moshi: Moshi): PromotionApi {
return Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(PROMOTION_BASE_URL)
.baseUrl(if (BuildConfig.DEBUG) DEV_TANGEM_TECH_BASE_URL else PROD_TANGEM_TECH_BASE_URL)
.client(okHttpClient)
.build()
.create(PromotionApi::class.java)
@ -87,8 +90,6 @@ class NetworkModule {
const val PROD_TANGEM_TECH_BASE_URL = "https://api.tangem-tech.com/v1/"
const val DEV_TANGEM_TECH_BASE_URL = "https://devapi.tangem-tech.com/v1/"
const val PROMOTION_BASE_URL = "https://tangem.com/v1/"
const val PAYMENTOLOGY_BASE_URL: String = "https://paymentologygate.oa.r.appspot.com/"
const val API_ONE_INCH_TIMEOUT_MS = 5000L
}

View file

@ -21,6 +21,20 @@ internal fun OkHttpClient.Builder.addHeaders(vararg requestHeaders: RequestHeade
)
}
internal fun OkHttpClient.Builder.addLazyHeaders(vararg requestHeaders: LazyRequestHeader): OkHttpClient.Builder {
return addInterceptor(
Interceptor { chain ->
val request = chain.request().newBuilder().apply {
requestHeaders
.flatMap(LazyRequestHeader::values)
.forEach { addHeader(it.first, it.second.invoke()) }
}.build()
chain.proceed(request)
},
)
}
/**
* Extension for logging each [OkHttpClient] request
*

View file

@ -1,6 +1,7 @@
package com.tangem.datasource.utils
import com.tangem.lib.auth.AuthProvider
import com.tangem.lib.auth.LazyAuthProvider
/**
* Presentation of request header
@ -15,7 +16,17 @@ sealed class RequestHeader(vararg pairs: Pair<String, String>) {
object CacheControlHeader : RequestHeader("Cache-Control" to "max-age=600")
class AuthenticationHeader(authProvider: AuthProvider) : RequestHeader(
"card_public_key" to authProvider.getCardPublicKey(),
"card_id" to authProvider.getCardId(),
"card_public_key" to authProvider.getCardPublicKey(),
)
}
sealed class LazyRequestHeader(vararg pairs: Pair<String, () -> String>) {
val values: List<Pair<String, () -> String>> = pairs.toList()
class LazyAuthenticationHeader(authProvider: LazyAuthProvider) : LazyRequestHeader(
"card_id" to authProvider.getCardIdProvider(),
"card_public_key" to authProvider.getCardPublicKeyProvider(),
)
}

View file

@ -1,9 +0,0 @@
package com.tangem.lib.auth
/**
* Provides auth for Tangem WebView
*/
interface BasicAuthProvider {
fun getCredentials(): Map<String, String>
}

View file

@ -0,0 +1,14 @@
package com.tangem.lib.auth
/**
* Provides auth for tangemTech API
*/
interface LazyAuthProvider {
/**
* Returns authToken for tangem tech api
*/
fun getCardPublicKeyProvider(): () -> String
fun getCardIdProvider(): () -> String
}