Updated on 2026-08-14

This commit is contained in:
Tangem 2026-06-11 20:35:30 +05:00
parent 314a4b0f37
commit 86e5f8c8e6
4 changed files with 86 additions and 0 deletions

View file

@ -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,
)
}

View file

@ -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)

View file

@ -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

View file

@ -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<CryptoCurrencyStatus> {
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<List<UserWallet>?>(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"
}
}