Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-24 11:23:21 +03:00
parent 4aa74c4b70
commit 3d16de3f4f
6 changed files with 221 additions and 10 deletions

View file

@ -6,27 +6,32 @@ import arrow.core.left
import arrow.core.raise.catch
import arrow.core.raise.either
import arrow.core.raise.ensure
import arrow.core.toOption
import com.tangem.data.staking.store.YieldsBalancesStore
import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory
import com.tangem.datasource.api.stakekit.models.request.YieldBalanceRequestBody
import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO
import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.core.flow.FlowFetcher
import com.tangem.domain.core.utils.catchOn
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.model.StakingID
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import timber.log.Timber
internal fun <Params : YieldBalanceFetcherParams> commonFetcher(
implementor: YieldBalanceFetcherImplementor<Params>,
userWalletsStore: UserWalletsStore,
stakingYieldsStore: StakingYieldsStore,
yieldsBalancesStore: YieldsBalancesStore,
dispatchers: CoroutineDispatcherProvider,
): FlowFetcher<Params> {
return CommonYieldBalanceFetcher(
implementor = implementor,
userWalletsStore = userWalletsStore,
stakingYieldsStore = stakingYieldsStore,
yieldsBalancesStore = yieldsBalancesStore,
dispatchers = dispatchers,
@ -36,19 +41,25 @@ internal fun <Params : YieldBalanceFetcherParams> commonFetcher(
/**
* Common implementation of YieldBalanceFetcher
*
* @param implementor fetcher implementor
* @property implementor fetcher implementor
* @property userWalletsStore user wallets store
* @property stakingYieldsStore staking yields store
* @property yieldsBalancesStore yields balances store
* @property dispatchers dispatchers
*/
private class CommonYieldBalanceFetcher<Params : YieldBalanceFetcherParams>(
private val implementor: YieldBalanceFetcherImplementor<Params>,
private val userWalletsStore: UserWalletsStore,
private val stakingYieldsStore: StakingYieldsStore,
private val yieldsBalancesStore: YieldsBalancesStore,
private val dispatchers: CoroutineDispatcherProvider,
) : FlowFetcher<Params> {
override suspend fun invoke(params: Params): Either<Throwable, Unit> {
checkIsSupportedByWalletOrElse(userWalletId = params.userWalletId) {
return it.left()
}
val stakingIds = getStakingIds(params).getOrElse {
return it.left()
}
@ -58,7 +69,23 @@ private class CommonYieldBalanceFetcher<Params : YieldBalanceFetcherParams>(
implementor.fetch(params = params, stakingIds = stakingIds, requests)
}
.onLeft { yieldsBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = stakingIds) }
.onLeft {
Timber.e(it, "Unable to fetch yield balances $params")
yieldsBalancesStore.storeError(userWalletId = params.userWalletId, stakingIds = stakingIds)
}
}
private inline fun checkIsSupportedByWalletOrElse(userWalletId: UserWalletId, ifNotSupported: (Throwable) -> Unit) {
val maybeUserWallet = userWalletsStore.getSyncOrNull(key = userWalletId).toOption()
val isSupportedByWallet = maybeUserWallet.isSome(UserWallet::isMultiCurrency)
if (!isSupportedByWallet) {
val exception = IllegalStateException("Wallet $userWalletId is not supported: $maybeUserWallet")
Timber.e(exception)
ifNotSupported(exception)
}
}
private suspend fun getStakingIds(params: Params): Either<Throwable, Set<StakingID>> = either {

View file

@ -6,6 +6,7 @@ import com.tangem.data.staking.store.YieldsBalancesStore
import com.tangem.data.staking.utils.StakingIdFactory
import com.tangem.datasource.api.stakekit.StakeKitApi
import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.core.flow.FlowFetcher
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
@ -15,6 +16,7 @@ import javax.inject.Inject
/**
* Default implementation of [MultiYieldBalanceFetcher]
*
* @property userWalletsStore user wallets store
* @property stakingYieldsStore staking yields store
* @property yieldsBalancesStore yields balances store
* @property stakingIdFactory factory for creating StakingID
@ -24,6 +26,7 @@ import javax.inject.Inject
[REDACTED_AUTHOR]
*/
internal class DefaultMultiYieldBalanceFetcher @Inject constructor(
private val userWalletsStore: UserWalletsStore,
private val stakingYieldsStore: StakingYieldsStore,
private val yieldsBalancesStore: YieldsBalancesStore,
private val stakingIdFactory: StakingIdFactory,
@ -32,6 +35,7 @@ internal class DefaultMultiYieldBalanceFetcher @Inject constructor(
) : MultiYieldBalanceFetcher,
FlowFetcher<YieldBalanceFetcherParams.Multi> by commonFetcher(
implementor = createMultiFetcherImplementor(yieldsBalancesStore, stakingIdFactory, stakeKitApi, dispatchers),
userWalletsStore = userWalletsStore,
stakingYieldsStore = stakingYieldsStore,
yieldsBalancesStore = yieldsBalancesStore,
dispatchers = dispatchers,

View file

@ -6,6 +6,7 @@ import com.tangem.data.staking.store.YieldsBalancesStore
import com.tangem.data.staking.utils.StakingIdFactory
import com.tangem.datasource.api.stakekit.StakeKitApi
import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.core.flow.FlowFetcher
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
@ -16,6 +17,7 @@ import javax.inject.Inject
/**
* Default implementation of [MultiYieldBalanceFetcher]
*
* @property userWalletsStore user wallets store
* @property stakingYieldsStore staking yields store
* @property yieldsBalancesStore yields balances store
* @property stakingIdFactory factory for creating StakingID
@ -25,6 +27,7 @@ import javax.inject.Inject
[REDACTED_AUTHOR]
*/
internal class DefaultSingleYieldBalanceFetcher @Inject constructor(
private val userWalletsStore: UserWalletsStore,
private val stakingYieldsStore: StakingYieldsStore,
private val yieldsBalancesStore: YieldsBalancesStore,
private val stakingIdFactory: StakingIdFactory,
@ -33,6 +36,7 @@ internal class DefaultSingleYieldBalanceFetcher @Inject constructor(
) : SingleYieldBalanceFetcher,
FlowFetcher<YieldBalanceFetcherParams.Single> by commonFetcher(
implementor = createSingleFetcherImplementor(yieldsBalancesStore, stakingIdFactory, stakeKitApi, dispatchers),
userWalletsStore = userWalletsStore,
stakingYieldsStore = stakingYieldsStore,
yieldsBalancesStore = yieldsBalancesStore,
dispatchers = dispatchers,

View file

@ -1,10 +1,12 @@
package com.tangem.data.staking.multi
import arrow.core.toOption
import com.google.common.truth.Truth
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory
import com.tangem.common.test.data.staking.MockYieldDTOFactory
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
import com.tangem.common.test.domain.wallet.MockUserWalletFactory
import com.tangem.data.staking.store.YieldsBalancesStore
import com.tangem.data.staking.utils.StakingIdFactory
import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory
@ -13,6 +15,7 @@ import com.tangem.datasource.api.common.response.ApiResponseError
import com.tangem.datasource.api.stakekit.StakeKitApi
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.model.StakingID
import com.tangem.domain.wallets.models.UserWalletId
@ -26,12 +29,14 @@ import org.junit.Test
*/
internal class DefaultMultiYieldBalanceFetcherTest {
private val userWalletsStore: UserWalletsStore = mockk()
private val stakingYieldsStore: StakingYieldsStore = mockk()
private val yieldsBalancesStore: YieldsBalancesStore = mockk()
private val stakingIdFactory: StakingIdFactory = mockk()
private val stakeKitApi: StakeKitApi = mockk()
private val fetcher = DefaultMultiYieldBalanceFetcher(
userWalletsStore = userWalletsStore,
stakingYieldsStore = stakingYieldsStore,
yieldsBalancesStore = yieldsBalancesStore,
stakingIdFactory = stakingIdFactory,
@ -45,6 +50,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId)
coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId)
coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs
@ -63,6 +69,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.create(params.userWalletId, ton.id, ton.network)
stakingIdFactory.create(params.userWalletId, solana.id, solana.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
@ -76,18 +83,77 @@ internal class DefaultMultiYieldBalanceFetcherTest {
Truth.assertThat(actual.isRight()).isTrue()
}
@Test
fun `fetch yields balances failure if user wallet is not supported`() = runTest {
val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network)
val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap)
val userWallet = MockUserWalletFactory.create().copy(isMultiCurrency = false)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
val actual = fetcher(params)
coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) }
coVerify(inverse = true) {
stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network)
yieldsBalancesStore.refresh(userWalletId = any(), stakingIds = any())
stakingYieldsStore.getSyncWithTimeout()
stakeKitApi.getSingleYieldBalance(integrationId = any(), body = any())
yieldsBalancesStore.storeActual(userWalletId = any(), values = any())
yieldsBalancesStore.storeError(userWalletId = any(), stakingIds = any())
}
val expected = IllegalStateException("Wallet ${params.userWalletId} is not supported: ${userWallet.toOption()}")
Truth.assertThat(actual.isLeft()).isTrue()
Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java)
Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message)
}
@Test
fun `fetch yields balances failure if userWalletsStore returns null`() = runTest {
val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network)
val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns null
val actual = fetcher(params)
coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) }
coVerify(inverse = true) {
stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network)
yieldsBalancesStore.refresh(userWalletId = any(), stakingIds = any())
stakingYieldsStore.getSyncWithTimeout()
stakeKitApi.getSingleYieldBalance(integrationId = any(), body = any())
yieldsBalancesStore.storeActual(userWalletId = any(), values = any())
yieldsBalancesStore.storeError(userWalletId = any(), stakingIds = any())
}
val expected = IllegalStateException("Wallet ${params.userWalletId} is not supported: ${null.toOption()}")
Truth.assertThat(actual.isLeft()).isTrue()
Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java)
Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message)
}
@Test
fun `fetch yields balances failure if stakingIdFactory returns empty list`() = runTest {
val currencyIdWithNetworkMap = mapOf(ton.id to ton.network, solana.id to solana.network)
val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns emptySet()
coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns emptySet()
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.create(params.userWalletId, ton.id, ton.network)
stakingIdFactory.create(params.userWalletId, solana.id, solana.network)
}
@ -113,6 +179,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId)
coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId)
coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs
@ -122,6 +189,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.create(params.userWalletId, ton.id, ton.network)
stakingIdFactory.create(params.userWalletId, solana.id, solana.network)
yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds)
@ -147,6 +215,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId)
coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId)
coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs
@ -156,6 +225,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.create(params.userWalletId, ton.id, ton.network)
stakingIdFactory.create(params.userWalletId, solana.id, solana.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
@ -181,6 +251,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId)
coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId)
coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs
@ -195,6 +266,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.create(params.userWalletId, ton.id, ton.network)
stakingIdFactory.create(params.userWalletId, solana.id, solana.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
@ -226,6 +298,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId)
coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId)
coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs
@ -237,6 +310,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.create(params.userWalletId, ton.id, ton.network)
stakingIdFactory.create(params.userWalletId, solana.id, solana.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
@ -268,6 +342,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val params = YieldBalanceFetcherParams.Multi(userWalletId, currencyIdWithNetworkMap)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.create(params.userWalletId, ton.id, ton.network) } returns setOf(tonId)
coEvery { stakingIdFactory.create(params.userWalletId, solana.id, solana.network) } returns setOf(solanaId)
coEvery { yieldsBalancesStore.refresh(params.userWalletId, tonAndSolanaIds) } just Runs
@ -287,6 +362,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.create(params.userWalletId, ton.id, ton.network)
stakingIdFactory.create(params.userWalletId, solana.id, solana.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = tonAndSolanaIds)
@ -306,6 +382,7 @@ internal class DefaultMultiYieldBalanceFetcherTest {
private companion object {
val userWalletId = UserWalletId("011")
val userWallet = MockUserWalletFactory.create()
val mocks = MockCryptoCurrencyFactory()

View file

@ -1,10 +1,12 @@
package com.tangem.data.staking.single
import arrow.core.toOption
import com.google.common.truth.Truth
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.test.data.staking.MockYieldBalanceWrapperDTOFactory
import com.tangem.common.test.data.staking.MockYieldDTOFactory
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
import com.tangem.common.test.domain.wallet.MockUserWalletFactory
import com.tangem.data.staking.store.YieldsBalancesStore
import com.tangem.data.staking.utils.StakingIdFactory
import com.tangem.data.staking.utils.YieldBalanceRequestBodyFactory
@ -17,6 +19,7 @@ import com.tangem.datasource.api.stakekit.models.response.model.NetworkTypeDTO
import com.tangem.datasource.api.stakekit.models.response.model.TokenDTO
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.model.StakingID
import com.tangem.domain.wallets.models.UserWalletId
@ -31,12 +34,14 @@ import java.math.BigDecimal
*/
internal class DefaultSingleYieldBalanceFetcherTest {
private val userWalletsStore: UserWalletsStore = mockk()
private val stakingYieldsStore: StakingYieldsStore = mockk()
private val yieldsBalancesStore: YieldsBalancesStore = mockk()
private val stakingIdFactory: StakingIdFactory = mockk()
private val stakeKitApi: StakeKitApi = mockk()
private val fetcher = DefaultSingleYieldBalanceFetcher(
userWalletsStore = userWalletsStore,
stakingYieldsStore = stakingYieldsStore,
yieldsBalancesStore = yieldsBalancesStore,
stakingIdFactory = stakingIdFactory,
@ -52,6 +57,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
network = ton.network,
)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId
coEvery {
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
@ -70,6 +76,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
stakingYieldsStore.getSyncWithTimeout()
@ -82,6 +89,67 @@ internal class DefaultSingleYieldBalanceFetcherTest {
Truth.assertThat(actual.isRight()).isTrue()
}
@Test
fun `fetch yields balances failure if user wallet is not supported`() = runTest {
val params = YieldBalanceFetcherParams.Single(
userWalletId = userWalletId,
currencyId = ton.id,
network = ton.network,
)
val userWallet = MockUserWalletFactory.create().copy(isMultiCurrency = false)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
val actual = fetcher(params)
coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) }
coVerify(inverse = true) {
stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network)
yieldsBalancesStore.refresh(userWalletId = any(), stakingIds = any())
stakingYieldsStore.getSyncWithTimeout()
stakeKitApi.getSingleYieldBalance(integrationId = any(), body = any())
yieldsBalancesStore.storeActual(userWalletId = any(), values = any())
yieldsBalancesStore.storeError(userWalletId = any(), stakingIds = any())
}
val expected = IllegalStateException("Wallet ${params.userWalletId} is not supported: ${userWallet.toOption()}")
Truth.assertThat(actual.isLeft()).isTrue()
Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java)
Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message)
}
@Test
fun `fetch yields balances failure if userWalletsStore returns null`() = runTest {
val params = YieldBalanceFetcherParams.Single(
userWalletId = userWalletId,
currencyId = ton.id,
network = ton.network,
)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns null
val actual = fetcher(params)
coVerify { userWalletsStore.getSyncOrNull(params.userWalletId) }
coVerify(inverse = true) {
stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network)
yieldsBalancesStore.refresh(userWalletId = any(), stakingIds = any())
stakingYieldsStore.getSyncWithTimeout()
stakeKitApi.getSingleYieldBalance(integrationId = any(), body = any())
yieldsBalancesStore.storeActual(userWalletId = any(), values = any())
yieldsBalancesStore.storeError(userWalletId = any(), stakingIds = any())
}
val expected = IllegalStateException("Wallet ${params.userWalletId} is not supported: ${null.toOption()}")
Truth.assertThat(actual.isLeft()).isTrue()
Truth.assertThat(actual.leftOrNull()).isInstanceOf(expected::class.java)
Truth.assertThat(actual.leftOrNull()).hasMessageThat().isEqualTo(expected.message)
}
@Test
fun `fetch yields balances failure if stakingIdFactory createForDefault returns null`() = runTest {
val params = YieldBalanceFetcherParams.Single(
@ -90,11 +158,13 @@ internal class DefaultSingleYieldBalanceFetcherTest {
network = ton.network,
)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns null
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.createForDefault(userWalletId = userWalletId, currencyId = ton.id, network = ton.network)
}
@ -121,6 +191,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
network = ton.network,
)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId
coEvery {
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
@ -132,6 +203,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
stakingYieldsStore.getSyncWithTimeout()
@ -158,6 +230,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
network = ton.network,
)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId
coEvery {
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
@ -169,6 +242,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
stakingYieldsStore.getSyncWithTimeout()
@ -195,6 +269,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
network = ton.network,
)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId
coEvery {
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
@ -207,6 +282,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
stakingYieldsStore.getSyncWithTimeout()
@ -239,6 +315,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
network = ton.network,
)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId
coEvery {
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
@ -251,6 +328,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
stakingYieldsStore.getSyncWithTimeout()
@ -283,6 +361,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
network = ton.network,
)
coEvery { userWalletsStore.getSyncOrNull(params.userWalletId) } returns userWallet
coEvery { stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network) } returns tonId
coEvery {
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
@ -302,6 +381,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
val actual = fetcher(params)
coVerify {
userWalletsStore.getSyncOrNull(params.userWalletId)
stakingIdFactory.createForDefault(params.userWalletId, ton.id, ton.network)
yieldsBalancesStore.refresh(userWalletId = params.userWalletId, stakingIds = setOf(tonId))
stakingYieldsStore.getSyncWithTimeout()
@ -353,6 +433,7 @@ internal class DefaultSingleYieldBalanceFetcherTest {
private companion object {
val userWalletId = UserWalletId("011")
val userWallet = MockUserWalletFactory.create()
val mocks = MockCryptoCurrencyFactory()

View file

@ -91,6 +91,7 @@ abstract class BaseCurrencyStatusOperations(
userWalletId: UserWalletId,
currency: CryptoCurrency,
includeQuotes: Boolean = true,
subscribeOnYieldBalance: Boolean = true,
): Flow<Either<Error, CryptoCurrencyStatus>> {
val rawCurrencyId = currency.id.rawCurrencyId
@ -117,13 +118,24 @@ abstract class BaseCurrencyStatusOperations(
val yieldBalanceFlow = getYieldBalance(userWalletId = userWalletId, cryptoCurrency = currency)
return combine(quoteFlow, statusFlow, yieldBalanceFlow) { maybeQuote, maybeNetworkStatus, maybeYieldBalance ->
currencyStatusProxyCreator.createCurrencyStatus(
currency = currency,
maybeQuote = maybeQuote,
maybeNetworkStatus = maybeNetworkStatus,
maybeYieldBalance = maybeYieldBalance,
)
return if (subscribeOnYieldBalance) {
combine(quoteFlow, statusFlow, yieldBalanceFlow) { maybeQuote, maybeNetworkStatus, maybeYieldBalance ->
currencyStatusProxyCreator.createCurrencyStatus(
currency = currency,
maybeQuote = maybeQuote,
maybeNetworkStatus = maybeNetworkStatus,
maybeYieldBalance = maybeYieldBalance,
)
}
} else {
combine(quoteFlow, statusFlow) { maybeQuote, maybeNetworkStatus ->
currencyStatusProxyCreator.createCurrencyStatus(
currency = currency,
maybeQuote = maybeQuote,
maybeNetworkStatus = maybeNetworkStatus,
maybeYieldBalance = null,
)
}
}
}
@ -242,7 +254,13 @@ abstract class BaseCurrencyStatusOperations(
recover = { return flowOf(it.left()) },
)
return getCurrencyStatusFlow(userWalletId, currency, includeQuotes)
return getCurrencyStatusFlow(
userWalletId = userWalletId,
currency = currency,
includeQuotes = includeQuotes,
// If toggle is off, then subscribe on yield balance. If toggle is on, then don't
subscribeOnYieldBalance = !tokensFeatureToggles.isStakingLoadingRefactoringEnabled,
)
}
suspend fun getCurrenciesStatusesSync(userWalletId: UserWalletId): Either<Error, List<CryptoCurrencyStatus>> {