Updated on 2026-08-14
This commit is contained in:
parent
47a323859a
commit
750a696a84
17 changed files with 636 additions and 200 deletions
|
|
@ -0,0 +1,64 @@
|
|||
package com.tangem.data.common.currency
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusProducer
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
|
||||
import com.tangem.domain.notifications.toggles.NotificationsFeatureToggles
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class UserTokensResponseAddressesEnricher @Inject constructor(
|
||||
private val notificationsFeatureToggles: NotificationsFeatureToggles,
|
||||
private val walletsRepository: WalletsRepository,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId, response: UserTokensResponse): UserTokensResponse {
|
||||
if (!notificationsFeatureToggles.isNotificationsEnabled) {
|
||||
return response
|
||||
}
|
||||
|
||||
val isNotificationsEnabled = walletsRepository.isNotificationsEnabled(userWalletId)
|
||||
|
||||
return withContext(dispatchers.default) {
|
||||
val networksStatuses = if (isNotificationsEnabled) {
|
||||
multiNetworkStatusSupplier.invoke(MultiNetworkStatusProducer.Params(userWalletId)).first()
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
|
||||
val enrichedTokens = response.tokens.map { token ->
|
||||
if (isNotificationsEnabled) {
|
||||
val matchingNetwork = networksStatuses.find { status ->
|
||||
status.network.backendId == token.networkId &&
|
||||
status.network.derivationPath.value == token.derivationPath
|
||||
} ?: return@map token
|
||||
|
||||
val networkAddress = when (matchingNetwork.value) {
|
||||
is NetworkStatus.Verified -> (matchingNetwork.value as NetworkStatus.Verified).address
|
||||
is NetworkStatus.NoAccount -> (matchingNetwork.value as NetworkStatus.NoAccount).address
|
||||
else -> null
|
||||
}
|
||||
|
||||
val addresses = networkAddress
|
||||
?.availableAddresses
|
||||
?.map { it.value }
|
||||
?.toList()
|
||||
.orEmpty()
|
||||
|
||||
token.copy(addresses = addresses)
|
||||
} else {
|
||||
token.copy(addresses = emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
response.copy(tokens = enrichedTokens, notifyStatus = isNotificationsEnabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
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.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.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
|
||||
class UserTokensSaver constructor(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val userTokensResponseAddressesEnricher: UserTokensResponseAddressesEnricher,
|
||||
) {
|
||||
private val userTokensBackwardCompatibility = UserTokensBackwardCompatibility()
|
||||
|
||||
suspend fun store(userWalletId: UserWalletId, response: UserTokensResponse, useEnricher: Boolean = true) =
|
||||
withContext(dispatchers.io) {
|
||||
val compatibleUserTokensResponse = userTokensBackwardCompatibility.applyCompatibilityAndGetUpdated(response)
|
||||
val enrichedUserTokensResponse = if (useEnricher) {
|
||||
userTokensResponseAddressesEnricher(
|
||||
userWalletId = userWalletId,
|
||||
response = compatibleUserTokensResponse,
|
||||
)
|
||||
} else {
|
||||
compatibleUserTokensResponse
|
||||
}
|
||||
appPreferencesStore.storeObject(
|
||||
key = PreferencesKeys.getUserTokensKey(userWalletId = userWalletId.stringValue),
|
||||
value = enrichedUserTokensResponse,
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun storeAndPush(userWalletId: UserWalletId, response: UserTokensResponse) {
|
||||
val enrichedUserTokensResponse = userTokensResponseAddressesEnricher(
|
||||
userWalletId = userWalletId,
|
||||
response = response,
|
||||
)
|
||||
store(userWalletId, enrichedUserTokensResponse, false)
|
||||
push(userWalletId, enrichedUserTokensResponse, false)
|
||||
}
|
||||
|
||||
suspend fun push(userWalletId: UserWalletId, response: UserTokensResponse, useEnricher: Boolean = true) =
|
||||
withContext(dispatchers.io) {
|
||||
val enrichedUserTokensResponse = if (useEnricher) {
|
||||
userTokensResponseAddressesEnricher(
|
||||
userWalletId = userWalletId,
|
||||
response = response,
|
||||
)
|
||||
} else {
|
||||
response
|
||||
}
|
||||
safeApiCall({ tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedUserTokensResponse).bind() }) {
|
||||
Timber.e(it, "Unable to push user tokens for: ${userWalletId.stringValue}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,17 @@ package com.tangem.data.common.di
|
|||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.common.currency.CardCryptoCurrencyFactory
|
||||
import com.tangem.data.common.currency.DefaultCardCryptoCurrencyFactory
|
||||
import com.tangem.data.common.currency.UserTokensResponseAddressesEnricher
|
||||
import com.tangem.data.common.currency.UserTokensSaver
|
||||
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
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
|
||||
import com.tangem.domain.notifications.toggles.NotificationsFeatureToggles
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -30,4 +38,36 @@ internal object DataCommonModule {
|
|||
userTokensResponseStore = userTokensResponseStore,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideUserTokensEncricher(
|
||||
notificationsFeatureToggles: NotificationsFeatureToggles,
|
||||
walletsRepository: WalletsRepository,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): UserTokensResponseAddressesEnricher {
|
||||
return UserTokensResponseAddressesEnricher(
|
||||
notificationsFeatureToggles = notificationsFeatureToggles,
|
||||
walletsRepository = walletsRepository,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideUserTokensSaver(
|
||||
tangemTechApi: TangemTechApi,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
enricher: UserTokensResponseAddressesEnricher,
|
||||
): UserTokensSaver {
|
||||
return UserTokensSaver(
|
||||
tangemTechApi = tangemTechApi,
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
dispatchers = dispatchers,
|
||||
userTokensResponseAddressesEnricher = enricher,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.tangem.data.common.tokens
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.blockchainsdk.utils.toCoinId
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
|
||||
/**
|
||||
* Helper to apply compatibility changes for [UserTokensResponse] to support old saved tokens
|
||||
* in new application with new IDs
|
||||
*/
|
||||
internal class UserTokensBackwardCompatibility {
|
||||
|
||||
fun applyCompatibilityAndGetUpdated(userTokensResponse: UserTokensResponse): UserTokensResponse {
|
||||
return userTokensResponse.copy(
|
||||
tokens = userTokensResponse.tokens.map { token ->
|
||||
val oldSavedId = NETWORKS_TO_OLD_SAVED_IDS[token.networkId]
|
||||
if (oldSavedId != null && token.id == oldSavedId) {
|
||||
Blockchain.fromNetworkId(token.networkId)?.let { blockchain ->
|
||||
token.copy(
|
||||
id = blockchain.toCoinId(),
|
||||
)
|
||||
} ?: token
|
||||
} else {
|
||||
token
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val NETWORKS_TO_OLD_SAVED_IDS = mapOf(
|
||||
"optimistic-ethereum" to "ethereum",
|
||||
"arbitrum-one" to "ethereum",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
package com.tangem.data.common.currency
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
|
||||
import com.tangem.domain.notifications.toggles.NotificationsFeatureToggles
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.tokens.model.NetworkAddress
|
||||
import io.mockk.clearAllMocks
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class UserTokensResponseAddressesEnricherTest {
|
||||
|
||||
private lateinit var notificationsFeatureToggles: NotificationsFeatureToggles
|
||||
private lateinit var walletsRepository: WalletsRepository
|
||||
private val dispatchers: CoroutineDispatcherProvider = TestingCoroutineDispatcherProvider()
|
||||
private lateinit var multiNetworkStatusSupplier: MultiNetworkStatusSupplier
|
||||
private lateinit var enricher: UserTokensResponseAddressesEnricher
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
notificationsFeatureToggles = mockk()
|
||||
walletsRepository = mockk()
|
||||
multiNetworkStatusSupplier = mockk()
|
||||
|
||||
enricher = UserTokensResponseAddressesEnricher(
|
||||
notificationsFeatureToggles = notificationsFeatureToggles,
|
||||
walletsRepository = walletsRepository,
|
||||
dispatchers = dispatchers,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
clearAllMocks()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN notifications are disabled globally WHEN invoke THEN return original response`() = runTest {
|
||||
// GIVEN
|
||||
val userWalletId = UserWalletId("1234567890abcdef")
|
||||
val token = createToken()
|
||||
val response = createUserTokensResponse(tokens = listOf(token))
|
||||
every { notificationsFeatureToggles.isNotificationsEnabled } returns false
|
||||
|
||||
// WHEN
|
||||
val result = enricher(userWalletId, response)
|
||||
|
||||
// THEN
|
||||
assertThat(result).isEqualTo(response)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN notifications are disabled for wallet WHEN invoke THEN return response with empty addresses`() =
|
||||
runTest {
|
||||
// GIVEN
|
||||
val userWalletId = UserWalletId("1234567890abcdef")
|
||||
val token = createToken()
|
||||
val response = createUserTokensResponse(tokens = listOf(token))
|
||||
every { notificationsFeatureToggles.isNotificationsEnabled } returns true
|
||||
coEvery { walletsRepository.isNotificationsEnabled(userWalletId) } returns false
|
||||
coEvery {
|
||||
multiNetworkStatusSupplier.invoke(any())
|
||||
} returns flowOf(
|
||||
setOf(
|
||||
NetworkStatus(
|
||||
network = mockk {
|
||||
every { backendId } returns "ethereum"
|
||||
every { derivationPath.value } returns "m/44'/60'/0'/0/0"
|
||||
},
|
||||
value = NetworkStatus.Verified(
|
||||
address = mockk {
|
||||
every { availableAddresses } returns emptySet()
|
||||
},
|
||||
amounts = emptyMap(),
|
||||
pendingTransactions = emptyMap(),
|
||||
source = StatusSource.ACTUAL,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = enricher(userWalletId, response)
|
||||
|
||||
// THEN
|
||||
assertThat(result.tokens).hasSize(1)
|
||||
assertThat(result.tokens[0].addresses).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN notifications are enabled and addresses available WHEN invoke THEN return enriched response`() =
|
||||
runTest {
|
||||
// GIVEN
|
||||
val userWalletId = UserWalletId("1234567890abcdef")
|
||||
val token = createToken()
|
||||
val response = createUserTokensResponse(tokens = listOf(token))
|
||||
val addresses = listOf("0x123", "0x456")
|
||||
|
||||
every { notificationsFeatureToggles.isNotificationsEnabled } returns true
|
||||
coEvery { walletsRepository.isNotificationsEnabled(userWalletId) } returns true
|
||||
coEvery {
|
||||
multiNetworkStatusSupplier.invoke(any())
|
||||
} returns flowOf(
|
||||
setOf(
|
||||
NetworkStatus(
|
||||
network = mockk {
|
||||
every { backendId } returns "ethereum"
|
||||
every { derivationPath.value } returns "m/44'/60'/0'/0/0"
|
||||
},
|
||||
value = NetworkStatus.Verified(
|
||||
address = mockk {
|
||||
every { availableAddresses } returns addresses.map { address ->
|
||||
mockk<NetworkAddress.Address> {
|
||||
every { value } returns address
|
||||
}
|
||||
}.toSet()
|
||||
},
|
||||
amounts = emptyMap(),
|
||||
pendingTransactions = emptyMap(),
|
||||
source = StatusSource.ACTUAL,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = enricher(userWalletId, response)
|
||||
|
||||
// THEN
|
||||
assertThat(result.tokens).hasSize(1)
|
||||
assertThat(result.tokens[0].addresses).containsExactlyElementsIn(addresses)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN notifications are enabled but no matching network WHEN invoke THEN return original token`() = runTest {
|
||||
// GIVEN
|
||||
val userWalletId = UserWalletId("1234567890abcdef")
|
||||
val token = createToken()
|
||||
val response = createUserTokensResponse(tokens = listOf(token))
|
||||
|
||||
every { notificationsFeatureToggles.isNotificationsEnabled } returns true
|
||||
coEvery { walletsRepository.isNotificationsEnabled(userWalletId) } returns true
|
||||
coEvery {
|
||||
multiNetworkStatusSupplier.invoke(any())
|
||||
} returns flowOf(
|
||||
setOf(
|
||||
NetworkStatus(
|
||||
network = mockk {
|
||||
every { backendId } returns "bitcoin"
|
||||
every { derivationPath.value } returns "m/44'/0'/0'/0/0"
|
||||
},
|
||||
value = NetworkStatus.Verified(
|
||||
address = mockk {
|
||||
every { availableAddresses } returns emptySet()
|
||||
},
|
||||
amounts = emptyMap(),
|
||||
pendingTransactions = emptyMap(),
|
||||
source = StatusSource.ACTUAL,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = enricher(userWalletId, response)
|
||||
|
||||
// THEN
|
||||
assertThat(result.tokens).hasSize(1)
|
||||
assertThat(result.tokens[0]).isEqualTo(token)
|
||||
}
|
||||
|
||||
private fun createToken(
|
||||
networkId: String = "ethereum",
|
||||
derivationPath: String = "m/44'/60'/0'/0/0",
|
||||
list: List<String> = emptyList(),
|
||||
name: String = "Ethereum",
|
||||
symbol: String = "ETH",
|
||||
decimals: Int = 18,
|
||||
contractAddress: String? = null,
|
||||
id: String? = null,
|
||||
) = UserTokensResponse.Token(
|
||||
id = id,
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
name = name,
|
||||
symbol = symbol,
|
||||
decimals = decimals,
|
||||
contractAddress = contractAddress,
|
||||
addresses = list,
|
||||
)
|
||||
|
||||
private fun createUserTokensResponse(
|
||||
tokens: List<UserTokensResponse.Token> = emptyList(),
|
||||
version: Int = 0,
|
||||
group: UserTokensResponse.GroupType = UserTokensResponse.GroupType.NETWORK,
|
||||
sort: UserTokensResponse.SortType = UserTokensResponse.SortType.BALANCE,
|
||||
notifyStatus: Boolean? = null,
|
||||
) = UserTokensResponse(
|
||||
version = version,
|
||||
group = group,
|
||||
sort = sort,
|
||||
notifyStatus = notifyStatus,
|
||||
tokens = tokens,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
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.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
|
||||
|
||||
class UserTokensSaverTest {
|
||||
|
||||
private val tangemTechApi: TangemTechApi = mockk()
|
||||
private val dataStore: DataStore<Preferences> = mockk(relaxed = true)
|
||||
private val appPreferenceStore = AppPreferencesStore(
|
||||
moshi = Moshi.Builder().build(),
|
||||
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()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN user wallet id and response WHEN store THEN should store 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)
|
||||
|
||||
// WHEN
|
||||
userTokensSaver.store(userWalletId, response)
|
||||
|
||||
// THEN
|
||||
coVerify {
|
||||
dataStore.updateData(any())
|
||||
}
|
||||
coVerify(exactly = 0) {
|
||||
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 THEN should 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 { tangemTechApi.saveUserTokens(any(), any()) } returns ApiResponse.Success(Unit)
|
||||
|
||||
// WHEN
|
||||
userTokensSaver.push(userWalletId, response)
|
||||
|
||||
// THEN
|
||||
coVerify {
|
||||
tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse)
|
||||
}
|
||||
coVerify(exactly = 0) {
|
||||
dataStore.updateData(any())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN user wallet id and response WHEN push AND api call fails THEN should log error`() = 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(),
|
||||
)
|
||||
val error = ApiResponseError.UnknownException(Exception("API Error"))
|
||||
coEvery { userTokensResponseAddressesEnricher(userWalletId, response) } returns enrichedResponse
|
||||
coEvery { tangemTechApi.saveUserTokens(any(), any()) } returns
|
||||
ApiResponse.Error(error) as ApiResponse<Unit>
|
||||
|
||||
// WHEN
|
||||
userTokensSaver.push(userWalletId, response)
|
||||
|
||||
// THEN
|
||||
coVerify {
|
||||
tangemTechApi.saveUserTokens(userWalletId.stringValue, enrichedResponse)
|
||||
}
|
||||
coVerify(exactly = 0) {
|
||||
dataStore.updateData(any())
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue