Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-26 20:34:55 +04:00
parent 7310b74876
commit 64cd1ae5a9
19 changed files with 149 additions and 95 deletions

View file

@ -9,7 +9,7 @@ import com.tangem.datasource.api.common.response.isNetworkError
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.datasource.api.tangemTech.models.WalletType
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.token.UserTokensResponseStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
@ -29,7 +29,7 @@ class UserTokensSaver(
private val dispatchers: CoroutineDispatcherProvider,
private val addressesEnricher: UserTokensResponseAddressesEnricher,
private val walletServerBinder: WalletServerBinder,
private val appsFlyerConversionStore: AppsFlyerConversionStore,
private val appsFlyerStore: AppsFlyerStore,
private val accountsFeatureToggles: AccountsFeatureToggles,
private val pushTokensRetryerPool: RetryerPool,
) {
@ -72,7 +72,7 @@ class UserTokensSaver(
pushNew(userWallet = userWallet, response = enrichedResponse, onFailSend = onFailSend)
} else {
val conversionData = appsFlyerConversionStore.get()
val conversionData = appsFlyerStore.get()
val enrichedResponse = response.enrichIf(userWalletId = userWalletId, condition = useEnricher).copy(
walletName = userWallet.name,

View file

@ -10,7 +10,7 @@ import com.tangem.data.common.quote.QuotesFetcher
import com.tangem.data.common.wallet.DefaultWalletServerBinder
import com.tangem.data.common.wallet.WalletServerBinder
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.token.UserTokensResponseStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
@ -76,7 +76,7 @@ internal object DataCommonModule {
dispatchers: CoroutineDispatcherProvider,
addressesEnricher: UserTokensResponseAddressesEnricher,
walletServerBinder: WalletServerBinder,
appsFlyerConversionStore: AppsFlyerConversionStore,
appsFlyerStore: AppsFlyerStore,
accountsFeatureToggles: AccountsFeatureToggles,
): UserTokensSaver {
return UserTokensSaver(
@ -90,7 +90,7 @@ internal object DataCommonModule {
coroutineScope = CoroutineScope(SupervisorJob() + dispatchers.default),
),
walletServerBinder = walletServerBinder,
appsFlyerConversionStore = appsFlyerConversionStore,
appsFlyerStore = appsFlyerStore,
)
}
@ -110,13 +110,13 @@ internal object DataCommonModule {
@Singleton
fun provideWalletServerBinder(
userWalletsStore: UserWalletsStore,
appsFlyerConversionStore: AppsFlyerConversionStore,
appsFlyerStore: AppsFlyerStore,
tangemTechApi: TangemTechApi,
dispatchers: CoroutineDispatcherProvider,
): WalletServerBinder {
return DefaultWalletServerBinder(
userWalletsStore = userWalletsStore,
appsFlyerConversionStore = appsFlyerConversionStore,
appsFlyerStore = appsFlyerStore,
tangemTechApi = tangemTechApi,
dispatchers = dispatchers,
)

View file

@ -3,7 +3,7 @@ package com.tangem.data.common.wallet
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.converters.WalletIdBodyConverter
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
@ -12,7 +12,7 @@ import kotlinx.coroutines.withContext
internal class DefaultWalletServerBinder(
private val userWalletsStore: UserWalletsStore,
private val appsFlyerConversionStore: AppsFlyerConversionStore,
private val appsFlyerStore: AppsFlyerStore,
private val tangemTechApi: TangemTechApi,
private val dispatchers: CoroutineDispatcherProvider,
) : WalletServerBinder {
@ -24,7 +24,7 @@ internal class DefaultWalletServerBinder(
}
override suspend fun bind(userWallet: UserWallet): ApiResponse<Unit> {
val conversionData = appsFlyerConversionStore.get()
val conversionData = appsFlyerStore.get()
return withContext(dispatchers.io) {
tangemTechApi.createWallet(

View file

@ -6,7 +6,7 @@ import com.tangem.datasource.api.common.response.ApiResponseError
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.datasource.api.tangemTech.models.WalletType
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.token.UserTokensResponseStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
@ -30,7 +30,7 @@ class UserTokensSaverTest {
every { this@mockk.isFeatureEnabled } returns true
}
private val walletServerBinder: WalletServerBinder = mockk()
private val appsFlyerConversionStore: AppsFlyerConversionStore = mockk()
private val appsFlyerStore: AppsFlyerStore = mockk()
private val userTokensSaver: UserTokensSaver = UserTokensSaver(
tangemTechApi = tangemTechApi,
@ -39,7 +39,7 @@ class UserTokensSaverTest {
dispatchers = TestingCoroutineDispatcherProvider(),
addressesEnricher = enricher,
walletServerBinder = walletServerBinder,
appsFlyerConversionStore = appsFlyerConversionStore,
appsFlyerStore = appsFlyerStore,
accountsFeatureToggles = accountsFeatureToggles,
pushTokensRetryerPool = mockk(),
)

View file

@ -6,7 +6,7 @@ import com.tangem.datasource.api.common.response.ApiResponseError
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.WalletIdBody
import com.tangem.datasource.api.tangemTech.models.WalletType
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
@ -27,13 +27,13 @@ import org.junit.jupiter.api.TestInstance
internal class DefaultWalletServerBinderTest {
private val userWalletsStore: UserWalletsStore = mockk()
private val appsFlyerConversionStore: AppsFlyerConversionStore = mockk()
private val appsFlyerStore: AppsFlyerStore = mockk()
private val tangemTechApi: TangemTechApi = mockk()
private val dispatchers: CoroutineDispatcherProvider = TestingCoroutineDispatcherProvider()
private val binder = DefaultWalletServerBinder(
userWalletsStore = userWalletsStore,
appsFlyerConversionStore = appsFlyerConversionStore,
appsFlyerStore = appsFlyerStore,
tangemTechApi = tangemTechApi,
dispatchers = dispatchers
)
@ -47,7 +47,7 @@ internal class DefaultWalletServerBinderTest {
@AfterEach
fun tearDown() {
clearMocks(userWalletsStore, appsFlyerConversionStore, tangemTechApi)
clearMocks(userWalletsStore, appsFlyerStore, tangemTechApi)
}
@Nested
@ -66,7 +66,7 @@ internal class DefaultWalletServerBinderTest {
val apiResponse = ApiResponse.Success(Unit)
coEvery { userWalletsStore.getSyncOrNull(userWalletId) } returns userWallet
coEvery { appsFlyerConversionStore.get() } returns conversionData
coEvery { appsFlyerStore.get() } returns conversionData
coEvery { tangemTechApi.createWallet(requestBody) } returns apiResponse
val actual = binder.bind(userWalletId = userWalletId)
@ -75,7 +75,7 @@ internal class DefaultWalletServerBinderTest {
coVerifyOrder {
userWalletsStore.getSyncOrNull(userWalletId)
appsFlyerConversionStore.get()
appsFlyerStore.get()
tangemTechApi.createWallet(requestBody)
}
}
@ -93,7 +93,7 @@ internal class DefaultWalletServerBinderTest {
}
coVerify(inverse = true) {
appsFlyerConversionStore.get()
appsFlyerStore.get()
tangemTechApi.createWallet(any())
}
}
@ -108,7 +108,7 @@ internal class DefaultWalletServerBinderTest {
val apiResponse = ApiResponse.Success(Unit)
coEvery { userWalletsStore.getSyncOrNull(userWalletId) } returns userWallet
coEvery { appsFlyerConversionStore.get() } returns null
coEvery { appsFlyerStore.get() } returns null
coEvery { tangemTechApi.createWallet(requestBody) } returns apiResponse
val actual = binder.bind(userWalletId = userWalletId)
@ -117,7 +117,7 @@ internal class DefaultWalletServerBinderTest {
coVerifyOrder {
userWalletsStore.getSyncOrNull(userWalletId)
appsFlyerConversionStore.get()
appsFlyerStore.get()
tangemTechApi.createWallet(requestBody)
}
}
@ -134,7 +134,7 @@ internal class DefaultWalletServerBinderTest {
val apiResponse = ApiResponse.Error(ApiResponseError.TimeoutException()) as ApiResponse<Unit>
coEvery { userWalletsStore.getSyncOrNull(userWalletId) } returns userWallet
coEvery { appsFlyerConversionStore.get() } returns conversionData
coEvery { appsFlyerStore.get() } returns conversionData
coEvery { tangemTechApi.createWallet(requestBody) } returns apiResponse
val actual = binder.bind(userWalletId = userWalletId)
@ -143,7 +143,7 @@ internal class DefaultWalletServerBinderTest {
coVerifyOrder {
userWalletsStore.getSyncOrNull(userWalletId)
appsFlyerConversionStore.get()
appsFlyerStore.get()
tangemTechApi.createWallet(requestBody)
}
}
@ -164,7 +164,7 @@ internal class DefaultWalletServerBinderTest {
)
val apiResponse = ApiResponse.Success(Unit)
coEvery { appsFlyerConversionStore.get() } returns conversionData
coEvery { appsFlyerStore.get() } returns conversionData
coEvery { tangemTechApi.createWallet(requestBody) } returns apiResponse
val actual = binder.bind(userWallet = userWallet)
@ -172,7 +172,7 @@ internal class DefaultWalletServerBinderTest {
Truth.assertThat(actual).isEqualTo(apiResponse)
coVerifyOrder {
appsFlyerConversionStore.get()
appsFlyerStore.get()
tangemTechApi.createWallet(requestBody)
}
}
@ -186,7 +186,7 @@ internal class DefaultWalletServerBinderTest {
)
val apiResponse = ApiResponse.Success(Unit)
coEvery { appsFlyerConversionStore.get() } returns null
coEvery { appsFlyerStore.get() } returns null
coEvery { tangemTechApi.createWallet(requestBody) } returns apiResponse
val actual = binder.bind(userWallet = userWallet)
@ -194,7 +194,7 @@ internal class DefaultWalletServerBinderTest {
Truth.assertThat(actual).isEqualTo(apiResponse)
coVerifyOrder {
appsFlyerConversionStore.get()
appsFlyerStore.get()
tangemTechApi.createWallet(requestBody)
}
}
@ -210,7 +210,7 @@ internal class DefaultWalletServerBinderTest {
)
val apiResponse = ApiResponse.Error(ApiResponseError.TimeoutException()) as ApiResponse<Unit>
coEvery { appsFlyerConversionStore.get() } returns conversionData
coEvery { appsFlyerStore.get() } returns conversionData
coEvery { tangemTechApi.createWallet(requestBody) } returns apiResponse
val actual = binder.bind(userWallet = userWallet)
@ -218,7 +218,7 @@ internal class DefaultWalletServerBinderTest {
Truth.assertThat(actual).isEqualTo(apiResponse)
coVerifyOrder {
appsFlyerConversionStore.get()
appsFlyerStore.get()
tangemTechApi.createWallet(requestBody)
}
}

View file

@ -4,14 +4,16 @@ import com.tangem.data.notifications.converters.NotificationsEligibleNetworkConv
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.NotificationApplicationCreateBody
import com.tangem.utils.info.AppInfoProvider
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.*
import com.tangem.datasource.local.preferences.utils.getSyncOrNull
import com.tangem.datasource.local.preferences.utils.store
import com.tangem.domain.notifications.models.ApplicationId
import com.tangem.domain.notifications.repository.PushNotificationsRepository
import com.tangem.domain.notifications.models.NotificationsEligibleNetwork
import com.tangem.domain.notifications.repository.PushNotificationsRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.info.AppInfoProvider
import kotlinx.coroutines.withContext
import javax.inject.Inject
@ -19,6 +21,7 @@ internal class DefaultPushNotificationsRepository @Inject constructor(
private val tangemTechApi: TangemTechApi,
private val appInfoProvider: AppInfoProvider,
private val appPreferencesStore: AppPreferencesStore,
private val appsFlyerStore: AppsFlyerStore,
private val dispatchers: CoroutineDispatcherProvider,
) : PushNotificationsRepository {
@ -32,6 +35,7 @@ internal class DefaultPushNotificationsRepository @Inject constructor(
timezone = appInfoProvider.timezone,
version = appInfoProvider.appVersion,
pushToken = pushToken,
appsflyerId = appsFlyerStore.getUID(),
),
).getOrThrow().appId

View file

@ -3,17 +3,20 @@ package com.tangem.data.notifications
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.utils.info.AppInfoProvider
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.google.common.truth.Truth.assertThat
import com.squareup.moshi.Moshi
import com.tangem.data.notifications.converters.NotificationsEligibleNetworkConverter
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.tangemTech.models.*
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.CryptoNetworkResponse
import com.tangem.datasource.api.tangemTech.models.NotificationApplicationCreateBody
import com.tangem.datasource.api.tangemTech.models.NotificationApplicationIdResponse
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.domain.notifications.models.ApplicationId
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import com.tangem.utils.info.AppInfoProvider
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
@ -31,10 +34,12 @@ class DefaultPushNotificationsRepositoryTest {
dispatchers = TestingCoroutineDispatcherProvider(),
preferencesDataStore = preferencesDataStore,
)
private val appsFlyerStore: AppsFlyerStore = mockk()
private val repository = DefaultPushNotificationsRepository(
tangemTechApi = tangemTechApi,
appInfoProvider = appInfoProvider,
appPreferencesStore = appPreferencesStore,
appsFlyerStore = appsFlyerStore,
dispatchers = TestingCoroutineDispatcherProvider(),
)
@ -52,6 +57,7 @@ class DefaultPushNotificationsRepositoryTest {
coEvery { appInfoProvider.language } returns "en"
coEvery { appInfoProvider.appVersion } returns "5.21.1"
coEvery { appInfoProvider.timezone } returns "UTC"
coEvery { appsFlyerStore.getUID() } returns "UID"
coEvery { tangemTechApi.createApplicationId(any()) } returns ApiResponse.Success(
expectedAppIdResponse,
)
@ -71,6 +77,7 @@ class DefaultPushNotificationsRepositoryTest {
timezone = "UTC",
version = "5.21.1",
pushToken = pushToken,
appsflyerId = "UID",
),
)
}

View file

@ -15,7 +15,7 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.converters.WalletIdBodyConverter
import com.tangem.datasource.api.tangemTech.models.*
import com.tangem.datasource.api.tangemTech.models.SeedPhraseNotificationDTO.Status
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.datastore.RuntimeStateStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
@ -49,7 +49,7 @@ internal class DefaultWalletsRepository(
private val dispatchers: CoroutineDispatcherProvider,
private val authProvider: AuthProvider,
private val walletServerBinder: WalletServerBinder,
private val appsFlyerConversionStore: AppsFlyerConversionStore,
private val appsFlyerStore: AppsFlyerStore,
private val accountsFeatureToggles: AccountsFeatureToggles,
private val moshi: com.squareup.moshi.Moshi,
) : WalletsRepository {
@ -411,7 +411,7 @@ internal class DefaultWalletsRepository(
associateApplicationIdWithWallets().getOrThrow()
}
} else {
val conversionData = appsFlyerConversionStore.get()
val conversionData = appsFlyerStore.get()
val publicKeys = authProvider.getCardsPublicKeys()
val walletsBody = wallets.map { userWallet ->
WalletIdBodyConverter.convert(

View file

@ -12,7 +12,7 @@ import com.tangem.data.wallets.hot.DefaultHotWalletAccessCodeAttemptsRepository
import com.tangem.datasource.api.common.AuthProvider
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.datastore.RuntimeStateStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
@ -45,7 +45,7 @@ internal object WalletsDataModule {
dispatchers: CoroutineDispatcherProvider,
authProvider: AuthProvider,
walletServerBinder: WalletServerBinder,
appsFlyerConversionStore: AppsFlyerConversionStore,
appsFlyerStore: AppsFlyerStore,
accountsFeatureToggles: AccountsFeatureToggles,
@NetworkMoshi moshi: Moshi,
): WalletsRepository {
@ -57,7 +57,7 @@ internal object WalletsDataModule {
dispatchers = dispatchers,
authProvider = authProvider,
walletServerBinder = walletServerBinder,
appsFlyerConversionStore = appsFlyerConversionStore,
appsFlyerStore = appsFlyerStore,
accountsFeatureToggles = accountsFeatureToggles,
moshi = moshi,
)

View file

@ -12,7 +12,7 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.PromocodeActivationBody
import com.tangem.datasource.api.tangemTech.models.PromocodeActivationResponse
import com.tangem.datasource.api.tangemTech.models.WalletResponse
import com.tangem.datasource.local.appsflyer.AppsFlyerConversionStore
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
@ -41,7 +41,7 @@ class DefaultWalletsRepositoryTest {
private lateinit var tangemTechApi: TangemTechApi
private lateinit var dispatchers: CoroutineDispatcherProvider
private lateinit var walletServerBinder: WalletServerBinder
private lateinit var appsFlyerConversionStore: AppsFlyerConversionStore
private lateinit var appsFlyerStore: AppsFlyerStore
private val testWalletId = UserWalletId("1234567890abcdef")
@ -49,7 +49,7 @@ class DefaultWalletsRepositoryTest {
fun setup() {
tangemTechApi = mockk()
walletServerBinder = mockk()
appsFlyerConversionStore = mockk()
appsFlyerStore = mockk()
dispatchers = TestingCoroutineDispatcherProvider()
repository = DefaultWalletsRepository(
appPreferencesStore = appPreferenceStore,
@ -59,7 +59,7 @@ class DefaultWalletsRepositoryTest {
dispatchers = dispatchers,
authProvider = mockk(),
walletServerBinder = walletServerBinder,
appsFlyerConversionStore = appsFlyerConversionStore,
appsFlyerStore = appsFlyerStore,
accountsFeatureToggles = mockk(),
moshi = mockk(),
)
@ -227,12 +227,12 @@ class DefaultWalletsRepositoryTest {
dispatchers = dispatchers,
authProvider = authProvider,
walletServerBinder = walletServerBinder,
appsFlyerConversionStore = appsFlyerConversionStore,
appsFlyerStore = appsFlyerStore,
accountsFeatureToggles = accountsFeatureToggles,
moshi = mockk(),
)
coEvery { appsFlyerConversionStore.get() } returns null
coEvery { appsFlyerStore.get() } returns null
coEvery {
tangemTechApi.associateApplicationIdWithWallets(