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

@ -73,7 +73,7 @@ class AppsFlyerDeepLinkListener @Inject constructor(
private fun storeConversionData(refcode: String, campaign: String?) {
coroutineScope.launch {
mutex.withLock {
appsFlyerConversionStore.store(
appsFlyerConversionStore.storeIfAbsent(
value = AppsFlyerConversionData(refcode = refcode, campaign = campaign),
)
}

View file

@ -30,10 +30,10 @@ class AppsFlyerClient @AssistedInject constructor(
setAppId(context.packageName)
setDebugLog(true)
init(apiKey, ConversionListener, context)
subscribeForDeepLink(appsFlyerDeepLinkListener)
init(apiKey, ConversionListener, context)
Timber.i("Starting AppsFlyer SDK")
start(context, apiKey, InitializationListener)
Timber.i("AppsFlyer SDK started")

View file

@ -39,57 +39,57 @@ class AppsFlyerDeepLinkListenerTest {
fun onDeepLinking(model: OnDeepLinkingModel) = runTest {
listener.onDeepLinking(p0 = model.deepLinkResult)
if (model.shouldStore) {
val value = AppsFlyerConversionData(refcode = SUCCESS_REFCODE, campaign = SUCCESS_CAMPAIGN)
coVerify { appsFlyerConversionStore.store(value = value) }
} else {
coVerify(inverse = true) { appsFlyerConversionStore.store(value = any()) }
}
if (model.shouldStore) {
val value = AppsFlyerConversionData(refcode = SUCCESS_REFCODE, campaign = SUCCESS_CAMPAIGN)
coVerify { appsFlyerConversionStore.storeIfAbsent(value = value) }
} else {
coVerify(inverse = true) { appsFlyerConversionStore.storeIfAbsent(value = any()) }
}
}
private fun provideTestModels(): List<OnDeepLinkingModel> {
return listOf(
// DeepLinkResult.Status.NOT_FOUND
OnDeepLinkingModel(
deepLinkResult = DeepLinkResult(null, null),
shouldStore = false,
return listOf(
// DeepLinkResult.Status.NOT_FOUND
OnDeepLinkingModel(
deepLinkResult = DeepLinkResult(null, null),
shouldStore = false,
),
// DeepLinkResult.Status.ERROR
OnDeepLinkingModel(
deepLinkResult = DeepLinkResult(null, DeepLinkResult.Error.NETWORK),
shouldStore = false,
),
// DeepLinkResult.Status.FOUND
OnDeepLinkingModel(
deepLinkResult = createFoundDeepLink(
deepLinkValue = AppsFlyerDeepLinkListener.REFERRAL_DEEP_LINK_VALUE,
refcode = SUCCESS_REFCODE,
campaign = SUCCESS_CAMPAIGN,
),
// DeepLinkResult.Status.ERROR
OnDeepLinkingModel(
deepLinkResult = DeepLinkResult(null, DeepLinkResult.Error.NETWORK),
shouldStore = false,
shouldStore = true,
),
OnDeepLinkingModel(
deepLinkResult = createFoundDeepLink(
deepLinkValue = AppsFlyerDeepLinkListener.REFERRAL_DEEP_LINK_VALUE,
refcode = "",
campaign = SUCCESS_CAMPAIGN,
),
// DeepLinkResult.Status.FOUND
OnDeepLinkingModel(
deepLinkResult = createFoundDeepLink(
deepLinkValue = AppsFlyerDeepLinkListener.REFERRAL_DEEP_LINK_VALUE,
refcode = SUCCESS_REFCODE,
campaign = SUCCESS_CAMPAIGN,
),
shouldStore = true,
shouldStore = false,
),
OnDeepLinkingModel(
deepLinkResult = createFoundDeepLink(
deepLinkValue = AppsFlyerDeepLinkListener.REFERRAL_DEEP_LINK_VALUE,
refcode = null,
campaign = SUCCESS_CAMPAIGN,
),
OnDeepLinkingModel(
deepLinkResult = createFoundDeepLink(
deepLinkValue = AppsFlyerDeepLinkListener.REFERRAL_DEEP_LINK_VALUE,
refcode = "",
campaign = SUCCESS_CAMPAIGN,
),
shouldStore = false,
),
OnDeepLinkingModel(
deepLinkResult = createFoundDeepLink(
deepLinkValue = AppsFlyerDeepLinkListener.REFERRAL_DEEP_LINK_VALUE,
refcode = null,
campaign = SUCCESS_CAMPAIGN,
),
shouldStore = false,
),
OnDeepLinkingModel(
deepLinkResult = createFoundDeepLink(deepLinkValue = "some_other_deep_link_value"),
shouldStore = false,
),
)
}
shouldStore = false,
),
OnDeepLinkingModel(
deepLinkResult = createFoundDeepLink(deepLinkValue = "some_other_deep_link_value"),
shouldStore = false,
),
)
}
data class OnDeepLinkingModel(
val deepLinkResult: DeepLinkResult,

View file

@ -7,4 +7,6 @@ interface AppsFlyerConversionStore {
suspend fun get(): AppsFlyerConversionData?
suspend fun store(value: AppsFlyerConversionData)
suspend fun storeIfAbsent(value: AppsFlyerConversionData)
}

View file

@ -29,6 +29,17 @@ internal class DefaultAppsFlyerConversionStore(
appPreferencesStore.storeObject(KEY, dto)
}
override suspend fun storeIfAbsent(value: AppsFlyerConversionData) {
Timber.i("Storing conversion data to store if absent: $value")
val dto = appPreferencesStore.getObjectSyncOrNull<ConversionDataDTO>(KEY)
if (dto == null) {
Timber.i("Conversion data is absent, storing $value")
appPreferencesStore.storeObject(KEY, ConversionDataConverter.convert(value))
}
}
private companion object {
val KEY = stringPreferencesKey("APPS_FLYER_CONVERSION_DATA")

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,
)
}

View file

@ -1,15 +1,10 @@
package com.tangem.domain.wallets.repository
import arrow.core.Option
import com.tangem.domain.wallets.models.AppsFlyerConversionData
interface WalletsPromoRepository {
suspend fun getConversionData(): Option<AppsFlyerConversionData>
suspend fun bindRefcodeWithWallets(conversionData: AppsFlyerConversionData)
suspend fun saveConversionData(refcode: String, campaign: String?)
suspend fun bindRefcodeWithWallets(refcode: String, campaign: String?)
suspend fun bindSavedRefcodeWithWallets(): AppsFlyerConversionData
suspend fun retryBindRefcodeWithWallets()
}

View file

@ -1,10 +1,8 @@
package com.tangem.domain.wallets.usecase
import arrow.core.Either
import arrow.core.raise.Raise
import arrow.core.raise.catch
import arrow.core.raise.either
import arrow.core.raise.ensure
import com.tangem.domain.wallets.models.AppsFlyerConversionData
import com.tangem.domain.wallets.repository.WalletsPromoRepository
import kotlinx.coroutines.sync.Mutex
@ -17,59 +15,21 @@ class BindRefcodeWithWalletUseCase @Inject constructor(
private val mutex = Mutex()
suspend operator fun invoke(refcode: String, campaign: String?): Either<Error, Unit> = either {
ensure(refcode.isNotBlank()) { Error.InvalidRefcode }
suspend operator fun invoke(conversionData: AppsFlyerConversionData): Either<Throwable, Unit> = either {
mutex.withLock {
checkSavedRefcode()
bindRefcode(refcode = refcode, campaign = campaign)
saveConversionData(refcode = refcode, campaign = campaign)
catch(
block = { walletsPromoRepository.bindRefcodeWithWallets(conversionData) },
catch = ::raise,
)
}
}
suspend fun retry(): Either<Error, Unit> = either {
suspend fun retry(): Either<Throwable, Unit> = either {
mutex.withLock {
val conversionData = tryBindRefcodeAgain()
saveConversionData(refcode = conversionData.refcode, campaign = conversionData.campaign)
catch(
block = { walletsPromoRepository.retryBindRefcodeWithWallets() },
catch = ::raise,
)
}
}
private suspend fun Raise<Error>.checkSavedRefcode() {
walletsPromoRepository.getConversionData().onSome {
raise(Error.RefcodeAlreadySaved)
}
}
private suspend fun Raise<Error>.bindRefcode(refcode: String, campaign: String?) {
catch(
block = { walletsPromoRepository.bindRefcodeWithWallets(refcode, campaign) },
catch = { raise(Error.DataError(it)) },
)
}
private suspend fun Raise<Error>.tryBindRefcodeAgain(): AppsFlyerConversionData {
return catch(
block = { walletsPromoRepository.bindSavedRefcodeWithWallets() },
catch = { raise(Error.DataError(it)) },
)
}
private suspend fun Raise<Error>.saveConversionData(refcode: String, campaign: String?) {
catch(
block = { walletsPromoRepository.saveConversionData(refcode, campaign) },
catch = { raise(Error.DataError(it)) },
)
}
sealed interface Error {
data object InvalidRefcode : Error
data object RefcodeAlreadySaved : Error
data class DataError(val throwable: Throwable) : Error
}
}

View file

@ -10,6 +10,7 @@ import com.tangem.core.ui.extensions.mask
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.GlobalLoadingMessage
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.domain.models.network.NetworkStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.networks.multi.MultiNetworkStatusProducer
@ -18,6 +19,7 @@ import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.wallets.PromoCodeActivationResult
import com.tangem.domain.wallets.PromoCodeActivationResult.*
import com.tangem.domain.wallets.models.AppsFlyerConversionData
import com.tangem.domain.wallets.models.errors.ActivatePromoCodeError
import com.tangem.domain.wallets.usecase.ActivateBitcoinPromocodeUseCase
import com.tangem.domain.wallets.usecase.BindRefcodeWithWalletUseCase
@ -46,6 +48,7 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
private val activateBitcoinPromocodeUseCase: ActivateBitcoinPromocodeUseCase,
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
private val appsFlyerConversionStore: AppsFlyerConversionStore,
private val bindRefcodeWithWalletUseCase: BindRefcodeWithWalletUseCase,
private val analyticsEventsHandler: AnalyticsEventHandler,
private val dispatchers: CoroutineDispatcherProvider,
@ -62,6 +65,8 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
} else {
findSelectedWallet(promoCode)
}
saveAndBindRefcode()
}
private fun findSelectedWallet(promoCode: String) {
@ -92,13 +97,9 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
Timber.tag(LOG_TAG).d("All user network statuses ${networkStatuses?.size}")
val cryptoCurrencies = multiWalletCryptoCurrenciesSupplier
.getSyncOrNull(
MultiWalletCryptoCurrenciesProducer.Params(
userWallet
.walletId,
),
)
val cryptoCurrencies = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
MultiWalletCryptoCurrenciesProducer.Params(userWallet.walletId),
)
Timber.tag(LOG_TAG).d("All user cryptoCurrencies on main ${cryptoCurrencies?.size}")
@ -106,8 +107,7 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
Timber.tag(LOG_TAG).d("BitcoinCurrency $bitcoinCurrency")
val bitcoinStatus = networkStatuses?.firstOrNull { status ->
status.network.id == bitcoinCurrency
?.network?.id
status.network.id == bitcoinCurrency?.network?.id
}
Timber.tag(LOG_TAG).d("BitcoinStatus $bitcoinStatus")
@ -129,13 +129,6 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
"Start activation promoCode ${promoCode.mask()} address ${bitcoinAddress.mask()}",
)
if (refcode != null) {
launch {
bindRefcodeWithWalletUseCase(refcode = refcode, campaign = campaign)
.onLeft { Timber.e("Failed to bind refcode with wallets: $it") }
}
}
activatePromoCode(bitcoinAddress = bitcoinAddress, promoCode = promoCode)
} else {
uiMessageSender.send(GlobalLoadingMessage(false))
@ -196,6 +189,19 @@ internal class DefaultPromoDeeplinkHandler @AssistedInject constructor(
)
}
private fun saveAndBindRefcode() {
scope.launch(dispatchers.default) {
if (!refcode.isNullOrBlank()) {
val conversionData = AppsFlyerConversionData(refcode = refcode, campaign = campaign)
appsFlyerConversionStore.storeIfAbsent(value = conversionData)
bindRefcodeWithWalletUseCase(conversionData)
.onLeft { Timber.e("Failed to bind refcode with wallets: $it") }
}
}
}
@AssistedFactory
interface Factory : PromoDeeplinkHandler.Factory {
override fun create(

View file

@ -12,6 +12,7 @@ import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.domain.models.StatusSource
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
@ -70,6 +71,9 @@ class DefaultPromoDeeplinkHandlerTest {
@MockK
private lateinit var bindRefcodeWithWalletUseCase: BindRefcodeWithWalletUseCase
@MockK
private lateinit var appsFlyerConversionStore: AppsFlyerConversionStore
private lateinit var messages: MutableList<UiMessage>
@Before
@ -110,6 +114,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -143,6 +148,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = TestingCoroutineDispatcherProvider(),
)
@ -175,6 +181,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = TestingCoroutineDispatcherProvider(),
)
@ -213,6 +220,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -255,6 +263,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -372,6 +381,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -404,6 +414,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -445,6 +456,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -507,6 +519,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -560,6 +573,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -619,6 +633,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -677,6 +692,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -731,6 +747,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)
@ -785,6 +802,7 @@ class DefaultPromoDeeplinkHandlerTest {
activateBitcoinPromocodeUseCase = activateBitcoinPromocodeUseCase,
getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase,
bindRefcodeWithWalletUseCase = bindRefcodeWithWalletUseCase,
appsFlyerConversionStore = appsFlyerConversionStore,
analyticsEventsHandler = analyticsEventHandler,
dispatchers = dispatcherProvider,
)