diff --git a/data/source/preferences/src/main/kotlin/com/tangem/data/source/preferences/storage/UsedCardsPrefStorage.kt b/data/source/preferences/src/main/kotlin/com/tangem/data/source/preferences/storage/UsedCardsPrefStorage.kt index b1fbf61361..de987e84fc 100644 --- a/data/source/preferences/src/main/kotlin/com/tangem/data/source/preferences/storage/UsedCardsPrefStorage.kt +++ b/data/source/preferences/src/main/kotlin/com/tangem/data/source/preferences/storage/UsedCardsPrefStorage.kt @@ -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? = null, diff --git a/features/learn2earn/impl/build.gradle.kts b/features/learn2earn/impl/build.gradle.kts index 9e390b1f67..bd20fe9bf6 100644 --- a/features/learn2earn/impl/build.gradle.kts +++ b/features/learn2earn/impl/build.gradle.kts @@ -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) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultLearn2earnRepository.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultLearn2earnRepository.kt new file mode 100644 index 0000000000..8443d28b82 --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultLearn2earnRepository.kt @@ -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 { + 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 { + 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" + } +} \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultPreferenceStorage.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultPreferenceStorage.kt new file mode 100644 index 0000000000..92f5d7da83 --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultPreferenceStorage.kt @@ -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) +} \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultUsedCardsPreferenceStorage.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultUsedCardsPreferenceStorage.kt new file mode 100644 index 0000000000..a2f3a8cab4 --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultUsedCardsPreferenceStorage.kt @@ -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() +} \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/api/Learn2earnPreferenceStorage.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/api/Learn2earnPreferenceStorage.kt new file mode 100644 index 0000000000..78f548febc --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/api/Learn2earnPreferenceStorage.kt @@ -0,0 +1,10 @@ +package com.tangem.feature.learn2earn.data.api + +/** +[REDACTED_AUTHOR] + */ +interface Learn2earnPreferenceStorage { + var promoCode: String? + var promotionInfo: String? + var alreadyReceivedAward: Boolean +} \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/api/Learn2earnRepository.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/api/Learn2earnRepository.kt new file mode 100644 index 0000000000..6641bc36c8 --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/api/Learn2earnRepository.kt @@ -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 + suspend fun getPromotionInfo(): Result + 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 +} \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/api/UsedCardsPreferenceStorage.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/api/UsedCardsPreferenceStorage.kt new file mode 100644 index 0000000000..c7d1174496 --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/api/UsedCardsPreferenceStorage.kt @@ -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 +} \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/di/Learn2earnDataModule.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/di/Learn2earnDataModule.kt new file mode 100644 index 0000000000..9d6e5a0507 --- /dev/null +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/di/Learn2earnDataModule.kt @@ -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, + ) + } +} \ No newline at end of file