Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-02 18:48:42 +04:00
parent a540a98d01
commit 47d119c2da
6 changed files with 69 additions and 1 deletions

View file

@ -24,6 +24,8 @@ 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 kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.withContext
import javax.inject.Inject
import javax.inject.Singleton
@ -77,6 +79,10 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
return migratedResponse
}
override fun get(userWalletId: UserWalletId): Flow<GetWalletAccountsResponse> {
return getAccountsResponseStore(userWalletId = userWalletId).data.filterNotNull()
}
override suspend fun getSaved(userWalletId: UserWalletId): GetWalletAccountsResponse? {
return getAccountsResponseStore(userWalletId = userWalletId).getSyncOrNull()
}

View file

@ -20,6 +20,7 @@ import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResp
import com.tangem.datasource.api.tangemTech.models.account.SaveWalletAccountsResponse
import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.test.core.getEmittedValues
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.*
import kotlinx.coroutines.flow.MutableStateFlow
@ -340,6 +341,47 @@ class DefaultWalletAccountsFetcherTest {
}
}
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
inner class Get {
@Test
fun get() = runTest {
// Arrange
val response = createGetWalletAccountsResponse(userWalletId = userWalletId)
accountsResponseStoreFlow.value = response
// Act
val actual = getEmittedValues(fetcher.get(userWalletId))
// Assert
val expected = response
Truth.assertThat(actual).containsExactly(expected)
coVerifyOrder {
accountsResponseStoreFactory.create(userWalletId)
accountsResponseStore.data
}
}
@Test
fun `get if store is empty`() = runTest {
// Arrange
accountsResponseStoreFlow.value = null
// Act
val actual = getEmittedValues(fetcher.get(userWalletId))
// Assert
Truth.assertThat(actual).isEmpty()
coVerifyOrder {
accountsResponseStoreFactory.create(userWalletId)
accountsResponseStore.data
}
}
}
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
inner class Store {

View file

@ -2,6 +2,7 @@ package com.tangem.data.common.account
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
import com.tangem.domain.models.wallet.UserWalletId
import kotlinx.coroutines.flow.Flow
/**
* Component for fetching wallet accounts
@ -14,6 +15,9 @@ interface WalletAccountsFetcher {
@Throws
suspend fun fetch(userWalletId: UserWalletId): GetWalletAccountsResponse
/** Get wallet accounts by [userWalletId] */
fun get(userWalletId: UserWalletId): Flow<GetWalletAccountsResponse>
/** Get saved wallet accounts by [userWalletId] */
suspend fun getSaved(userWalletId: UserWalletId): GetWalletAccountsResponse?
}

View file

@ -23,6 +23,7 @@ dependencies {
implementation(projects.data.common)
/** Domain modules */
implementation(projects.domain.account)
implementation(projects.domain.onramp)
implementation(projects.domain.legacy)
implementation(projects.domain.card)

View file

@ -7,16 +7,19 @@ import com.tangem.blockchainsdk.utils.OLD_POLYGON_NAME
import com.tangem.blockchainsdk.utils.fromNetworkId
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
import com.tangem.data.common.account.WalletAccountsFetcher
import com.tangem.data.onramp.converters.HotCryptoCurrencyConverter
import com.tangem.datasource.api.common.response.ApiResponseError
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.models.HotCryptoResponse
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse
import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
import com.tangem.datasource.exchangeservice.hotcrypto.HotCryptoResponseStore
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.card.common.extensions.canHandleBlockchain
import com.tangem.domain.card.common.extensions.canHandleToken
import com.tangem.domain.models.wallet.UserWallet
@ -54,7 +57,9 @@ internal class DefaultHotCryptoRepository(
private val userWalletsStore: UserWalletsStore,
private val tangemTechApi: TangemTechApi,
private val appCurrencyResponseStore: AppCurrencyResponseStore,
private val accountsFeatureToggles: AccountsFeatureToggles,
private val userTokensResponseStore: UserTokensResponseStore,
private val walletAccountsFetcher: WalletAccountsFetcher,
private val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventHandler: AnalyticsEventHandler,
) : HotCryptoRepository {
@ -100,7 +105,11 @@ internal class DefaultHotCryptoRepository(
private fun getWalletsWithTokensFlow(): Flow<Map<UserWallet, List<UserTokensResponse.Token>>> {
return userWalletsStore.userWallets.flatMapLatest { userWallets ->
val flows = userWallets.map { userWallet ->
userTokensResponseStore.get(userWalletId = userWallet.walletId)
if (accountsFeatureToggles.isFeatureEnabled) {
walletAccountsFetcher.get(userWalletId = userWallet.walletId).map { it.toUserTokensResponse() }
} else {
userTokensResponseStore.get(userWalletId = userWallet.walletId)
}
.map { userWallet to it?.tokens.orEmpty() }
}

View file

@ -3,6 +3,7 @@ package com.tangem.data.onramp.di
import com.squareup.moshi.Moshi
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.data.common.account.WalletAccountsFetcher
import com.tangem.data.onramp.DefaultHotCryptoRepository
import com.tangem.data.onramp.DefaultOnrampErrorResolver
import com.tangem.data.onramp.DefaultOnrampRepository
@ -28,6 +29,7 @@ import com.tangem.datasource.local.onramp.sepa.OnrampSepaAvailabilityStore
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.account.featuretoggle.AccountsFeatureToggles
import com.tangem.domain.onramp.repositories.*
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -109,6 +111,8 @@ internal object OnrampDataModule {
dispatchers: CoroutineDispatcherProvider,
analyticsEventHandler: AnalyticsEventHandler,
userTokensResponseStore: UserTokensResponseStore,
accountsFeatureToggles: AccountsFeatureToggles,
walletAccountsFetcher: WalletAccountsFetcher,
): HotCryptoRepository {
return DefaultHotCryptoRepository(
excludedBlockchains = excludedBlockchains,
@ -119,6 +123,8 @@ internal object OnrampDataModule {
dispatchers = dispatchers,
analyticsEventHandler = analyticsEventHandler,
userTokensResponseStore = userTokensResponseStore,
accountsFeatureToggles = accountsFeatureToggles,
walletAccountsFetcher = walletAccountsFetcher,
)
}