Updated on 2026-08-14
This commit is contained in:
parent
fa6b5817bf
commit
cd572639c7
9 changed files with 386 additions and 1 deletions
|
|
@ -8,6 +8,10 @@ android {
|
|||
namespace = "com.tangem.domain.tokens"
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
/** Project - Domain */
|
||||
|
|
@ -49,9 +53,12 @@ dependencies {
|
|||
implementation(deps.reKotlin)
|
||||
|
||||
/** Tests */
|
||||
testImplementation(deps.test.junit)
|
||||
testImplementation(deps.test.coroutine)
|
||||
testImplementation(deps.test.junit5)
|
||||
testRuntimeOnly(deps.test.junit5.engine)
|
||||
testImplementation(deps.test.mockk)
|
||||
testImplementation(deps.test.truth)
|
||||
testImplementation(projects.common.test)
|
||||
testImplementation(tangemDeps.blockchain) {
|
||||
exclude(module = "joda-time")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.domain.tokens.wallet
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
/**
|
||||
* Base contract for implementation of wallet's balance fetcher
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal interface BaseWalletBalanceFetcher {
|
||||
|
||||
/** Fetching sources */
|
||||
val fetchingSources: Set<FetchingSource>
|
||||
|
||||
/** Get crypto currencies of wallet with [userWalletId] */
|
||||
suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set<CryptoCurrency>
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.domain.tokens.wallet
|
||||
|
||||
/**
|
||||
* Source type that is necessary to load cryptocurrency data
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal enum class FetchingSource {
|
||||
NETWORK,
|
||||
QUOTE,
|
||||
STAKING,
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.tangem.domain.tokens.wallet.implementor
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
|
||||
import com.tangem.domain.tokens.wallet.BaseWalletBalanceFetcher
|
||||
import com.tangem.domain.tokens.wallet.FetchingSource
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Implementation of [BaseWalletBalanceFetcher] for MULTI-CURRENCY wallet
|
||||
*
|
||||
* @property multiWalletCryptoCurrenciesFetcher multi wallet fetcher of crypto currencies
|
||||
* @property multiWalletCryptoCurrenciesSupplier multi wallet supplier of crypto currencies
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class MultiWalletBalanceFetcher(
|
||||
private val multiWalletCryptoCurrenciesFetcher: MultiWalletCryptoCurrenciesFetcher,
|
||||
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
) : BaseWalletBalanceFetcher {
|
||||
|
||||
override val fetchingSources: Set<FetchingSource> = setOf(
|
||||
FetchingSource.NETWORK,
|
||||
FetchingSource.QUOTE,
|
||||
FetchingSource.STAKING,
|
||||
)
|
||||
|
||||
override suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set<CryptoCurrency> {
|
||||
multiWalletCryptoCurrenciesFetcher(
|
||||
params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId),
|
||||
)
|
||||
.onLeft(Timber::e)
|
||||
|
||||
return multiWalletCryptoCurrenciesSupplier(
|
||||
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId),
|
||||
)
|
||||
.firstOrNull()
|
||||
.orEmpty()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.tangem.domain.tokens.wallet.implementor
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.wallet.BaseWalletBalanceFetcher
|
||||
import com.tangem.domain.tokens.wallet.FetchingSource
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
/**
|
||||
* Implementation of [BaseWalletBalanceFetcher] for SINGLE-CURRENCY wallet
|
||||
*
|
||||
* @property currenciesRepository currencies repository
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class SingleWalletBalanceFetcher(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
) : BaseWalletBalanceFetcher {
|
||||
|
||||
override val fetchingSources: Set<FetchingSource> = setOf(
|
||||
FetchingSource.NETWORK,
|
||||
FetchingSource.QUOTE,
|
||||
)
|
||||
|
||||
override suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set<CryptoCurrency> {
|
||||
val primaryCurrency = currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(
|
||||
userWalletId = userWalletId,
|
||||
refresh = true,
|
||||
)
|
||||
|
||||
return setOf(primaryCurrency)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.domain.tokens.wallet.implementor
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.wallet.BaseWalletBalanceFetcher
|
||||
import com.tangem.domain.tokens.wallet.FetchingSource
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
/**
|
||||
* Implementation of [BaseWalletBalanceFetcher] for SINGLE-CURRENCY wallet WITH TOKEN (like, NODL)
|
||||
*
|
||||
* @property currenciesRepository currencies repository
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class SingleWalletWithTokenBalanceFetcher(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
) : BaseWalletBalanceFetcher {
|
||||
|
||||
override val fetchingSources: Set<FetchingSource> = setOf(
|
||||
FetchingSource.NETWORK,
|
||||
FetchingSource.QUOTE,
|
||||
)
|
||||
|
||||
override suspend fun getCryptoCurrencies(userWalletId: UserWalletId): Set<CryptoCurrency> {
|
||||
return currenciesRepository.getSingleCurrencyWalletWithCardCurrencies(
|
||||
userWalletId = userWalletId,
|
||||
refresh = true,
|
||||
).toSet()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package com.tangem.domain.tokens.wallet.implementor
|
||||
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesFetcher
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
|
||||
import com.tangem.domain.tokens.wallet.FetchingSource
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class MultiWalletBalanceFetcherTest {
|
||||
|
||||
private val cryptoCurrencyFactory = MockCryptoCurrencyFactory()
|
||||
|
||||
private val multiWalletFetcher: MultiWalletCryptoCurrenciesFetcher = mockk()
|
||||
private val multiWalletSupplier: MultiWalletCryptoCurrenciesSupplier = mockk()
|
||||
private val fetcher = MultiWalletBalanceFetcher(
|
||||
multiWalletCryptoCurrenciesFetcher = multiWalletFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletSupplier,
|
||||
)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(multiWalletFetcher)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getFetchingSources() {
|
||||
// Act
|
||||
val actual = fetcher.fetchingSources
|
||||
|
||||
// Assert
|
||||
val expected = setOf(FetchingSource.NETWORK, FetchingSource.QUOTE, FetchingSource.STAKING)
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCryptoCurrencies successfully if multiWalletCryptoCurrenciesFetcher RETURNS SUCCESS`() = runTest {
|
||||
// Arrange
|
||||
val currencies: Set<CryptoCurrency> = cryptoCurrencyFactory.ethereumAndStellar.toSet()
|
||||
val supplierFlow = flowOf(currencies)
|
||||
|
||||
coEvery {
|
||||
multiWalletFetcher(params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId))
|
||||
} returns Unit.right()
|
||||
|
||||
every {
|
||||
multiWalletSupplier(params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId))
|
||||
} returns supplierFlow
|
||||
|
||||
// Act
|
||||
val actual = fetcher.getCryptoCurrencies(userWalletId = userWalletId)
|
||||
|
||||
// Assert
|
||||
val expected = currencies.toSet()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCryptoCurrencies successfully if multiWalletCryptoCurrenciesFetcher RETURNS ERROR`() = runTest {
|
||||
// Arrange
|
||||
val currencies: Set<CryptoCurrency> = cryptoCurrencyFactory.ethereumAndStellar.toSet()
|
||||
val supplierFlow = flowOf(currencies)
|
||||
|
||||
coEvery {
|
||||
multiWalletFetcher(params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId))
|
||||
} returns IllegalStateException().left()
|
||||
|
||||
every {
|
||||
multiWalletSupplier(params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId))
|
||||
} returns supplierFlow
|
||||
|
||||
// Act
|
||||
val actual = fetcher.getCryptoCurrencies(userWalletId = userWalletId)
|
||||
|
||||
// Assert
|
||||
val expected = currencies.toSet()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCryptoCurrencies successfully if multiWalletCryptoCurrenciesSupplier IS EMPTY FLOW`() = runTest {
|
||||
// Arrange
|
||||
val supplierFlow = emptyFlow<Set<CryptoCurrency>>()
|
||||
|
||||
coEvery {
|
||||
multiWalletFetcher(params = MultiWalletCryptoCurrenciesFetcher.Params(userWalletId = userWalletId))
|
||||
} returns Unit.right()
|
||||
|
||||
every {
|
||||
multiWalletSupplier(params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId = userWalletId))
|
||||
} returns supplierFlow
|
||||
|
||||
// Act
|
||||
val actual = fetcher.getCryptoCurrencies(userWalletId = userWalletId)
|
||||
|
||||
// Assert
|
||||
val expected = emptySet<CryptoCurrency>()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val userWalletId = UserWalletId("011")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package com.tangem.domain.tokens.wallet.implementor
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.wallet.FetchingSource
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class SingleWalletBalanceFetcherTest {
|
||||
|
||||
private val cryptoCurrencyFactory = MockCryptoCurrencyFactory()
|
||||
|
||||
private val currenciesRepository: CurrenciesRepository = mockk()
|
||||
private val fetcher = SingleWalletBalanceFetcher(currenciesRepository = currenciesRepository)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(currenciesRepository)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getFetchingSources() {
|
||||
// Act
|
||||
val actual = fetcher.fetchingSources
|
||||
|
||||
// Assert
|
||||
val expected = setOf(FetchingSource.NETWORK, FetchingSource.QUOTE)
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCryptoCurrencies() = runTest {
|
||||
// Arrange
|
||||
val userWalletId = UserWalletId("011")
|
||||
val currency = cryptoCurrencyFactory.ethereum
|
||||
|
||||
coEvery {
|
||||
currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(userWalletId = userWalletId, refresh = true)
|
||||
} returns currency
|
||||
|
||||
// Act
|
||||
val actual = fetcher.getCryptoCurrencies(userWalletId = userWalletId)
|
||||
|
||||
// Assert
|
||||
val expected = setOf(currency)
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package com.tangem.domain.tokens.wallet.implementor
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.wallet.FetchingSource
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class SingleWalletWithTokenBalanceFetcherTest {
|
||||
|
||||
private val cryptoCurrencyFactory = MockCryptoCurrencyFactory()
|
||||
|
||||
private val currenciesRepository: CurrenciesRepository = mockk()
|
||||
private val fetcher = SingleWalletWithTokenBalanceFetcher(currenciesRepository = currenciesRepository)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(currenciesRepository)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getFetchingSources() {
|
||||
// Act
|
||||
val actual = fetcher.fetchingSources
|
||||
|
||||
// Assert
|
||||
val expected = setOf(FetchingSource.NETWORK, FetchingSource.QUOTE)
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCryptoCurrencies() = runTest {
|
||||
// Arrange
|
||||
val userWalletId = UserWalletId("011")
|
||||
val currencies = cryptoCurrencyFactory.ethereumAndStellar
|
||||
|
||||
coEvery {
|
||||
currenciesRepository.getSingleCurrencyWalletWithCardCurrencies(userWalletId = userWalletId, refresh = true)
|
||||
} returns currencies
|
||||
|
||||
// Act
|
||||
val actual = fetcher.getCryptoCurrencies(userWalletId = userWalletId)
|
||||
|
||||
// Assert
|
||||
val expected = currencies.toSet()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue