Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-15 15:20:48 +03:00
parent e45d91b15e
commit fc223990a4
10 changed files with 270 additions and 0 deletions

View file

@ -0,0 +1,104 @@
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
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
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 saveConversionData(refcode: String, campaign: String?) {
val data = AppsFlyerConversionData(refcode = refcode, campaign = campaign)
appsFlyerConversionStore.store(data)
}
override suspend fun bindRefcodeWithWallets(refcode: String, campaign: String?) = withContext(dispatchers.io) {
val walletIds = userWalletsStore.userWalletsSync.map { it.walletId.stringValue }
val result = tangemTechApi.bindWalletsByReferralCode(
body = BindWalletsByReferralCodeBody(
walletIds = walletIds,
refcode = refcode,
campaign = campaign,
),
)
val bindingData = ReferralWalletsBindingData(
refcode = refcode,
campaign = campaign,
isDone = result is ApiResponse.Success,
)
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
}
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)
private data class ReferralWalletsBindingData(
@Json(name = "refcode") val refcode: String,
@Json(name = "campaign") val campaign: String?,
@Json(name = "done") val isDone: Boolean,
)
private companion object {
val REFERRAL_WALLETS_BINDING_DATA_KEY by lazy { stringPreferencesKey(name = "referralWalletsBindingData") }
}
}

View file

@ -3,6 +3,7 @@ package com.tangem.data.wallets.di
import com.squareup.moshi.Moshi
import com.tangem.data.common.wallet.WalletServerBinder
import com.tangem.data.wallets.DefaultWalletNamesMigrationRepository
import com.tangem.data.wallets.DefaultWalletsPromoRepository
import com.tangem.data.wallets.DefaultWalletsRepository
import com.tangem.data.wallets.cold.DefaultColdMapDerivationsRepository
import com.tangem.data.wallets.derivations.DefaultDerivationsRepository
@ -21,6 +22,7 @@ import com.tangem.domain.wallets.derivations.DerivationsRepository
import com.tangem.domain.wallets.derivations.HotMapDerivationsRepository
import com.tangem.domain.wallets.hot.HotWalletAccessCodeAttemptsRepository
import com.tangem.domain.wallets.repository.WalletNamesMigrationRepository
import com.tangem.domain.wallets.repository.WalletsPromoRepository
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Binds
@ -66,6 +68,24 @@ internal object WalletsDataModule {
fun provideMigrateNamesRepository(appPreferencesStore: AppPreferencesStore): WalletNamesMigrationRepository {
return DefaultWalletNamesMigrationRepository(appPreferencesStore)
}
@Provides
@Singleton
fun provideWalletsPromoRepository(
appPreferencesStore: AppPreferencesStore,
tangemTechApi: TangemTechApi,
userWalletsStore: UserWalletsStore,
appsFlyerConversionStore: AppsFlyerConversionStore,
dispatchers: CoroutineDispatcherProvider,
): WalletsPromoRepository {
return DefaultWalletsPromoRepository(
appPreferencesStore = appPreferencesStore,
tangemTechApi = tangemTechApi,
userWalletsStore = userWalletsStore,
appsFlyerConversionStore = appsFlyerConversionStore,
dispatchers = dispatchers,
)
}
}
@Module