diff --git a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt index d88224fe30..1172d04238 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt @@ -4,6 +4,7 @@ import com.tangem.data.wallets.hot.TangemHotWalletSigner import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.card.repository.CardSdkConfigRepository +import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.demo.models.DemoConfig import com.tangem.domain.dynamicaddresses.DynamicAddressesFeatureToggles import com.tangem.domain.dynamicaddresses.GetDynamicReceiveAddressUseCase @@ -263,6 +264,7 @@ internal object TransactionDomainModule { getDynamicReceiveAddressUseCase: GetDynamicReceiveAddressUseCase, dynamicAddressesRepository: DynamicAddressesRepository, dynamicAddressesFeatureToggles: DynamicAddressesFeatureToggles, + userWalletsListRepository: UserWalletsListRepository, ): ReceiveAddressesFactory { return ReceiveAddressesFactory( getEnsNameUseCase = getEnsNameUseCase, @@ -270,6 +272,7 @@ internal object TransactionDomainModule { getDynamicReceiveAddressUseCase = getDynamicReceiveAddressUseCase, dynamicAddressesRepository = dynamicAddressesRepository, dynamicAddressesFeatureToggles = dynamicAddressesFeatureToggles, + userWalletsListRepository = userWalletsListRepository, ) } diff --git a/domain/transaction/build.gradle.kts b/domain/transaction/build.gradle.kts index cc13ce06eb..d9aef0228a 100644 --- a/domain/transaction/build.gradle.kts +++ b/domain/transaction/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { implementation(projects.libs.crypto) implementation(projects.domain.account.status) + implementation(projects.domain.common) implementation(projects.domain.dynamicAddresses) implementation(projects.domain.dynamicAddresses.models) implementation(projects.domain.models) diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ReceiveAddressesFactory.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ReceiveAddressesFactory.kt index 93a25ab440..7f19a5a852 100644 --- a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ReceiveAddressesFactory.kt +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ReceiveAddressesFactory.kt @@ -1,5 +1,7 @@ package com.tangem.domain.transaction.usecase +import com.tangem.domain.common.wallets.UserWalletsListRepository +import com.tangem.domain.common.wallets.getSyncOrNull import com.tangem.domain.dynamicaddresses.DynamicAddressesFeatureToggles import com.tangem.domain.dynamicaddresses.GetDynamicReceiveAddressUseCase import com.tangem.domain.dynamicaddresses.model.DynamicAddressesStatus @@ -13,6 +15,7 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.Network import com.tangem.domain.models.network.NetworkAddress import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.tokens.GetViewedTokenReceiveWarningUseCase import com.tangem.domain.transaction.R import com.tangem.lib.crypto.BlockchainUtils @@ -25,6 +28,7 @@ class ReceiveAddressesFactory( private val getDynamicReceiveAddressUseCase: GetDynamicReceiveAddressUseCase, private val dynamicAddressesRepository: DynamicAddressesRepository, private val dynamicAddressesFeatureToggles: DynamicAddressesFeatureToggles, + private val userWalletsListRepository: UserWalletsListRepository, ) { suspend fun create( @@ -67,6 +71,9 @@ class ReceiveAddressesFactory( if (!dynamicAddressesFeatureToggles.isDynamicAddressesEnabled) return null if (cryptoCurrency !is CryptoCurrency.Coin) return null + val userWallet = userWalletsListRepository.getSyncOrNull(userWalletId) + if (userWallet == null || !userWallet.isMultiCurrency) return null + val status = dynamicAddressesRepository.getStatus(userWalletId, cryptoCurrency.network).firstOrNull() if (status != DynamicAddressesStatus.ENABLED) return null diff --git a/domain/transaction/src/test/java/com/tangem/domain/transaction/usecase/ReceiveAddressesFactoryTest.kt b/domain/transaction/src/test/java/com/tangem/domain/transaction/usecase/ReceiveAddressesFactoryTest.kt new file mode 100644 index 0000000000..e5440e7e58 --- /dev/null +++ b/domain/transaction/src/test/java/com/tangem/domain/transaction/usecase/ReceiveAddressesFactoryTest.kt @@ -0,0 +1,75 @@ +package com.tangem.domain.transaction.usecase + +import com.google.common.truth.Truth.assertThat +import com.tangem.blockchain.common.Blockchain +import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory +import com.tangem.common.test.domain.wallet.MockUserWalletFactory +import com.tangem.domain.common.wallets.UserWalletsListRepository +import com.tangem.domain.dynamicaddresses.DynamicAddressesFeatureToggles +import com.tangem.domain.dynamicaddresses.GetDynamicReceiveAddressUseCase +import com.tangem.domain.dynamicaddresses.repository.DynamicAddressesRepository +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.network.NetworkAddress +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.tokens.GetViewedTokenReceiveWarningUseCase +import io.mockk.coEvery +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.test.runTest +import org.junit.Test +import kotlin.time.Duration.Companion.seconds + +internal class ReceiveAddressesFactoryTest { + + private val getEnsNameUseCase: GetEnsNameUseCase = mockk() + private val getViewedTokenReceiveWarningUseCase: GetViewedTokenReceiveWarningUseCase = mockk() + private val getDynamicReceiveAddressUseCase: GetDynamicReceiveAddressUseCase = mockk() + private val dynamicAddressesRepository: DynamicAddressesRepository = mockk() + private val dynamicAddressesFeatureToggles: DynamicAddressesFeatureToggles = mockk() + private val userWalletsListRepository: UserWalletsListRepository = mockk() + + private val factory = ReceiveAddressesFactory( + getEnsNameUseCase = getEnsNameUseCase, + getViewedTokenReceiveWarningUseCase = getViewedTokenReceiveWarningUseCase, + getDynamicReceiveAddressUseCase = getDynamicReceiveAddressUseCase, + dynamicAddressesRepository = dynamicAddressesRepository, + dynamicAddressesFeatureToggles = dynamicAddressesFeatureToggles, + userWalletsListRepository = userWalletsListRepository, + ) + + @Test + fun `GIVEN single-currency wallet WHEN create THEN standard addresses returned without status check`() = runTest( + timeout = 3.seconds, + ) { + // GIVEN + val userWallet = MockUserWalletFactory.createSingleWalletWithToken() // isMultiCurrency = false + val coin = MockCryptoCurrencyFactory().createCoin(Blockchain.Ethereum) + val status = mockk { + every { currency } returns coin + every { value.networkAddress } returns NetworkAddress.Single( + defaultAddress = NetworkAddress.Address(value = ADDRESS, type = NetworkAddress.Address.Type.Primary), + ) + } + + every { dynamicAddressesFeatureToggles.isDynamicAddressesEnabled } returns true + every { userWalletsListRepository.userWallets } returns MutableStateFlow?>(listOf(userWallet)) + // Single-currency wallets never populate the accounts store, so the status flow never emits ([REDACTED_TASK_KEY]) + every { dynamicAddressesRepository.getStatus(any(), any()) } returns flow { awaitCancellation() } + coEvery { getEnsNameUseCase.invoke(any(), any(), any()) } returns null + coEvery { getViewedTokenReceiveWarningUseCase() } returns emptySet() + + // WHEN + val config = factory.create(status = status, userWalletId = userWallet.walletId) + + // THEN + assertThat(config).isNotNull() + assertThat(config!!.receiveAddress.map { it.value }).containsExactly(ADDRESS) + } + + private companion object { + const val ADDRESS = "0x1234" + } +} \ No newline at end of file