Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-01 12:49:20 +04:00
parent f75a69abfe
commit 4d7ae277a4
14 changed files with 498 additions and 10 deletions

View file

@ -11,7 +11,7 @@ import com.tangem.data.common.cache.etag.ETagsStore
import com.tangem.data.common.currency.UserTokensSaver
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.common.response.ApiResponseError.HttpException.Code
import com.tangem.datasource.api.common.response.IF_NONE_MATCH_HEADER
import com.tangem.datasource.api.common.response.ETAG_HEADER
import com.tangem.datasource.api.common.response.isNetworkError
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
@ -86,7 +86,11 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
tangemTechApi.saveWalletAccounts(
walletId = userWalletId.stringValue,
eTag = eTag,
body = body,
body = body.copy(
accounts = body.accounts.map {
it.copy(tokens = null, totalTokens = null, totalNetworks = null)
},
),
)
}
@ -140,7 +144,7 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
private suspend fun assignTokens(userWalletId: UserWalletId, accountsResponse: GetWalletAccountsResponse) {
val accountsResponseWithTokens = accountsResponse.assignTokens(userWalletId)
pushAndStore(userWalletId = userWalletId, response = accountsResponseWithTokens)
store(userWalletId = userWalletId, response = accountsResponseWithTokens)
userTokensSaver.push(
userWalletId = userWalletId,
@ -153,7 +157,7 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
}
private suspend fun saveETag(userWalletId: UserWalletId, apiResponse: ApiResponse<*>) {
val eTag = apiResponse.headers[IF_NONE_MATCH_HEADER]?.firstOrNull()
val eTag = apiResponse.headers[ETAG_HEADER]?.firstOrNull()
if (eTag != null) {
eTagsStore.store(userWalletId = userWalletId, key = ETagsStore.Key.WalletAccounts, value = eTag)

View file

@ -17,6 +17,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
import javax.inject.Singleton
typealias AccountsResponseStore = DataStore<GetWalletAccountsResponse?>
@ -30,6 +31,7 @@ typealias AccountsResponseStore = DataStore<GetWalletAccountsResponse?>
*
[REDACTED_AUTHOR]
*/
@Singleton
internal class AccountsResponseStoreFactory @Inject constructor(
@ApplicationContext private val context: Context,
@NetworkMoshi private val moshi: Moshi,

View file

@ -8,7 +8,7 @@ import com.tangem.data.common.cache.etag.ETagsStore
import com.tangem.data.common.currency.UserTokensSaver
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.common.response.ApiResponseError
import com.tangem.datasource.api.common.response.IF_NONE_MATCH_HEADER
import com.tangem.datasource.api.common.response.ETAG_HEADER
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
@ -85,7 +85,7 @@ class DefaultWalletAccountsFetcherTest {
val newETag = "newEtag"
val apiResponse = ApiResponse.Success(
data = accountsResponse,
headers = mapOf(IF_NONE_MATCH_HEADER to listOf(newETag)),
headers = mapOf(ETAG_HEADER to listOf(newETag)),
)
accountsResponseStoreFlow.value = savedAccountsResponse
@ -156,7 +156,7 @@ class DefaultWalletAccountsFetcherTest {
val newETag = "newEtag"
val apiResponse = ApiResponse.Success(
data = accountsResponse,
headers = mapOf(IF_NONE_MATCH_HEADER to listOf(newETag)),
headers = mapOf(ETAG_HEADER to listOf(newETag)),
)
accountsResponseStoreFlow.value = savedAccountsResponse
@ -247,7 +247,7 @@ class DefaultWalletAccountsFetcherTest {
val newETag = "newEtag"
val apiResponse = ApiResponse.Success(
data = accountsResponse,
headers = mapOf(IF_NONE_MATCH_HEADER to listOf(newETag)),
headers = mapOf(ETAG_HEADER to listOf(newETag)),
)
val apiError = ApiResponseError.HttpException(

View file

@ -34,6 +34,11 @@ internal class DefaultETagsStore(
appPreferencesStore.store(key = key, value = value)
}
override suspend fun clear(userWalletId: UserWalletId, key: ETagsStore.Key) {
val key = getAccountsETagKey(userWalletId = userWalletId, key = key)
appPreferencesStore.editData { it.remove(key) }
}
private fun getAccountsETagKey(userWalletId: UserWalletId, key: ETagsStore.Key): Preferences.Key<String> {
return stringPreferencesKey(name = "etag_${key}_${userWalletId.stringValue}")
}

View file

@ -25,6 +25,14 @@ interface ETagsStore {
*/
suspend fun store(userWalletId: UserWalletId, key: Key, value: String)
/**
* Clears the stored ETag value for the specified wallet and key
*
* @param userWalletId identifier of the user wallet
* @param key the key for which to get the ETag value
*/
suspend fun clear(userWalletId: UserWalletId, key: Key)
/** Enumeration of possible keys for storing ETag values */
enum class Key {
WalletAccounts,