From 0ab1c7507a37e707d5001038743951b1a47ca96e Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 27 Jun 2025 18:48:33 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/tap/ApplicationEntryPoint.kt | 3 + .../java/com/tangem/tap/TangemApplication.kt | 7 +- .../domain/scanCard/LegacyScanProcessor.kt | 11 +- .../domain/tasks/product/DerivationsFinder.kt | 12 +- .../tap/proxy/redux/DaggerGraphState.kt | 2 + .../local/preferences/PreferencesKeys.kt | 2 - .../token/DefaultUserTokensResponseStore.kt | 26 +++- .../local/token/UserTokensResponseStore.kt | 5 + .../data/common/currency/UserTokensSaver.kt | 14 +- .../tangem/data/common/di/DataCommonModule.kt | 5 +- .../common/currency/UserTokensSaverTest.kt | 136 ++++++++---------- .../DefaultCustomTokensRepository.kt | 17 +-- .../DefaultManageTokensRepository.kt | 10 +- .../managetokens/di/ManageTokensDataModule.kt | 10 +- .../data/onramp/DefaultHotCryptoRepository.kt | 6 +- .../tangem/data/onramp/di/OnrampDataModule.kt | 9 +- .../tangem/data/tokens/di/TokensDataModule.kt | 5 +- .../repository/DefaultCurrenciesRepository.kt | 101 ++++++------- 18 files changed, 188 insertions(+), 193 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt index a005dd97cb..aaeed5140b 100644 --- a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt +++ b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt @@ -21,6 +21,7 @@ import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.issuers.IssuersConfigStorage import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.domain.appcurrency.repository.AppCurrencyRepository import com.tangem.domain.apptheme.GetAppThemeModeUseCase import com.tangem.domain.apptheme.repository.AppThemeModeRepository @@ -145,4 +146,6 @@ interface ApplicationEntryPoint { fun getColdUserWalletBuilderFactory(): ColdUserWalletBuilder.Factory fun getApiConfigsManager(): ApiConfigsManager + + fun getUserTokensResponseStore(): UserTokensResponseStore } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/TangemApplication.kt b/app/src/main/java/com/tangem/tap/TangemApplication.kt index 2be2d0310a..621f3eed14 100644 --- a/app/src/main/java/com/tangem/tap/TangemApplication.kt +++ b/app/src/main/java/com/tangem/tap/TangemApplication.kt @@ -38,6 +38,7 @@ import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.issuers.IssuersConfigStorage import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.utils.NetworkLogsSaveInterceptor import com.tangem.domain.appcurrency.repository.AppCurrencyRepository import com.tangem.domain.apptheme.GetAppThemeModeUseCase @@ -232,6 +233,9 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat private val apiConfigsManager: ApiConfigsManager get() = entryPoint.getApiConfigsManager() + private val userTokensResponseStore: UserTokensResponseStore + get() = entryPoint.getUserTokensResponseStore() + // endregion private val appScope = MainScope() @@ -320,7 +324,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat } derivationsFinder = DerivationsFinder( - appPreferencesStore = appPreferencesStore, + userTokensResponseStore = userTokensResponseStore, dispatchers = dispatchers, ) @@ -370,6 +374,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat uiMessageSender = uiMessageSender, onlineCardVerifier = onlineCardVerifier, coldUserWalletBuilderFactory = coldUserWalletBuilderFactory, + userTokensResponseStore = userTokensResponseStore, ), ), ) diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt index 29665865af..5ce4d8f38e 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt @@ -18,9 +18,6 @@ import com.tangem.core.ui.R import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.toWrappedList import com.tangem.core.ui.message.dialog.Dialogs -import com.tangem.datasource.api.tangemTech.models.UserTokensResponse -import com.tangem.datasource.local.preferences.PreferencesKeys -import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.util.twinsIsTwinned import com.tangem.domain.feedback.models.FeedbackEmailType @@ -258,10 +255,10 @@ internal class LegacyScanProcessor @Inject constructor( onSuccess() return } - val appPrefStoreStore = store.inject(DaggerGraphState::appPreferencesStore) - val tokens = appPrefStoreStore.getObjectSyncOrNull( - key = PreferencesKeys.getUserTokensKey(userWalletId.stringValue), - ) + + val userTokensResponseStore = store.inject(DaggerGraphState::userTokensResponseStore) + val tokens = userTokensResponseStore.getSyncOrNull(userWalletId = userWalletId) + if (scanResponse.card.isAccessCodeSet && tokens == null) { store.dispatchDialogShow( AppDialog.WalletAlreadyWasUsedDialog( diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/DerivationsFinder.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/DerivationsFinder.kt index 6fcad66476..6fde516a55 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/DerivationsFinder.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/DerivationsFinder.kt @@ -5,10 +5,7 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.derivation.DerivationStyle import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.crypto.hdWallet.DerivationPath -import com.tangem.datasource.api.tangemTech.models.UserTokensResponse -import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.datasource.local.preferences.PreferencesKeys -import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.domain.common.DerivationStyleProvider import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation import com.tangem.domain.models.scan.CardDTO @@ -25,7 +22,7 @@ internal data class BlockchainToDerive( // FIXME: May be move to DI, currently unnecessary internal class DerivationsFinder( - private val appPreferencesStore: AppPreferencesStore, + private val userTokensResponseStore: UserTokensResponseStore, private val dispatchers: CoroutineDispatcherProvider, ) { @@ -67,10 +64,7 @@ internal class DerivationsFinder( } private suspend fun getBlockchains(userWalletId: UserWalletId): MutableSet { - val responseTokens = appPreferencesStore.getObjectSyncOrNull( - key = PreferencesKeys.getUserTokensKey(userWalletId.stringValue), - ) - ?.tokens + val responseTokens = userTokensResponseStore.getSyncOrNull(userWalletId = userWalletId)?.tokens ?: return hashSetOf() return responseTokens.asSequence() diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt index 526d65968d..e7817d2245 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt @@ -13,6 +13,7 @@ import com.tangem.datasource.connection.NetworkConnectionManager import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.issuers.IssuersConfigStorage import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.domain.appcurrency.repository.AppCurrencyRepository import com.tangem.domain.apptheme.repository.AppThemeModeRepository import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository @@ -79,4 +80,5 @@ data class DaggerGraphState( val onlineCardVerifier: OnlineCardVerifier? = null, val cardArworksProvider: CardArtworksProvider? = null, val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory? = null, + val userTokensResponseStore: UserTokensResponseStore? = null, ) : StateType \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt index 5e4f9577d1..874a358083 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt @@ -151,8 +151,6 @@ object PreferencesKeys { fun getShouldShowInitialPermissionScreen(permission: String) = booleanPreferencesKey("shouldShowInitialPushPermissionScreen_$permission") // endregion - - fun getUserTokensKey(userWalletId: String) = stringPreferencesKey(name = "user_tokens_$userWalletId") } /** Preferences keys set that should be migrated from "PreferencesDataSource" to a new DataStore */ diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultUserTokensResponseStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultUserTokensResponseStore.kt index c04690b7ce..6e25e1c446 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultUserTokensResponseStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultUserTokensResponseStore.kt @@ -1,10 +1,13 @@ package com.tangem.datasource.local.token +import androidx.datastore.preferences.core.stringPreferencesKey import com.tangem.datasource.api.tangemTech.models.UserTokensResponse import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.datasource.local.preferences.PreferencesKeys +import com.tangem.datasource.local.preferences.utils.getObject import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull +import com.tangem.datasource.local.preferences.utils.storeObject import com.tangem.domain.wallets.models.UserWalletId +import kotlinx.coroutines.flow.Flow /** * Default implementation of [UserTokensResponseStore] @@ -17,9 +20,24 @@ internal class DefaultUserTokensResponseStore( private val appPreferencesStore: AppPreferencesStore, ) : UserTokensResponseStore { - override suspend fun getSyncOrNull(userWalletId: UserWalletId): UserTokensResponse? { - return appPreferencesStore.getObjectSyncOrNull( - key = PreferencesKeys.getUserTokensKey(userWalletId = userWalletId.stringValue), + override fun get(userWalletId: UserWalletId): Flow { + return appPreferencesStore.getObject( + key = createPreferencesKey(userWalletId = userWalletId.stringValue), ) } + + override suspend fun getSyncOrNull(userWalletId: UserWalletId): UserTokensResponse? { + return appPreferencesStore.getObjectSyncOrNull( + key = createPreferencesKey(userWalletId = userWalletId.stringValue), + ) + } + + override suspend fun store(userWalletId: UserWalletId, response: UserTokensResponse) { + appPreferencesStore.storeObject( + key = createPreferencesKey(userWalletId = userWalletId.stringValue), + value = response, + ) + } + + private fun createPreferencesKey(userWalletId: String) = stringPreferencesKey(name = "user_tokens_$userWalletId") } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/token/UserTokensResponseStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/token/UserTokensResponseStore.kt index df802c591c..6fd03be9a2 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/token/UserTokensResponseStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/token/UserTokensResponseStore.kt @@ -2,6 +2,7 @@ package com.tangem.datasource.local.token import com.tangem.datasource.api.tangemTech.models.UserTokensResponse import com.tangem.domain.wallets.models.UserWalletId +import kotlinx.coroutines.flow.Flow /** * Store of [UserTokensResponse] @@ -10,6 +11,10 @@ import com.tangem.domain.wallets.models.UserWalletId */ interface UserTokensResponseStore { + fun get(userWalletId: UserWalletId): Flow + /** Get [UserTokensResponse] synchronously by [userWalletId] or null */ suspend fun getSyncOrNull(userWalletId: UserWalletId): UserTokensResponse? + + suspend fun store(userWalletId: UserWalletId, response: UserTokensResponse) } \ No newline at end of file diff --git a/data/common/src/main/kotlin/com/tangem/data/common/currency/UserTokensSaver.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/UserTokensSaver.kt index de9781bffc..487b96f427 100644 --- a/data/common/src/main/kotlin/com/tangem/data/common/currency/UserTokensSaver.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/UserTokensSaver.kt @@ -4,17 +4,15 @@ import com.tangem.data.common.api.safeApiCall import com.tangem.data.common.tokens.UserTokensBackwardCompatibility import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.api.tangemTech.models.UserTokensResponse -import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.datasource.local.preferences.PreferencesKeys -import com.tangem.datasource.local.preferences.utils.storeObject +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.domain.wallets.models.UserWalletId import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.withContext import timber.log.Timber -class UserTokensSaver constructor( +class UserTokensSaver( private val tangemTechApi: TangemTechApi, - private val appPreferencesStore: AppPreferencesStore, + private val userTokensResponseStore: UserTokensResponseStore, private val dispatchers: CoroutineDispatcherProvider, private val userTokensResponseAddressesEnricher: UserTokensResponseAddressesEnricher, ) { @@ -31,10 +29,8 @@ class UserTokensSaver constructor( } else { compatibleUserTokensResponse } - appPreferencesStore.storeObject( - key = PreferencesKeys.getUserTokensKey(userWalletId = userWalletId.stringValue), - value = enrichedUserTokensResponse, - ) + + userTokensResponseStore.store(userWalletId = userWalletId, response = enrichedUserTokensResponse) } suspend fun storeAndPush(userWalletId: UserWalletId, response: UserTokensResponse) { diff --git a/data/common/src/main/kotlin/com/tangem/data/common/di/DataCommonModule.kt b/data/common/src/main/kotlin/com/tangem/data/common/di/DataCommonModule.kt index 6ceeb800e9..c8c834d85c 100644 --- a/data/common/src/main/kotlin/com/tangem/data/common/di/DataCommonModule.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/di/DataCommonModule.kt @@ -8,7 +8,6 @@ import com.tangem.data.common.currency.UserTokensSaver import com.tangem.data.common.quote.DefaultQuotesFetcher import com.tangem.data.common.quote.QuotesFetcher import com.tangem.datasource.api.tangemTech.TangemTechApi -import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.demo.DemoConfig @@ -61,13 +60,13 @@ internal object DataCommonModule { @Singleton fun provideUserTokensSaver( tangemTechApi: TangemTechApi, - appPreferencesStore: AppPreferencesStore, + userTokensResponseStore: UserTokensResponseStore, dispatchers: CoroutineDispatcherProvider, enricher: UserTokensResponseAddressesEnricher, ): UserTokensSaver { return UserTokensSaver( tangemTechApi = tangemTechApi, - appPreferencesStore = appPreferencesStore, + userTokensResponseStore = userTokensResponseStore, dispatchers = dispatchers, userTokensResponseAddressesEnricher = enricher, ) diff --git a/data/common/src/test/kotlin/com/tangem/data/common/currency/UserTokensSaverTest.kt b/data/common/src/test/kotlin/com/tangem/data/common/currency/UserTokensSaverTest.kt index 8a7e2e922a..caeb9bd3f9 100644 --- a/data/common/src/test/kotlin/com/tangem/data/common/currency/UserTokensSaverTest.kt +++ b/data/common/src/test/kotlin/com/tangem/data/common/currency/UserTokensSaverTest.kt @@ -1,51 +1,35 @@ package com.tangem.data.common.currency -import androidx.datastore.core.DataStore -import androidx.datastore.preferences.core.Preferences -import com.squareup.moshi.Moshi import com.tangem.datasource.api.common.response.ApiResponse 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.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.* -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest -import org.junit.After -import org.junit.Before -import org.junit.Test +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class UserTokensSaverTest { private val tangemTechApi: TangemTechApi = mockk() - private val dataStore: DataStore = mockk(relaxed = true) - private val appPreferenceStore = AppPreferencesStore( - moshi = Moshi.Builder().build(), + private val userTokensResponseStore: UserTokensResponseStore = mockk(relaxed = true) + private val enricher: UserTokensResponseAddressesEnricher = mockk() + + private val userTokensSaver: UserTokensSaver = UserTokensSaver( + tangemTechApi = tangemTechApi, + userTokensResponseStore = userTokensResponseStore, + userTokensResponseAddressesEnricher = enricher, dispatchers = TestingCoroutineDispatcherProvider(), - preferencesDataStore = dataStore, ) - private val dispatchers: CoroutineDispatcherProvider = TestingCoroutineDispatcherProvider() - private val userTokensResponseAddressesEnricher: UserTokensResponseAddressesEnricher = mockk() - private lateinit var userTokensSaver: UserTokensSaver - - @Before - fun setup() { - coEvery { dataStore.data } returns flowOf(mockk(relaxed = true)) - userTokensSaver = UserTokensSaver( - tangemTechApi = tangemTechApi, - appPreferencesStore = appPreferenceStore, - dispatchers = dispatchers, - userTokensResponseAddressesEnricher = userTokensResponseAddressesEnricher, - ) - } - - @After - fun tearDown() { - clearAllMocks() + @BeforeEach + fun resetMocks() { + clearMocks(tangemTechApi, userTokensResponseStore, enricher) } @Test @@ -58,57 +42,30 @@ class UserTokensSaverTest { sort = UserTokensResponse.SortType.BALANCE, tokens = emptyList(), ) + val enrichedResponse = UserTokensResponse( version = 0, group = UserTokensResponse.GroupType.NETWORK, - sort = UserTokensResponse.SortType.BALANCE, + sort = UserTokensResponse.SortType.MANUAL, tokens = emptyList(), ) - coEvery { userTokensResponseAddressesEnricher(userWalletId, response) } returns enrichedResponse - coEvery { dataStore.updateData(any()) } returns mockk(relaxed = true) + + coEvery { enricher(userWalletId, response) } returns enrichedResponse // WHEN userTokensSaver.store(userWalletId, response) // THEN - coVerify { - dataStore.updateData(any()) + coVerifyOrder { + enricher(userWalletId, response) + userTokensResponseStore.store(userWalletId, enrichedResponse) } - coVerify(exactly = 0) { + + coVerify(inverse = true) { tangemTechApi.saveUserTokens(any(), any()) } } - @Test - fun `GIVEN user wallet id and response WHEN storeAndPush THEN should store and push 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.BALANCE, - tokens = emptyList(), - ) - coEvery { userTokensResponseAddressesEnricher(userWalletId, response) } returns enrichedResponse - coEvery { dataStore.updateData(any()) } returns mockk(relaxed = true) - coEvery { tangemTechApi.saveUserTokens(any(), any()) } returns ApiResponse.Success(Unit) - - // WHEN - userTokensSaver.storeAndPush(userWalletId, response) - - // THEN - coVerify { - dataStore.updateData(any()) - tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse) - } - } - @Test fun `GIVEN user wallet id and response WHEN push AND api call fails THEN should log error and call onFailSend`() = runTest { @@ -123,14 +80,13 @@ class UserTokensSaverTest { val enrichedResponse = UserTokensResponse( version = 0, group = UserTokensResponse.GroupType.NETWORK, - sort = UserTokensResponse.SortType.BALANCE, + sort = UserTokensResponse.SortType.MANUAL, tokens = emptyList(), ) val error = ApiResponseError.UnknownException(Exception("API Error")) var onFailSendCalled = false - coEvery { userTokensResponseAddressesEnricher(userWalletId, response) } returns enrichedResponse - coEvery { tangemTechApi.saveUserTokens(any(), any()) } returns - ApiResponse.Error(error) as ApiResponse + coEvery { enricher(userWalletId, response) } returns enrichedResponse + coEvery { tangemTechApi.saveUserTokens(any(), any()) } returns ApiResponse.Error(error) as ApiResponse // WHEN userTokensSaver.push( @@ -140,12 +96,42 @@ class UserTokensSaverTest { ) // THEN - coVerify { + coVerifyOrder { + enricher(userWalletId, response) tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse) } - coVerify(exactly = 0) { - dataStore.updateData(any()) - } + 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 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.BALANCE, + tokens = emptyList(), + ) + coEvery { enricher(userWalletId, response) } returns enrichedResponse + coEvery { + tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse) + } returns ApiResponse.Success(Unit) + + // WHEN + userTokensSaver.storeAndPush(userWalletId, response) + + // THEN + coVerifyOrder { + enricher(userWalletId, response) + tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse) + } + } } \ No newline at end of file diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt index 9064c8fb08..49054eb06e 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt @@ -12,10 +12,7 @@ import com.tangem.data.common.network.NetworkFactory import com.tangem.data.managetokens.utils.TokenAddressesConverter import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.tangemTech.TangemTechApi -import com.tangem.datasource.api.tangemTech.models.UserTokensResponse -import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.datasource.local.preferences.PreferencesKeys -import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.common.extensions.canHandleBlockchain import com.tangem.domain.common.extensions.supportedBlockchains @@ -35,7 +32,7 @@ import kotlinx.coroutines.withContext internal class DefaultCustomTokensRepository( private val tangemTechApi: TangemTechApi, private val userWalletsStore: UserWalletsStore, - private val appPreferencesStore: AppPreferencesStore, + private val userTokensResponseStore: UserTokensResponseStore, private val walletManagersFacade: WalletManagersFacade, private val excludedBlockchains: ExcludedBlockchains, private val dispatchers: CoroutineDispatcherProvider, @@ -71,9 +68,8 @@ internal class DefaultCustomTokensRepository( contractAddress: String?, ): Boolean { return withContext(dispatchers.io) { - val storedCurrencies = appPreferencesStore.getObjectSyncOrNull( - key = PreferencesKeys.getUserTokensKey(userWalletId.stringValue), - ) + val storedCurrencies = userTokensResponseStore.getSyncOrNull(userWalletId) + requireNotNull(storedCurrencies) { "User tokens not found for user wallet [$userWalletId] while checking if currency is not added" } @@ -230,9 +226,8 @@ internal class DefaultCustomTokensRepository( contractAddress = currency.contractAddress, ) } - val storedCurrencies = appPreferencesStore.getObjectSyncOrNull( - key = PreferencesKeys.getUserTokensKey(userWalletId.stringValue), - ) + val storedCurrencies = userTokensResponseStore.getSyncOrNull(userWalletId) + requireNotNull(storedCurrencies) { "User tokens not found for user wallet [$userWalletId] while removing currency" } diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt index 7b4aef4179..55f8660e21 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt @@ -17,9 +17,7 @@ import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.api.tangemTech.models.UserTokensResponse import com.tangem.datasource.local.config.testnet.TestnetTokensStorage -import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.datasource.local.preferences.PreferencesKeys -import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.common.TapWorkarounds.isTestCard import com.tangem.domain.common.extensions.canHandleBlockchain @@ -46,7 +44,7 @@ internal class DefaultManageTokensRepository( private val tangemTechApi: TangemTechApi, private val userWalletsStore: UserWalletsStore, private val manageTokensUpdateFetcher: ManageTokensUpdateFetcher, - private val appPreferencesStore: AppPreferencesStore, + private val userTokensResponseStore: UserTokensResponseStore, private val testnetTokensStorage: TestnetTokensStorage, private val excludedBlockchains: ExcludedBlockchains, private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory, @@ -251,9 +249,7 @@ internal class DefaultManageTokensRepository( } private suspend fun getSavedUserTokensResponseSync(key: UserWalletId): UserTokensResponse? { - return appPreferencesStore.getObjectSyncOrNull( - key = PreferencesKeys.getUserTokensKey(key.stringValue), - ) + return userTokensResponseStore.getSyncOrNull(userWalletId = key) } override suspend fun checkCurrencyUnsupportedState( diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt index 1e3cc8eafe..87943d1e88 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt @@ -9,7 +9,7 @@ import com.tangem.data.managetokens.DefaultManageTokensRepository import com.tangem.data.managetokens.utils.ManageTokensUpdateFetcher import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.local.config.testnet.TestnetTokensStorage -import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.managetokens.repository.CustomTokensRepository import com.tangem.domain.managetokens.repository.ManageTokensRepository @@ -31,7 +31,7 @@ internal object ManageTokensDataModule { tangemTechApi: TangemTechApi, userWalletsStore: UserWalletsStore, manageTokensUpdateFetcher: ManageTokensUpdateFetcher, - appPreferencesStore: AppPreferencesStore, + userTokensResponseStore: UserTokensResponseStore, testnetTokensStorage: TestnetTokensStorage, dispatchers: CoroutineDispatcherProvider, excludedBlockchains: ExcludedBlockchains, @@ -42,7 +42,7 @@ internal object ManageTokensDataModule { tangemTechApi = tangemTechApi, userWalletsStore = userWalletsStore, manageTokensUpdateFetcher = manageTokensUpdateFetcher, - appPreferencesStore = appPreferencesStore, + userTokensResponseStore = userTokensResponseStore, testnetTokensStorage = testnetTokensStorage, excludedBlockchains = excludedBlockchains, cardCryptoCurrencyFactory = cardCryptoCurrencyFactory, @@ -56,7 +56,7 @@ internal object ManageTokensDataModule { fun provideCustomTokensRepository( tangemTechApi: TangemTechApi, userWalletsStore: UserWalletsStore, - appPreferencesStore: AppPreferencesStore, + userTokensResponseStore: UserTokensResponseStore, walletManagersFacade: WalletManagersFacade, dispatchers: CoroutineDispatcherProvider, excludedBlockchains: ExcludedBlockchains, @@ -66,7 +66,7 @@ internal object ManageTokensDataModule { return DefaultCustomTokensRepository( tangemTechApi = tangemTechApi, userWalletsStore = userWalletsStore, - appPreferencesStore = appPreferencesStore, + userTokensResponseStore = userTokensResponseStore, walletManagersFacade = walletManagersFacade, excludedBlockchains = excludedBlockchains, dispatchers = dispatchers, diff --git a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultHotCryptoRepository.kt b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultHotCryptoRepository.kt index e0d1ec226d..4df4a7a45c 100644 --- a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultHotCryptoRepository.kt +++ b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultHotCryptoRepository.kt @@ -18,6 +18,7 @@ import com.tangem.datasource.exchangeservice.hotcrypto.HotCryptoResponseStore import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getObject +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.common.extensions.canHandleBlockchain import com.tangem.domain.common.extensions.canHandleToken @@ -58,6 +59,7 @@ internal class DefaultHotCryptoRepository( private val userWalletsStore: UserWalletsStore, private val tangemTechApi: TangemTechApi, private val appPreferencesStore: AppPreferencesStore, + private val userTokensResponseStore: UserTokensResponseStore, private val dispatchers: CoroutineDispatcherProvider, private val analyticsEventHandler: AnalyticsEventHandler, ) : HotCryptoRepository { @@ -103,9 +105,7 @@ internal class DefaultHotCryptoRepository( private fun getWalletsWithTokensFlow(): Flow>> { return userWalletsStore.userWallets.flatMapLatest { userWallets -> val flows = userWallets.map { userWallet -> - appPreferencesStore.getObject( - key = PreferencesKeys.getUserTokensKey(userWallet.walletId.stringValue), - ) + userTokensResponseStore.get(userWalletId = userWallet.walletId) .map { userWallet to it?.tokens.orEmpty() } } diff --git a/data/onramp/src/main/java/com/tangem/data/onramp/di/OnrampDataModule.kt b/data/onramp/src/main/java/com/tangem/data/onramp/di/OnrampDataModule.kt index 3ecf2df253..9adfb5cc75 100644 --- a/data/onramp/src/main/java/com/tangem/data/onramp/di/OnrampDataModule.kt +++ b/data/onramp/src/main/java/com/tangem/data/onramp/di/OnrampDataModule.kt @@ -8,7 +8,6 @@ import com.tangem.data.onramp.DefaultOnrampErrorResolver import com.tangem.data.onramp.DefaultOnrampRepository import com.tangem.data.onramp.DefaultOnrampTransactionRepository import com.tangem.data.onramp.converters.error.OnrampErrorConverter -import com.tangem.domain.onramp.repositories.LegacyTopUpRepository import com.tangem.data.onramp.legacy.MercuryoTopUpRepository import com.tangem.datasource.api.express.TangemExpressApi import com.tangem.datasource.api.express.models.response.ExpressErrorResponse @@ -24,11 +23,9 @@ import com.tangem.datasource.local.onramp.pairs.OnrampPairsStore import com.tangem.datasource.local.onramp.paymentmethods.OnrampPaymentMethodsStore import com.tangem.datasource.local.onramp.quotes.OnrampQuotesStore import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.local.userwallet.UserWalletsStore -import com.tangem.domain.onramp.repositories.HotCryptoRepository -import com.tangem.domain.onramp.repositories.OnrampErrorResolver -import com.tangem.domain.onramp.repositories.OnrampRepository -import com.tangem.domain.onramp.repositories.OnrampTransactionRepository +import com.tangem.domain.onramp.repositories.* import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module @@ -104,6 +101,7 @@ internal object OnrampDataModule { appPreferencesStore: AppPreferencesStore, dispatchers: CoroutineDispatcherProvider, analyticsEventHandler: AnalyticsEventHandler, + userTokensResponseStore: UserTokensResponseStore, ): HotCryptoRepository { return DefaultHotCryptoRepository( excludedBlockchains = excludedBlockchains, @@ -113,6 +111,7 @@ internal object OnrampDataModule { appPreferencesStore = appPreferencesStore, dispatchers = dispatchers, analyticsEventHandler = analyticsEventHandler, + userTokensResponseStore = userTokensResponseStore, ) } diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt index eece90d80a..64bcd2722c 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/di/TokensDataModule.kt @@ -10,6 +10,7 @@ import com.tangem.data.tokens.repository.DefaultPolkadotAccountHealthCheckReposi import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.exchangeservice.swap.ExpressServiceLoader import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.CurrencyChecksRepository @@ -30,7 +31,7 @@ internal object TokensDataModule { @Singleton fun provideCurrenciesRepository( tangemTechApi: TangemTechApi, - appPreferencesStore: AppPreferencesStore, + userTokensResponseStore: UserTokensResponseStore, userWalletsStore: UserWalletsStore, walletManagersFacade: WalletManagersFacade, cacheRegistry: CacheRegistry, @@ -45,7 +46,7 @@ internal object TokensDataModule { userWalletsStore = userWalletsStore, walletManagersFacade = walletManagersFacade, cacheRegistry = cacheRegistry, - appPreferencesStore = appPreferencesStore, + userTokensResponseStore = userTokensResponseStore, expressServiceLoader = expressServiceLoader, dispatchers = dispatchers, excludedBlockchains = excludedBlockchains, diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt index ce4c171722..cd903d6cbb 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt @@ -14,10 +14,7 @@ import com.tangem.datasource.api.express.models.request.LeastTokenInfo import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.api.tangemTech.models.UserTokensResponse import com.tangem.datasource.exchangeservice.swap.ExpressServiceLoader -import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.datasource.local.preferences.PreferencesKeys -import com.tangem.datasource.local.preferences.utils.getObject -import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull +import com.tangem.datasource.local.token.UserTokensResponseStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.core.error.DataError @@ -28,11 +25,7 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.FeePaidCurrency import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.domain.wallets.models.UserWallet -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.domain.wallets.models.isLocked -import com.tangem.domain.wallets.models.isMultiCurrency -import com.tangem.domain.wallets.models.requireColdWallet +import com.tangem.domain.wallets.models.* import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.* import kotlinx.coroutines.flow.* @@ -45,11 +38,11 @@ internal class DefaultCurrenciesRepository( private val userWalletsStore: UserWalletsStore, private val walletManagersFacade: WalletManagersFacade, private val cacheRegistry: CacheRegistry, - private val appPreferencesStore: AppPreferencesStore, private val expressServiceLoader: ExpressServiceLoader, private val dispatchers: CoroutineDispatcherProvider, private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory, private val userTokensSaver: UserTokensSaver, + private val userTokensResponseStore: UserTokensResponseStore, excludedBlockchains: ExcludedBlockchains, ) : CurrenciesRepository { @@ -96,7 +89,10 @@ internal class DefaultCurrenciesRepository( response = updatedResponse, ) - fetchExpressAssetsByNetworkIds(userWalletId, updatedResponse) + fetchExpressAssetsByNetworkIds( + userWallet = userWalletsStore.getSyncStrict(key = userWalletId), + userTokens = updatedResponse, + ) } } @@ -119,7 +115,11 @@ internal class DefaultCurrenciesRepository( userWalletId = userWalletId, response = updatedResponse, ) - fetchExpressAssetsByNetworkIds(userWalletId, updatedResponse) + + fetchExpressAssetsByNetworkIds( + userWallet = userWalletsStore.getSyncStrict(key = userWalletId), + userTokens = updatedResponse, + ) } } @@ -205,7 +205,7 @@ internal class DefaultCurrenciesRepository( override fun getWalletCurrenciesUpdates(userWalletId: UserWalletId): Flow> { return channelFlow { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) if (userWallet.isMultiCurrency) { getMultiCurrencyWalletCurrenciesUpdates(userWalletId).collect(::send) @@ -222,13 +222,19 @@ internal class DefaultCurrenciesRepository( refresh: Boolean, ): CryptoCurrency { return withContext(dispatchers.io) { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = false) val currency = cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard( userWallet.requireColdWallet().scanResponse, ) - fetchExpressAssetsByNetworkIds(userWalletId, listOf(currency), refresh) + + fetchExpressAssetsByNetworkIds( + userWallet = userWallet, + cryptoCurrencies = listOf(currency), + refresh = refresh, + ) + currency } } @@ -238,7 +244,8 @@ internal class DefaultCurrenciesRepository( refresh: Boolean, ): List { return withContext(dispatchers.io) { - val scanResponse = getUserWallet(userWalletId).requireColdWallet().scanResponse + val userWallet = userWalletsStore.getSyncStrict(userWalletId) + val scanResponse = userWallet.requireColdWallet().scanResponse val currencies = if (scanResponse.cardTypesResolver.isSingleWalletWithToken()) { cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(scanResponse = scanResponse) @@ -248,7 +255,12 @@ internal class DefaultCurrenciesRepository( } } - fetchExpressAssetsByNetworkIds(userWalletId, currencies, refresh) + fetchExpressAssetsByNetworkIds( + userWallet = userWallet, + cryptoCurrencies = currencies, + refresh = refresh, + ) + currencies } } @@ -258,7 +270,7 @@ internal class DefaultCurrenciesRepository( id: CryptoCurrency.ID, ): CryptoCurrency { return withContext(dispatchers.io) { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = false) val currency = cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken( @@ -266,14 +278,14 @@ internal class DefaultCurrenciesRepository( ) .find { it.id == id } requireNotNull(currency) { "Unable to find currency with provided ID: $id" } - fetchExpressAssetsByNetworkIds(userWalletId, listOf(currency)) + fetchExpressAssetsByNetworkIds(userWallet, listOf(currency)) currency } } override fun getMultiCurrencyWalletCurrenciesUpdates(userWalletId: UserWalletId): Flow> { return channelFlow { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true) getMultiCurrencyWalletCurrencies(userWallet) @@ -290,7 +302,7 @@ internal class DefaultCurrenciesRepository( userWalletId: UserWalletId, refresh: Boolean, ): List = withContext(dispatchers.io) { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true) fetchTokensIfCacheExpired(userWallet, refresh) @@ -307,7 +319,7 @@ internal class DefaultCurrenciesRepository( override suspend fun getMultiCurrencyWalletCachedCurrenciesSync(userWalletId: UserWalletId) = withContext(dispatchers.io) { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true) val storedTokens = requireNotNull( @@ -329,7 +341,7 @@ internal class DefaultCurrenciesRepository( override suspend fun getMultiCurrencyWalletCurrency(userWalletId: UserWalletId, id: String): CryptoCurrency = withContext(dispatchers.io) { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true) val response = requireNotNull( @@ -352,7 +364,7 @@ internal class DefaultCurrenciesRepository( derivationPath: Network.DerivationPath, ): CryptoCurrency.Coin { return withContext(dispatchers.io) { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) ensureIsCorrectUserWallet(userWallet = userWallet, isMultiCurrencyWalletExpected = true) fetchTokensIfCacheExpired(userWallet = userWallet, refresh = false) @@ -382,7 +394,7 @@ internal class DefaultCurrenciesRepository( override fun isTokensGrouped(userWalletId: UserWalletId): Flow { return channelFlow { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) if (userWallet.isMultiCurrency) { getSavedUserTokensResponse(userWalletId) @@ -398,7 +410,7 @@ internal class DefaultCurrenciesRepository( override fun isTokensSortedByBalance(userWalletId: UserWalletId): Flow { return channelFlow { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) if (userWallet.isMultiCurrency) { getSavedUserTokensResponse(userWalletId) @@ -470,7 +482,7 @@ internal class DefaultCurrenciesRepository( contractAddress: String, networkId: String, ): CryptoCurrency.Token { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) val token = withContext(dispatchers.io) { val foundToken = tangemTechApi.getCoins( contractAddress = contractAddress, @@ -599,7 +611,7 @@ internal class DefaultCurrenciesRepository( userTokensSaver.store(userWalletId, compatibleUserTokensResponse) - fetchExpressAssetsByNetworkIds(userWalletId, compatibleUserTokensResponse) + fetchExpressAssetsByNetworkIds(userWallet, compatibleUserTokensResponse) } private suspend fun checkIsEmptyDemoWallet(userWallet: UserWallet.Cold): Boolean { @@ -608,7 +620,7 @@ internal class DefaultCurrenciesRepository( return demoConfig.isDemoCardId(userWallet.cardId) && response == null } - private suspend fun fetchExpressAssetsByNetworkIds(userWalletId: UserWalletId, userTokens: UserTokensResponse) { + private suspend fun fetchExpressAssetsByNetworkIds(userWallet: UserWallet, userTokens: UserTokensResponse) { val tokens = userTokens.tokens.map { token -> LeastTokenInfo( contractAddress = token.contractAddress ?: EMPTY_CONTRACT_ADDRESS_VALUE, @@ -617,12 +629,12 @@ internal class DefaultCurrenciesRepository( } coroutineScope { - launch { expressServiceLoader.update(getUserWallet(userWalletId), tokens) } + launch { expressServiceLoader.update(userWallet, tokens) } } } private suspend fun fetchExpressAssetsByNetworkIds( - userWalletId: UserWalletId, + userWallet: UserWallet, cryptoCurrencies: List, refresh: Boolean = false, ) { @@ -634,11 +646,11 @@ internal class DefaultCurrenciesRepository( ) } cacheRegistry.invokeOnExpire( - key = getAssetsCacheKey(userWalletId), + key = getAssetsCacheKey(userWallet.walletId), skipCache = refresh, block = { coroutineScope { - launch { expressServiceLoader.update(getUserWallet(userWalletId), tokens) } + launch { expressServiceLoader.update(userWallet, tokens) } } }, ) @@ -648,9 +660,8 @@ internal class DefaultCurrenciesRepository( private suspend fun handleFetchTokensError(userWallet: UserWallet, e: ApiResponseError): UserTokensResponse { val userWalletId = userWallet.walletId - val response = appPreferencesStore.getObjectSyncOrNull( - key = PreferencesKeys.getUserTokensKey(userWalletId.stringValue), - ) ?: createDefaultUserTokensResponse(userWallet) + val response = userTokensResponseStore.getSyncOrNull(userWalletId = userWalletId) + ?: createDefaultUserTokensResponse(userWallet = userWallet) if (e is ApiResponseError.HttpException && e.code == ApiResponseError.HttpException.Code.NOT_FOUND) { Timber.w(e, "Requested currencies could not be found in the remote store for: $userWalletId") @@ -666,20 +677,14 @@ internal class DefaultCurrenciesRepository( private fun createDefaultUserTokensResponse(userWallet: UserWallet) = userTokensResponseFactory.createUserTokensResponse( currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard( - userWallet.requireColdWallet().scanResponse, + userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY] ), isGroupedByNetwork = false, isSortedByBalance = false, ) - private fun getUserWallet(userWalletId: UserWalletId): UserWallet { - return requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) { - "Unable to find a user wallet with provided ID: $userWalletId" - } - } - private fun ensureIsCorrectUserWallet(userWalletId: UserWalletId, isMultiCurrencyWalletExpected: Boolean) { - val userWallet = getUserWallet(userWalletId) + val userWallet = userWalletsStore.getSyncStrict(userWalletId) ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected) } @@ -708,14 +713,10 @@ internal class DefaultCurrenciesRepository( private fun getTokensCacheKey(userWalletId: UserWalletId): String = "tokens_cache_key_${userWalletId.stringValue}" private fun getSavedUserTokensResponse(key: UserWalletId): Flow { - return appPreferencesStore - .getObject(PreferencesKeys.getUserTokensKey(userWalletId = key.stringValue)) - .filterNotNull() + return userTokensResponseStore.get(userWalletId = key).filterNotNull() } private suspend fun getSavedUserTokensResponseSync(key: UserWalletId): UserTokensResponse? { - return appPreferencesStore.getObjectSyncOrNull( - key = PreferencesKeys.getUserTokensKey(key.stringValue), - ) + return userTokensResponseStore.getSyncOrNull(userWalletId = key) } } \ No newline at end of file