Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-21 14:21:10 +04:00
parent fc223990a4
commit 9fd13fdc46
11 changed files with 149 additions and 176 deletions

View file

@ -1,15 +1,11 @@
package com.tangem.data.wallets
import androidx.datastore.preferences.core.stringPreferencesKey
import arrow.core.Option
import arrow.core.toOption
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.BindWalletsByReferralCodeBody
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
import com.tangem.datasource.local.preferences.utils.storeObject
@ -17,7 +13,6 @@ import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.wallets.models.AppsFlyerConversionData
import com.tangem.domain.wallets.repository.WalletsPromoRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.runSuspendCatching
import kotlinx.coroutines.withContext
import timber.log.Timber
@ -25,69 +20,57 @@ internal class DefaultWalletsPromoRepository(
private val appPreferencesStore: AppPreferencesStore,
private val tangemTechApi: TangemTechApi,
private val userWalletsStore: UserWalletsStore,
private val appsFlyerConversionStore: AppsFlyerConversionStore,
private val dispatchers: CoroutineDispatcherProvider,
) : WalletsPromoRepository {
override suspend fun getConversionData(): Option<AppsFlyerConversionData> {
return runSuspendCatching { appsFlyerConversionStore.get() }.getOrNull().toOption()
override suspend fun bindRefcodeWithWallets(conversionData: AppsFlyerConversionData) = withContext(dispatchers.io) {
val savedBindingData = getSavedBindingData()
when {
savedBindingData == null -> {
// first time binding
saveBindingData(refcode = conversionData.refcode, campaign = conversionData.campaign)
bind(refcode = conversionData.refcode, campaign = conversionData.campaign)
}
!savedBindingData.isDone -> {
// try again
bind(refcode = savedBindingData.refcode, campaign = savedBindingData.campaign)
}
}
}
override suspend fun saveConversionData(refcode: String, campaign: String?) {
val data = AppsFlyerConversionData(refcode = refcode, campaign = campaign)
override suspend fun retryBindRefcodeWithWallets() {
val savedBindingData = getSavedBindingData()
appsFlyerConversionStore.store(data)
if (savedBindingData != null) {
bind(refcode = savedBindingData.refcode, campaign = savedBindingData.campaign)
} else {
Timber.i("retryBindRefcodeWithWallets: Binding data isn't required")
}
}
override suspend fun bindRefcodeWithWallets(refcode: String, campaign: String?) = withContext(dispatchers.io) {
private suspend fun getSavedBindingData(): ReferralWalletsBindingData? {
return appPreferencesStore.getObjectSyncOrNull(key = REFERRAL_WALLETS_BINDING_DATA_KEY)
}
private suspend fun saveBindingData(refcode: String, campaign: String?) {
val bindingData = ReferralWalletsBindingData(refcode = refcode, campaign = campaign, isDone = false)
appPreferencesStore.storeObject(key = REFERRAL_WALLETS_BINDING_DATA_KEY, value = bindingData)
}
private suspend fun bind(refcode: String, campaign: String?) {
val walletIds = userWalletsStore.userWalletsSync.map { it.walletId.stringValue }
val result = tangemTechApi.bindWalletsByReferralCode(
body = BindWalletsByReferralCodeBody(
walletIds = walletIds,
refcode = refcode,
campaign = campaign,
),
body = BindWalletsByReferralCodeBody(walletIds = walletIds, refcode = refcode, campaign = campaign),
)
val bindingData = ReferralWalletsBindingData(
refcode = refcode,
campaign = campaign,
isDone = result is ApiResponse.Success,
)
if (result is ApiResponse.Success) {
val successData = ReferralWalletsBindingData(refcode = refcode, campaign = campaign, isDone = true)
appPreferencesStore.storeObject(key = REFERRAL_WALLETS_BINDING_DATA_KEY, value = bindingData)
result.getOrThrow()
}
override suspend fun bindSavedRefcodeWithWallets(): AppsFlyerConversionData {
val bindingData = appPreferencesStore.getObjectSyncOrNull<ReferralWalletsBindingData>(
key = REFERRAL_WALLETS_BINDING_DATA_KEY,
)
if (bindingData == null) {
val exception = IllegalStateException("No saved referral wallets binding data found")
Timber.e(exception)
throw exception
appPreferencesStore.storeObject(key = REFERRAL_WALLETS_BINDING_DATA_KEY, value = successData)
}
val conversionData = AppsFlyerConversionData(
refcode = bindingData.refcode,
campaign = bindingData.campaign,
)
if (bindingData.isDone) {
Timber.i("Referral code ${bindingData.refcode} already bound with wallets")
return conversionData
}
bindRefcodeWithWallets(
refcode = bindingData.refcode,
campaign = bindingData.campaign,
)
return conversionData
}
@JsonClass(generateAdapter = true)

View file

@ -75,14 +75,12 @@ internal object WalletsDataModule {
appPreferencesStore: AppPreferencesStore,
tangemTechApi: TangemTechApi,
userWalletsStore: UserWalletsStore,
appsFlyerConversionStore: AppsFlyerConversionStore,
dispatchers: CoroutineDispatcherProvider,
): WalletsPromoRepository {
return DefaultWalletsPromoRepository(
appPreferencesStore = appPreferencesStore,
tangemTechApi = tangemTechApi,
userWalletsStore = userWalletsStore,
appsFlyerConversionStore = appsFlyerConversionStore,
dispatchers = dispatchers,
)
}