Updated on 2026-08-14
This commit is contained in:
parent
31a8ee5dd4
commit
20695971eb
6 changed files with 2 additions and 136 deletions
|
|
@ -11,13 +11,10 @@ import com.tangem.domain.addressbook.usecase.DeleteContactUseCase
|
|||
import com.tangem.domain.addressbook.usecase.GetContactByIdUseCase
|
||||
import com.tangem.domain.addressbook.usecase.GetContactsUseCase
|
||||
import com.tangem.domain.addressbook.usecase.SyncAddressBooksUseCase
|
||||
import com.tangem.domain.addressbook.usecase.ValidateContactAddressUseCase
|
||||
import com.tangem.domain.addressbook.validation.ContactNameValidator
|
||||
import com.tangem.domain.addressbook.verification.ContactSignatureVerifier
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.tokens.GetNetworkAddressesUseCase
|
||||
import com.tangem.domain.transaction.usecase.SignUseCase
|
||||
import com.tangem.domain.transaction.usecase.ValidateWalletAddressUseCase
|
||||
import com.tangem.domain.transaction.usecase.VerifySecp256k1MessagesUseCase
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -29,18 +26,6 @@ import javax.inject.Singleton
|
|||
@InstallIn(SingletonComponent::class)
|
||||
object AddressBookDomainModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideValidateContactAddressUseCase(
|
||||
validateWalletAddressUseCase: ValidateWalletAddressUseCase,
|
||||
getNetworkAddressesUseCase: GetNetworkAddressesUseCase,
|
||||
): ValidateContactAddressUseCase {
|
||||
return ValidateContactAddressUseCase(
|
||||
validateWalletAddressUseCase = validateWalletAddressUseCase,
|
||||
getNetworkAddressesUseCase = getNetworkAddressesUseCase,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideContactSignatureVerifier(
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
package com.tangem.domain.addressbook.error
|
||||
|
||||
import com.tangem.domain.transaction.error.AddressValidation
|
||||
import com.tangem.domain.transaction.error.SignHashesError
|
||||
|
||||
sealed interface SaveContactError {
|
||||
|
||||
data class Name(val error: ContactNameValidationError) : SaveContactError
|
||||
|
||||
data class Address(val error: AddressValidation.Error) : SaveContactError
|
||||
|
||||
data class Signing(val error: SignHashesError) : SaveContactError
|
||||
|
||||
data class Backend(val error: AddressBookSyncError) : SaveContactError
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
package com.tangem.domain.addressbook.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.GetNetworkAddressesUseCase
|
||||
import com.tangem.domain.transaction.error.AddressValidation
|
||||
import com.tangem.domain.transaction.usecase.ValidateWalletAddressUseCase
|
||||
|
||||
/**
|
||||
* Validates a contact's address for a network, reusing the transaction-layer validation. Self-send
|
||||
* is allowed since saving one's own address in the book is valid.
|
||||
*/
|
||||
class ValidateContactAddressUseCase(
|
||||
private val validateWalletAddressUseCase: ValidateWalletAddressUseCase,
|
||||
private val getNetworkAddressesUseCase: GetNetworkAddressesUseCase,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
address: String,
|
||||
): Either<AddressValidation.Error, Unit> = either {
|
||||
val senderAddresses = getNetworkAddressesUseCase.invokeSync(
|
||||
userWalletId = userWalletId,
|
||||
networkRawId = network.id.rawId,
|
||||
)
|
||||
validateWalletAddressUseCase(
|
||||
userWalletId = userWalletId,
|
||||
network = network,
|
||||
address = address,
|
||||
senderAddresses = senderAddresses,
|
||||
allowSelfSend = true,
|
||||
).bind()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
package com.tangem.domain.addressbook.usecase
|
||||
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.domain.models.network.CryptoCurrencyAddress
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.GetNetworkAddressesUseCase
|
||||
import com.tangem.domain.transaction.error.AddressValidation
|
||||
import com.tangem.domain.transaction.usecase.ValidateWalletAddressUseCase
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
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
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class ValidateContactAddressUseCaseTest {
|
||||
|
||||
private val validateWalletAddressUseCase: ValidateWalletAddressUseCase = mockk()
|
||||
private val getNetworkAddressesUseCase: GetNetworkAddressesUseCase = mockk()
|
||||
private val useCase = ValidateContactAddressUseCase(
|
||||
validateWalletAddressUseCase = validateWalletAddressUseCase,
|
||||
getNetworkAddressesUseCase = getNetworkAddressesUseCase,
|
||||
)
|
||||
|
||||
private val walletId = UserWalletId("011")
|
||||
private val networkRawId = Network.RawID("ethereum")
|
||||
private val networkId = Network.ID(value = "ethereum", derivationPath = Network.DerivationPath.None)
|
||||
private val network: Network = mockk { every { id } returns networkId }
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(validateWalletAddressUseCase, getNetworkAddressesUseCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `valid address forwards sender addresses and allows self-send`() = runTest {
|
||||
val senderAddresses = listOf<CryptoCurrencyAddress>(mockk())
|
||||
coEvery { getNetworkAddressesUseCase.invokeSync(walletId, networkRawId) } returns senderAddresses
|
||||
coEvery {
|
||||
validateWalletAddressUseCase(any(), any(), any(), any<List<CryptoCurrencyAddress>>(), any())
|
||||
} returns AddressValidation.Success.Valid.right()
|
||||
|
||||
val result = useCase(walletId, network, "0xabc")
|
||||
|
||||
assertThat(result.isRight()).isTrue()
|
||||
coVerify {
|
||||
validateWalletAddressUseCase(
|
||||
userWalletId = walletId,
|
||||
network = network,
|
||||
address = "0xabc",
|
||||
senderAddresses = senderAddresses,
|
||||
allowSelfSend = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `invalid address propagates the validation error`() = runTest {
|
||||
coEvery { getNetworkAddressesUseCase.invokeSync(walletId, networkRawId) } returns emptyList()
|
||||
coEvery {
|
||||
validateWalletAddressUseCase(any(), any(), any(), any<List<CryptoCurrencyAddress>>(), any())
|
||||
} returns AddressValidation.Error.InvalidAddress.left()
|
||||
|
||||
val result = useCase(walletId, network, "bad")
|
||||
|
||||
assertThat(result.leftOrNull()).isEqualTo(AddressValidation.Error.InvalidAddress)
|
||||
}
|
||||
}
|
||||
|
|
@ -64,8 +64,7 @@ internal class AddressBookAnalyticsSender @Inject constructor(
|
|||
|
||||
/**
|
||||
* Fired when a save failure is surfaced to the user. [contactId] is set only in edit mode. Validation failures
|
||||
* ([SaveContactError.Name]/[SaveContactError.Address]) are shown inline rather than as a save error, so they do
|
||||
* not produce this event.
|
||||
* ([SaveContactError.Name]) are shown inline rather than as a save error, so they do not produce this event.
|
||||
*/
|
||||
fun sendSaveErrorShown(walletId: UserWalletId, contactId: String?, error: SaveContactError) {
|
||||
val errorType = error.toErrorType() ?: return
|
||||
|
|
@ -85,9 +84,7 @@ internal class AddressBookAnalyticsSender @Inject constructor(
|
|||
AddressBookSyncError.Network -> ErrorType.Network
|
||||
else -> ErrorType.Server
|
||||
}
|
||||
is SaveContactError.Name,
|
||||
is SaveContactError.Address,
|
||||
-> null
|
||||
is SaveContactError.Name -> null
|
||||
}
|
||||
|
||||
fun sendSaveToButtonClicked() {
|
||||
|
|
|
|||
|
|
@ -172,7 +172,6 @@ internal class AddressBookAnalyticsSenderTest {
|
|||
),
|
||||
// Validation failures are shown inline, not as a save error.
|
||||
SaveErrorModel(error = SaveContactError.Name(mockk()), expectedType = null),
|
||||
SaveErrorModel(error = SaveContactError.Address(mockk()), expectedType = null),
|
||||
)
|
||||
|
||||
private companion object {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue