Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-08 15:09:07 +04:00
parent 8568277f95
commit ca2804b0e0
9 changed files with 172 additions and 48 deletions

View file

@ -2,12 +2,17 @@ package com.tangem.data.common.currency
import com.tangem.data.common.api.safeApiCall
import com.tangem.data.common.tokens.UserTokensBackwardCompatibility
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.converters.WalletIdBodyConverter
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.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.retryer.Retryer
@ -50,24 +55,26 @@ class UserTokensSaver(
response: UserTokensResponse,
useEnricher: Boolean = true,
onFailSend: () -> Unit = {},
) {
withContext(dispatchers.default) {
val userWallet = userWalletsStore.getSyncOrNull(key = userWalletId)
) = withContext(dispatchers.io) {
val userWallet = userWalletsStore.getSyncOrNull(key = userWalletId)
if (userWallet == null) {
Timber.e("UserWallet with id $userWalletId not found. Cannot push tokens.")
onFailSend()
return@withContext
}
if (accountsFeatureToggles.isFeatureEnabled) {
val enrichedResponse = response.enrichIf(userWalletId = userWalletId, condition = useEnricher)
pushNew(userWallet = userWallet, response = enrichedResponse, onFailSend = onFailSend)
} else {
val enrichedResponse = response.enrichIf(userWalletId = userWalletId, condition = useEnricher).copy(
walletName = userWallet?.name,
walletName = userWallet.name,
walletType = WalletType.from(userWallet),
)
safeApiCall(
call = {
withContext(dispatchers.io) {
tangemTechApi.saveUserTokens(userId = userWalletId.stringValue, userTokens = enrichedResponse)
.bind()
}
},
onError = { onFailSend() },
)
pushLegacy(userWalletId = userWalletId, response = enrichedResponse, onFailSend = onFailSend)
}
}
@ -88,6 +95,39 @@ class UserTokensSaver(
)
}
private suspend fun pushLegacy(userWalletId: UserWalletId, response: UserTokensResponse, onFailSend: () -> Unit) {
safeApiCall(
call = { tangemTechApi.saveUserTokens(userId = userWalletId.stringValue, userTokens = response).bind() },
onError = { onFailSend() },
)
}
private suspend fun pushNew(userWallet: UserWallet, response: UserTokensResponse, onFailSend: () -> Unit) {
safeApiCall(
call = {
val apiResponse = tangemTechApi.saveTokens(
userId = userWallet.walletId.stringValue,
userTokens = response,
)
val isWalletNotFound = apiResponse is ApiResponse.Error &&
apiResponse.cause.isNetworkError(ApiResponseError.HttpException.Code.NOT_FOUND)
if (isWalletNotFound) {
tangemTechApi.createWallet(body = WalletIdBodyConverter.convert(userWallet)).bind()
tangemTechApi.saveTokens(
userId = userWallet.walletId.stringValue,
userTokens = response,
).bind()
} else {
apiResponse.bind()
}
},
onError = { onFailSend() },
)
}
private fun UserTokensResponse.applyCompatibility(): UserTokensResponse {
return userTokensBackwardCompatibility.applyCompatibilityAndGetUpdated(userTokensResponse = this)
}

View file

@ -73,7 +73,7 @@ class UserTokensSaverTest {
}
coVerify(inverse = true) {
tangemTechApi.saveUserTokens(any(), any())
tangemTechApi.saveTokens(any(), any())
}
}
@ -108,7 +108,8 @@ class UserTokensSaverTest {
coEvery { userWalletsStore.getSyncOrNull(userWalletId) } returns userWallet
coEvery { enricher(userWalletId, response) } returns enrichedResponse
coEvery { tangemTechApi.saveUserTokens(any(), any()) } returns ApiResponse.Error(error) as ApiResponse<Unit>
coEvery { tangemTechApi.saveTokens(any(), any()) } returns ApiResponse.Error(error) as ApiResponse<Unit>
coEvery { tangemTechApi.createWallet(body = any()) } returns ApiResponse.Error(error) as ApiResponse<Unit>
// WHEN
userTokensSaver.push(
@ -120,7 +121,7 @@ class UserTokensSaverTest {
// THEN
coVerifyOrder {
enricher(userWalletId, response)
tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse)
tangemTechApi.saveTokens(userWalletId.stringValue, enrichedResponse)
}
assert(onFailSendCalled) { "onFailSend callback should be called when API call fails" }
@ -155,7 +156,7 @@ class UserTokensSaverTest {
coEvery { userWalletsStore.getSyncOrNull(userWalletId) } returns userWallet
coEvery { enricher(userWalletId, response) } returns enrichedResponse
coEvery {
tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse)
tangemTechApi.saveTokens(userWalletId.stringValue, enrichedResponse)
} returns ApiResponse.Success(Unit)
// WHEN
@ -164,7 +165,7 @@ class UserTokensSaverTest {
// THEN
coVerifyOrder {
enricher(userWalletId, response)
tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse)
tangemTechApi.saveTokens(userWalletId.stringValue, enrichedResponse)
}
}
}