Updated on 2026-08-14

This commit is contained in:
Tangem 2023-06-19 08:47:01 +03:00
parent e16fe69575
commit 353c7a2397
19 changed files with 256 additions and 7 deletions

View file

@ -0,0 +1,7 @@
package com.tangem.tap.network.auth
import com.tangem.lib.auth.BasicAuthProvider
class TangemBasicAuthProvider(private val credentials: String?) : BasicAuthProvider {
override fun getCredentials(): String? = credentials
}

View file

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

View file

@ -0,0 +1,38 @@
package com.tangem.datasource.api.promotion
import com.tangem.datasource.api.promotion.models.*
import retrofit2.http.*
/**
[REDACTED_AUTHOR]
* Api details
* https://www.notion.so/tangem/Promotion-Program-API-0907159c3fdb4975aac761be632f44da
*/
interface PromotionApi {
@Headers("Cache-Control: max-age=$CACHE_CONTROL_SECONDS")
@GET("promotion")
suspend fun getPromotionInfo(@Query("programName") name: String): PromotionInfoResponse
@POST("promotion/code/validate")
suspend fun codeValidate(@Body request: CodeValidateRequestBody): CodeValidateResponse
@POST("promotion/code/award")
suspend fun codeAward(@Body request: CodeAwardRequestBody): CodeAwardResponse
@POST("promotion/validate")
suspend fun validate(@Body request: ValidateRequestBody): ValidateResponse
@GET("promotion/award")
suspend fun award(@Body request: AwardRequestBody): AwardResponse
companion object {
const val ONE_INCH_TIMEOUT_MS = 5000L
const val CACHE_CONTROL_SECONDS = 3600
}
}

View file

@ -0,0 +1,20 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
abstract class AbstractPromotionResponse {
abstract val error: Error?
fun isError(): Boolean = error != null
data class Error(
@Json(name = "code") val code: Int,
@Json(name = "description") val description: String,
) {
companion object
}
}

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class AwardRequestBody(
@Json(name = "walletId") val walletId: String,
@Json(name = "programName") val programName: String,
)

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class AwardResponse(
@Json(name = "status") val status: Boolean?,
@Json(name = "error") override val error: Error? = null,
) : AbstractPromotionResponse()

View file

@ -0,0 +1,12 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class CodeAwardRequestBody(
@Json(name = "walletId") val walletId: String,
@Json(name = "address") val address: String,
@Json(name = "code") val code: String?,
)

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class CodeAwardResponse(
@Json(name = "status") val status: Boolean?,
@Json(name = "error") override val error: Error? = null,
) : AbstractPromotionResponse()

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class CodeValidateRequestBody(
@Json(name = "walletId") val walletId: String,
@Json(name = "code") val code: String?,
)

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class CodeValidateResponse(
@Json(name = "valid") val valid: Boolean?,
@Json(name = "error") override val error: Error? = null,
) : AbstractPromotionResponse()

View file

@ -0,0 +1,41 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
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 = "error") override val error: Error? = null,
) : AbstractPromotionResponse() {
enum class Status(val value: String) {
@Json(name = "pending")
PENDING("pending"),
@Json(name = "active")
ACTIVE("active"),
@Json(name = "finished")
FINISHED("finished"),
}
data class TokenInfo(
@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,
)
}
}

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class ValidateRequestBody(
@Json(name = "walletId") val walletId: String,
@Json(name = "programName") val programName: String,
)

View file

@ -0,0 +1,11 @@
package com.tangem.datasource.api.promotion.models
import com.squareup.moshi.Json
/**
[REDACTED_AUTHOR]
*/
data class ValidateResponse(
@Json(name = "valid") val valid: Boolean?,
@Json(name = "error") override val error: Error? = null,
) : AbstractPromotionResponse()

View file

@ -1,11 +1,6 @@
package com.tangem.datasource.config
import com.tangem.blockchain.common.BlockchainSdkConfig
import com.tangem.blockchain.common.BlockchairCredentials
import com.tangem.blockchain.common.GetBlockCredentials
import com.tangem.blockchain.common.NowNodeCredentials
import com.tangem.blockchain.common.QuickNodeCredentials
import com.tangem.blockchain.common.TonCenterCredentials
import com.tangem.blockchain.common.*
import com.tangem.datasource.config.ConfigManager.Companion.IS_CREATING_TWIN_CARDS_ALLOWED
import com.tangem.datasource.config.ConfigManager.Companion.IS_SENDING_TO_PAY_ID_ENABLED
import com.tangem.datasource.config.ConfigManager.Companion.IS_TOP_UP_ENABLED
@ -111,6 +106,7 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
zendesk = configValues.zendesk,
swapReferrerAccount = configValues.swapReferrerAccount,
walletConnectProjectId = configValues.walletConnectProjectId,
tangemComAuthorization = configValues.tangemComAuthorization,
)
}
}

View file

@ -19,4 +19,5 @@ data class Config(
val zendesk: ZendeskConfig? = null,
val swapReferrerAccount: SwapReferrerAccount? = null,
val walletConnectProjectId: String = "",
val tangemComAuthorization: String? = null,
)

View file

@ -38,6 +38,7 @@ class ConfigValueModel(
val swapReferrerAccount: SwapReferrerAccount?,
val kaspaSecondaryApiUrl: String,
val walletConnectProjectId: String,
val tangemComAuthorization: String?,
)
data class AppsFlyer(

View file

@ -2,10 +2,12 @@ package com.tangem.datasource.di
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.RequestHeader.*
import com.tangem.datasource.utils.addHeaders
import com.tangem.datasource.utils.allowLogging
import com.tangem.lib.auth.AuthProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -13,6 +15,7 @@ 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
@ -54,10 +57,38 @@ class NetworkModule {
.create(PaymentologyApi::class.java)
}
@Provides
@Singleton
@PromotionOneInch
fun providePromotionOneInchApi(authProvider: AuthProvider, @NetworkMoshi moshi: Moshi): PromotionApi {
val okClient = OkHttpClient.Builder()
.addHeaders(
AuthenticationHeader(authProvider),
)
.allowLogging()
.callTimeout(PromotionApi.ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.connectTimeout(PromotionApi.ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.readTimeout(PromotionApi.ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.writeTimeout(PromotionApi.ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.build()
return createBasePromotionRetrofit(okClient, moshi)
}
private fun createBasePromotionRetrofit(okHttpClient: OkHttpClient, moshi: Moshi): PromotionApi {
return Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(PROMOTION_BASE_URL)
.client(okHttpClient)
.build()
.create(PromotionApi::class.java)
}
private companion object {
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/"
private const val PAYMENTOLOGY_BASE_URL: String = "https://paymentologygate.oa.r.appspot.com/"
const val PROMOTION_BASE_URL = "https://tangem.com/v1/"
const val PAYMENTOLOGY_BASE_URL: String = "https://paymentologygate.oa.r.appspot.com/"
}
}

View file

@ -0,0 +1,8 @@
package com.tangem.datasource.di
import javax.inject.Qualifier
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class PromotionOneInch

View file

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