Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-06 10:59:48 +04:00
parent e2721b21e1
commit a67ca6279f
14 changed files with 24 additions and 614 deletions

View file

@ -1,14 +1,12 @@
package com.tangem.data.common.currency
import com.tangem.data.common.api.safeApiCall
import com.tangem.data.common.tokens.UserTokensBackwardCompatibility
import com.tangem.data.common.wallet.WalletServerBinder
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.common.response.ApiResponseError
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.local.token.UserTokensResponseStore
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.common.wallets.getSyncOrNull
import com.tangem.domain.models.wallet.UserWallet
@ -23,31 +21,11 @@ import timber.log.Timber
class UserTokensSaver(
private val tangemTechApi: TangemTechApi,
private val userWalletsListRepository: UserWalletsListRepository,
private val userTokensResponseStore: UserTokensResponseStore,
private val dispatchers: CoroutineDispatcherProvider,
private val addressesEnricher: UserTokensResponseAddressesEnricher,
private val walletServerBinder: WalletServerBinder,
private val pushTokensRetryerPool: RetryerPool,
) {
private val userTokensBackwardCompatibility = UserTokensBackwardCompatibility()
suspend fun storeAndPush(userWalletId: UserWalletId, response: UserTokensResponse) {
withContext(dispatchers.default) {
val enrichedResponse = response.enrichIf(userWalletId = userWalletId, condition = true)
store(userWalletId = userWalletId, response = enrichedResponse, useEnricher = false)
push(userWalletId = userWalletId, response = enrichedResponse, useEnricher = false)
}
}
suspend fun store(userWalletId: UserWalletId, response: UserTokensResponse, useEnricher: Boolean = true) =
withContext(dispatchers.default) {
val updatedResponse = response
.applyCompatibility()
.enrichIf(userWalletId = userWalletId, condition = useEnricher)
userTokensResponseStore.store(userWalletId = userWalletId, response = updatedResponse)
}
suspend fun push(
userWalletId: UserWalletId,
@ -111,10 +89,6 @@ class UserTokensSaver(
)
}
private fun UserTokensResponse.applyCompatibility(): UserTokensResponse {
return userTokensBackwardCompatibility.applyCompatibilityAndGetUpdated(userTokensResponse = this)
}
private suspend fun UserTokensResponse.enrichIf(
userWalletId: UserWalletId,
condition: Boolean,

View file

@ -12,7 +12,6 @@ import com.tangem.data.common.wallet.WalletServerBinder
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.token.UserTokensResponseStore
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.demo.models.DemoConfig
import com.tangem.domain.walletmanager.WalletManagersFacade
@ -67,7 +66,6 @@ internal object DataCommonModule {
fun provideUserTokensSaver(
tangemTechApi: TangemTechApi,
userWalletsListRepository: UserWalletsListRepository,
userTokensResponseStore: UserTokensResponseStore,
dispatchers: CoroutineDispatcherProvider,
addressesEnricher: UserTokensResponseAddressesEnricher,
walletServerBinder: WalletServerBinder,
@ -75,7 +73,6 @@ internal object DataCommonModule {
return UserTokensSaver(
tangemTechApi = tangemTechApi,
userWalletsListRepository = userWalletsListRepository,
userTokensResponseStore = userTokensResponseStore,
dispatchers = dispatchers,
addressesEnricher = addressesEnricher,
pushTokensRetryerPool = RetryerPool(

View file

@ -6,7 +6,6 @@ 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.token.UserTokensResponseStore
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
@ -23,14 +22,12 @@ class UserTokensSaverTest {
private val tangemTechApi: TangemTechApi = mockk()
private val userWalletsListRepository: UserWalletsListRepository = mockk(relaxUnitFun = true)
private val userTokensResponseStore: UserTokensResponseStore = mockk(relaxed = true)
private val enricher: UserTokensResponseAddressesEnricher = mockk()
private val walletServerBinder: WalletServerBinder = mockk()
private val userTokensSaver: UserTokensSaver = UserTokensSaver(
tangemTechApi = tangemTechApi,
userWalletsListRepository = userWalletsListRepository,
userTokensResponseStore = userTokensResponseStore,
dispatchers = TestingCoroutineDispatcherProvider(),
addressesEnricher = enricher,
walletServerBinder = walletServerBinder,
@ -42,46 +39,11 @@ class UserTokensSaverTest {
clearMocks(
tangemTechApi,
userWalletsListRepository,
userTokensResponseStore,
enricher,
walletServerBinder,
)
}
@Test
fun `GIVEN user wallet id and response WHEN store THEN should store enriched response`() = runTest {
// GIVEN
val userWalletId = UserWalletId("1234567890abcdef")
val response = UserTokensResponse(
version = 0,
group = UserTokensResponse.GroupType.NETWORK,
sort = UserTokensResponse.SortType.BALANCE,
tokens = emptyList(),
)
val enrichedResponse = UserTokensResponse(
version = 0,
group = UserTokensResponse.GroupType.NETWORK,
sort = UserTokensResponse.SortType.MANUAL,
tokens = emptyList(),
)
coEvery { enricher(userWalletId, response) } returns enrichedResponse
// WHEN
userTokensSaver.store(userWalletId, response)
// THEN
coVerifyOrder {
enricher(userWalletId, response)
userTokensResponseStore.store(userWalletId, enrichedResponse)
}
coVerify(inverse = true) {
tangemTechApi.saveTokens(any(), any())
}
}
@Test
fun `GIVEN user wallet id and response WHEN push AND api call fails THEN should log error and call onFailSend`() =
runTest {
@ -133,49 +95,4 @@ class UserTokensSaverTest {
assert(onFailSendCalled) { "onFailSend callback should be called when API call fails" }
}
@Test
fun `GIVEN user wallet id and response WHEN storeAndPush THEN should store and push enriched response`() = runTest {
// GIVEN
val userWalletId = UserWalletId("1234567890abcdef")
val userWallet = mockk<UserWallet.Cold> {
every { this@mockk.walletId } returns userWalletId
every { this@mockk.name } returns "Wallet"
}
val response = UserTokensResponse(
version = 0,
group = UserTokensResponse.GroupType.NETWORK,
sort = UserTokensResponse.SortType.BALANCE,
tokens = emptyList(),
walletName = userWallet.name,
walletType = WalletType.COLD,
)
val enrichedResponse = UserTokensResponse(
version = 0,
group = UserTokensResponse.GroupType.NETWORK,
sort = UserTokensResponse.SortType.BALANCE,
tokens = emptyList(),
walletName = userWallet.name,
walletType = WalletType.COLD,
)
val userWalletsFlow = MutableStateFlow(listOf(userWallet))
every { userWalletsListRepository.userWallets } returns userWalletsFlow
coEvery { enricher(userWalletId, response) } returns enrichedResponse
coEvery {
tangemTechApi.saveTokens(userWalletId.stringValue, enrichedResponse)
} returns ApiResponse.Success(Unit)
// WHEN
userTokensSaver.storeAndPush(userWalletId, response)
// THEN
coVerifyOrder {
enricher(userWalletId, response)
userWalletsListRepository.userWallets
tangemTechApi.saveTokens(userWalletId.stringValue, enrichedResponse)
}
}
}