Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-01 12:48:45 +04:00
parent 0029b514bd
commit 3524a3bd86
7 changed files with 66 additions and 13 deletions

View file

@ -25,6 +25,7 @@ import com.tangem.datasource.api.tangemTech.models.orDefault
import com.tangem.datasource.utils.getSyncOrNull
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.withContext
@ -143,6 +144,11 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
apiResponse.bind().enrichByAccountId()
},
onError = { error ->
TangemLogger.e(
"pushInternal wallet=$userWalletId: PUT /accounts failed, " +
"isPreconditionFailed=${error.isNetworkError(code = Code.PRECONDITION_FAILED)}, error=$error",
)
if (error.isNetworkError(code = Code.PRECONDITION_FAILED)) {
throw error
}

View file

@ -59,6 +59,8 @@ internal class FetchWalletAccountsErrorHandler @Inject constructor(
storeWalletAccounts: suspend (UserWalletId, GetWalletAccountsResponse) -> Unit,
): FetchResult {
val isResponseUpToDate = error.isNetworkError(code = Code.NOT_MODIFIED)
val isNotFoundError = error.isNetworkError(code = Code.NOT_FOUND)
if (isResponseUpToDate) {
TangemLogger.e("ETag is up to date, no need to update accounts for wallet: $userWalletId")
val response = requireNotNull(savedAccountsResponse) {
@ -71,13 +73,16 @@ internal class FetchWalletAccountsErrorHandler @Inject constructor(
val response = savedAccountsResponse ?: createDefaultResponse(userWalletId)
val (accountDTOs, userTokensResponse) = response.accounts to response.toUserTokensResponse()
val isNotFoundError = error.isNetworkError(code = Code.NOT_FOUND)
if (isNotFoundError) {
val eTag = createWallet(userWalletId)
if (eTag != null) {
pushWalletAccounts(accountDTOs, eTag)
userTokensSaver.pushWithRetryer(userWalletId, userTokensResponse)
} else {
TangemLogger.e(
"handle wallet=$userWalletId: account creation skipped, createWallet returned null eTag",
)
}
}
@ -112,10 +117,17 @@ internal class FetchWalletAccountsErrorHandler @Inject constructor(
private suspend fun createWallet(userWalletId: UserWalletId): String? {
val creationResponse = walletServerBinder.bind(userWalletId)
return if (creationResponse is ApiResponse.Success && creationResponse.code == Code.CREATED) {
val isCreated = creationResponse is ApiResponse.Success && creationResponse.code == Code.CREATED
val eTag = if (isCreated) {
creationResponse.headers[ETAG_HEADER]?.firstOrNull()
} else {
null
}
if (eTag == null) {
TangemLogger.e("ETag is null for wallet: $userWalletId, isCreated: $isCreated")
}
return eTag
}
}

View file

@ -1,6 +1,7 @@
package com.tangem.data.common.wallet
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.common.response.ETAG_HEADER
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.converters.WalletIdBodyConverter
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
@ -9,6 +10,7 @@ import com.tangem.domain.common.wallets.getSyncOrNull
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.withContext
internal class DefaultWalletServerBinder(
@ -19,7 +21,12 @@ internal class DefaultWalletServerBinder(
) : WalletServerBinder {
override suspend fun bind(userWalletId: UserWalletId): ApiResponse<Unit>? {
val userWallet = userWalletsListRepository.getSyncOrNull(id = userWalletId) ?: return null
val userWallet = userWalletsListRepository.getSyncOrNull(id = userWalletId)
if (userWallet == null) {
TangemLogger.e("bind wallet=$userWalletId: user wallet not found locally, skipping createWallet call")
return null
}
return bind(userWallet)
}
@ -31,6 +38,12 @@ internal class DefaultWalletServerBinder(
tangemTechApi.createWallet(
body = WalletIdBodyConverter.convert(userWallet, conversionData),
)
}.also { response ->
val eTag = response.headers[ETAG_HEADER]?.firstOrNull()
TangemLogger.i(
"bind wallet=${userWallet.walletId}: createWallet code=${(response as? ApiResponse.Success)?.code}, " +
"hasETag=${eTag != null}, eTagNotEmpty=${!eTag.isNullOrEmpty()}",
)
}
}
}