Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-13 12:35:01 +01:00
parent 0b43caf853
commit 2e581a252f
6 changed files with 81 additions and 19 deletions

View file

@ -25,6 +25,10 @@ dependencies {
implementation(projects.core.utils)
// endregion
// region Libs
implementation(projects.libs.crypto)
// endregion
// region Domain
api(projects.domain.common)
api(projects.domain.tokens)

View file

@ -3,6 +3,7 @@ package com.tangem.domain.addressbook.usecase
import com.tangem.domain.addressbook.model.Contact
import com.tangem.domain.addressbook.repository.AddressBookRepository
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.lib.crypto.BlockchainUtils
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
@ -30,7 +31,10 @@ class GetContactsUseCase(
private fun Contact.matches(query: String): Boolean {
val isNameContaining = name.value.contains(other = query, ignoreCase = true)
val isAddressContaining = addresses.any { addressEntry ->
addressEntry.address.contains(other = query, ignoreCase = false)
val isCaseInsensitiveContractAddress = BlockchainUtils.isCaseInsensitiveContractAddress(
networkId = addressEntry.networkId.value,
)
addressEntry.address.contains(other = query, ignoreCase = isCaseInsensitiveContractAddress)
}
val isNetworkContaining = addresses.any { addressEntry ->
addressEntry.networkId.value.contains(other = query, ignoreCase = true)

View file

@ -54,31 +54,44 @@ class GetContactsUseCaseTest {
}
@Test
fun `GIVEN address query matching case WHEN invoke THEN returns matching contact`() = runTest {
// Arrange
val carol = contact(name = "Carol", address = "0xAbCdEf")
every { repository.getAllContacts() } returns flowOf(listOf(alice, carol))
// Act
val result = useCase(query = "0xAbCdEf").first()
// Assert
assertThat(result).containsExactly(carol)
}
@Test
fun `GIVEN address query with different case WHEN invoke THEN returns empty`() = runTest {
// Arrange
val carol = contact(name = "Carol", address = "0xAbCdEf")
fun `GIVEN EVM address query differing only in case WHEN invoke THEN returns matching contact`() = runTest {
// Arrange — EVM (ethereum) addresses are case-insensitive, so a lowercased query matches a checksummed address
val carol = contact(name = "Carol", address = "0xAbCdEf", networkId = "ethereum")
every { repository.getAllContacts() } returns flowOf(listOf(alice, carol))
// Act
val result = useCase(query = "0xabcdef").first()
// Assert
assertThat(result).containsExactly(carol)
}
@Test
fun `GIVEN non-EVM address query differing only in case WHEN invoke THEN returns empty`() = runTest {
// Arrange — non-EVM (solana) addresses are case-sensitive, so a differently-cased query must not match
val dave = contact(name = "Dave", address = "SoLAnaAddr", networkId = "solana")
every { repository.getAllContacts() } returns flowOf(listOf(alice, dave))
// Act
val result = useCase(query = "solanaaddr").first()
// Assert
assertThat(result).isEmpty()
}
@Test
fun `GIVEN non-EVM address query with exact case WHEN invoke THEN returns matching contact`() = runTest {
// Arrange
val dave = contact(name = "Dave", address = "SoLAnaAddr", networkId = "solana")
every { repository.getAllContacts() } returns flowOf(listOf(alice, dave))
// Act
val result = useCase(query = "SoLAnaAddr").first()
// Assert
assertThat(result).containsExactly(dave)
}
@Test
fun `GIVEN query matches a network id WHEN invoke THEN returns only contacts on that network`() = runTest {
// Arrange