Updated on 2026-08-14

This commit is contained in:
Tangem 2023-06-19 08:50:47 +03:00
parent 353c7a2397
commit 7e765758b4
9 changed files with 268 additions and 18 deletions

View file

@ -68,6 +68,10 @@ class UsedCardsPrefStorage internal constructor(
return cardInfo.isActivationStarted && !cardInfo.isActivationFinished
}
fun hadFinishedActivation(): Boolean {
return restore().any { it.isActivationFinished }
}
private fun findCardInfo(
cardId: String,
list: MutableList<DataSourceUsedCardInfo>? = null,

View file

@ -8,38 +8,45 @@ plugins {
}
dependencies {
/** AndroidX */
implementation(deps.androidx.activity.compose)
implementation(deps.androidx.core.ktx)
implementation(deps.androidx.appCompat)
implementation(deps.androidx.constraintLayout)
/** Compose */
implementation(deps.compose.material)
implementation(deps.compose.foundation)
implementation(deps.compose.constraintLayout)
implementation(deps.compose.ui)
implementation(deps.compose.ui.tooling)
implementation(deps.compose.animation)
implementation(deps.compose.navigation)
implementation(deps.compose.navigation.hilt)
/** Core modules */
implementation(project(":common"))
implementation(project(":core:featuretoggles"))
implementation(project(":core:datasource"))
implementation(project(":core:analytics"))
implementation(project(":core:utils"))
implementation(project(":core:ui"))
implementation(project(":core:res"))
implementation(project(":data:source:preferences"))
implementation(project(":libs:auth"))
implementation(deps.material)
/** AndroidX */
implementation(deps.androidx.core.ktx)
implementation(deps.androidx.appCompat)
implementation(deps.androidx.activity.compose)
implementation(deps.androidx.constraintLayout)
implementation(deps.androidx.browser)
/** Compose */
implementation(deps.compose.material)
implementation(deps.compose.foundation)
implementation(deps.compose.ui)
implementation(deps.compose.ui.tooling)
/** Tangem libraries */
// TODO: fixme: delete if later it doesn't needed
// TODO: 1inch: delete if later it doesn't needed
// implementation(deps.tangem.card.core)
// implementation(deps.tangem.card.android) {
// exclude(module = "joda-time")
// }
/** Network */
implementation(deps.krateSharedPref)
implementation(deps.moshi)
implementation(deps.moshi.kotlin)
implementation(deps.retrofit)
implementation(deps.retrofit.moshi)
/** Other libraries */
implementation(deps.kotlin.immutable.collections)
implementation(deps.kotlin.serialization)

View file

@ -0,0 +1,111 @@
package com.tangem.feature.learn2earn.data
import com.squareup.moshi.Moshi
import com.tangem.datasource.api.promotion.PromotionApi
import com.tangem.datasource.api.promotion.models.*
import com.tangem.feature.learn2earn.data.api.Learn2earnPreferenceStorage
import com.tangem.feature.learn2earn.data.api.Learn2earnRepository
import com.tangem.feature.learn2earn.data.api.UsedCardsPreferenceStorage
import timber.log.Timber
/**
[REDACTED_AUTHOR]
*/
internal class DefaultLearn2earnRepository(
private val preferencesStorage: Learn2earnPreferenceStorage,
private val usedCardsPreferenceStorage: UsedCardsPreferenceStorage,
private val moshi: Moshi,
private val api: PromotionApi,
) : Learn2earnRepository {
private val promotionInfoAdapter = moshi.adapter(PromotionInfoResponse::class.java)
override fun isHadActivatedCards(): Boolean {
return usedCardsPreferenceStorage.isHadActivatedCards()
}
override fun getPromoCode(): String? {
return preferencesStorage.promoCode
}
override fun savePromoCode(code: String) {
preferencesStorage.promoCode = code
}
override fun getProgramName(): String {
return PROGRAM_NAME
}
override fun isAlreadyReceivedAward(): Boolean {
return preferencesStorage.alreadyReceivedAward
}
override suspend fun requestAwardByCode(walletId: String, address: String): Result<Boolean> {
return runCatching {
api.codeAward(CodeAwardRequestBody(walletId, address, getPromoCode()))
}.fold(
onSuccess = { response ->
val alreadyReceived = response.status ?: false
preferencesStorage.alreadyReceivedAward = alreadyReceived
Result.success(alreadyReceived)
},
onFailure = { exception -> Result.failure(exception) },
)
}
override suspend fun getPromotionInfo(): Result<PromotionInfoResponse> {
val info = restorePromotionInfo()
return if (info?.status == PromotionInfoResponse.Status.FINISHED) {
Result.success(info)
} else {
runCatching { api.getPromotionInfo(getProgramName()) }
.fold(
onSuccess = { infoResponse ->
savePromotionInfo(infoResponse)
Result.success(infoResponse)
},
onFailure = { exception -> Result.failure(exception) },
)
}
}
override suspend fun validate(walletId: String): ValidateResponse {
return api.validate(ValidateRequestBody(walletId, getProgramName()))
}
override suspend fun award(walletId: String): AwardResponse {
return api.award(AwardRequestBody(walletId, getProgramName()))
}
override suspend fun codeValidate(walletId: String, code: String?): CodeValidateResponse {
return api.codeValidate(CodeValidateRequestBody(walletId, code))
}
override suspend fun codeAward(walletId: String, address: String, code: String?): CodeAwardResponse {
return api.codeAward(CodeAwardRequestBody(walletId, address, code))
}
private fun restorePromotionInfo(): PromotionInfoResponse? {
return try {
preferencesStorage.promotionInfo?.let { promotionInfoAdapter.fromJson(it) }
} catch (ex: Exception) {
Timber.e(ex)
preferencesStorage.promotionInfo = null
null
}
}
private fun savePromotionInfo(infoResponse: PromotionInfoResponse) {
try {
preferencesStorage.promotionInfo = promotionInfoAdapter.toJson(infoResponse)
} catch (ex: Exception) {
Timber.e(ex)
preferencesStorage.promotionInfo = null
}
}
private companion object {
const val PROGRAM_NAME: String = "1inch"
}
}

View file

@ -0,0 +1,20 @@
package com.tangem.feature.learn2earn.data
import android.content.Context
import com.tangem.feature.learn2earn.data.api.Learn2earnPreferenceStorage
import hu.autsoft.krate.SimpleKrate
import hu.autsoft.krate.booleanPref
import hu.autsoft.krate.default.withDefault
import hu.autsoft.krate.stringPref
/**
[REDACTED_AUTHOR]
*/
internal class DefaultPreferenceStorage(
context: Context,
) : SimpleKrate(context = context, name = "Lear2earnPromotion"), Learn2earnPreferenceStorage {
override var promoCode: String? by stringPref().withDefault(null)
override var promotionInfo: String? by stringPref().withDefault(null)
override var alreadyReceivedAward: Boolean by booleanPref().withDefault(false)
}

View file

@ -0,0 +1,14 @@
package com.tangem.feature.learn2earn.data
import com.tangem.data.source.preferences.storage.UsedCardsPrefStorage
import com.tangem.feature.learn2earn.data.api.UsedCardsPreferenceStorage
/**
[REDACTED_AUTHOR]
*/
class DefaultUsedCardsPreferenceStorage(
private val usedCardsPrefStorage: UsedCardsPrefStorage,
) : UsedCardsPreferenceStorage {
override fun isHadActivatedCards(): Boolean = usedCardsPrefStorage.hadFinishedActivation()
}

View file

@ -0,0 +1,10 @@
package com.tangem.feature.learn2earn.data.api
/**
[REDACTED_AUTHOR]
*/
interface Learn2earnPreferenceStorage {
var promoCode: String?
var promotionInfo: String?
var alreadyReceivedAward: Boolean
}

View file

@ -0,0 +1,20 @@
package com.tangem.feature.learn2earn.data.api
import com.tangem.datasource.api.promotion.models.*
/**
[REDACTED_AUTHOR]
*/
interface Learn2earnRepository {
fun isHadActivatedCards(): Boolean
fun getPromoCode(): String?
fun savePromoCode(code: String)
fun getProgramName(): String
fun isAlreadyReceivedAward(): Boolean
suspend fun requestAwardByCode(walletId: String, address: String): Result<Boolean>
suspend fun getPromotionInfo(): Result<PromotionInfoResponse>
suspend fun validate(walletId: String): ValidateResponse
suspend fun award(walletId: String): AwardResponse
suspend fun codeValidate(walletId: String, code: String?): CodeValidateResponse
suspend fun codeAward(walletId: String, address: String, code: String?): CodeAwardResponse
}

View file

@ -0,0 +1,9 @@
package com.tangem.feature.learn2earn.data.api
/**
[REDACTED_AUTHOR]
* An interface that encapsulates access to deprecated PreferencesDataSource.usedCardsPrefStorage.
*/
interface UsedCardsPreferenceStorage {
fun isHadActivatedCards(): Boolean
}

View file

@ -0,0 +1,55 @@
package com.tangem.feature.learn2earn.data.di
import android.content.Context
import com.squareup.moshi.Moshi
import com.tangem.data.source.preferences.PreferencesDataSource
import com.tangem.datasource.api.promotion.PromotionApi
import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.di.PromotionOneInch
import com.tangem.feature.learn2earn.data.DefaultLearn2earnRepository
import com.tangem.feature.learn2earn.data.DefaultPreferenceStorage
import com.tangem.feature.learn2earn.data.DefaultUsedCardsPreferenceStorage
import com.tangem.feature.learn2earn.data.api.Learn2earnPreferenceStorage
import com.tangem.feature.learn2earn.data.api.Learn2earnRepository
import com.tangem.feature.learn2earn.data.api.UsedCardsPreferenceStorage
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class Learn2earnDataModule {
@Provides
@Singleton
fun providePreferenceStorage(@ApplicationContext context: Context): Learn2earnPreferenceStorage {
return DefaultPreferenceStorage(context)
}
@Provides
@Singleton
fun provideDeprecatedPreferenceDataSource(
preferenceDataSource: PreferencesDataSource,
): UsedCardsPreferenceStorage {
return DefaultUsedCardsPreferenceStorage(preferenceDataSource.usedCardsPrefStorage)
}
@Provides
@Singleton
fun provideRepository(
preferenceStorage: Learn2earnPreferenceStorage,
usedCardsPreferenceStorage: UsedCardsPreferenceStorage,
@NetworkMoshi moshi: Moshi,
@PromotionOneInch promotionApi: PromotionApi,
): Learn2earnRepository {
return DefaultLearn2earnRepository(
preferencesStorage = preferenceStorage,
usedCardsPreferenceStorage = usedCardsPreferenceStorage,
moshi = moshi,
api = promotionApi,
)
}
}