Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-19 11:10:14 +04:00
parent 7b5b4753a7
commit 4e4e360ae1
5 changed files with 39 additions and 41 deletions

View file

@ -1,12 +1,14 @@
package com.tangem.data.transaction
import android.net.Uri
import androidx.core.text.isDigitsOnly
import com.tangem.blockchain.blockchains.near.NearWalletManager
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.NameResolver
import com.tangem.blockchain.common.ResolveAddressResult
import com.tangem.blockchain.common.ReverseResolveAddressResult
import com.tangem.blockchain.common.TransactionValidator
import com.tangem.blockchain.common.memo.MemoState
import com.tangem.blockchain.extensions.Result
import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWalletId
@ -16,7 +18,6 @@ import com.tangem.domain.wallets.models.ParsedQrCode
import com.tangem.domain.wallets.models.errors.ParsedQrCodeErrors
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
import java.math.BigInteger
class DefaultWalletAddressServiceRepository(
private val walletManagersFacade: WalletManagersFacade,
@ -95,17 +96,26 @@ class DefaultWalletAddressServiceRepository(
}
}
override fun validateMemo(network: Network, memo: String): Boolean {
if (memo.isEmpty()) return true
return when (network.rawId) {
Blockchain.XRP.id -> {
val tag = memo.toLongOrNull()
tag != null && tag <= XRP_TAG_MAX_NUMBER
override suspend fun validateMemo(userWalletId: UserWalletId, network: Network, memo: String): Boolean =
withContext(dispatchers.io) {
val walletManager = walletManagersFacade.getOrCreateWalletManager(
userWalletId = userWalletId,
network = network,
) ?: return@withContext true
val memoStateResult = (walletManager as? TransactionValidator)?.validateMemo(memo)
if (memoStateResult != null) {
when (memoStateResult) {
is Result.Success -> when (memoStateResult.data) {
MemoState.NotSupported,
MemoState.Valid,
-> true
MemoState.Invalid -> false
}
Blockchain.Stellar.id -> {
isAssignableXlmValue(memo)
is Result.Failure -> true
}
else -> true
} else {
true
}
}
@ -145,26 +155,4 @@ class DefaultWalletAddressServiceRepository(
private fun Blockchain.isNear(): Boolean {
return this == Blockchain.Near || this == Blockchain.NearTestnet
}
private fun isAssignableXlmValue(value: String): Boolean {
return when {
value.isNotEmpty() && value.isDigitsOnly() -> {
try {
// from com.tangem.blockchain.blockchains.stellar.StellarMemo.toStellarSdkMemo
value.toBigInteger() in BigInteger.ZERO..Long.MAX_VALUE.toBigInteger() * 2.toBigInteger()
} catch (ex: NumberFormatException) {
false
}
}
else -> {
// from org.stellar.sdk.MemoText
value.toByteArray().size <= XLM_MEMO_MAX_LENGTH
}
}
}
companion object {
private const val XLM_MEMO_MAX_LENGTH = 28
private const val XRP_TAG_MAX_NUMBER = 4294967295
}
}

View file

@ -23,7 +23,7 @@ interface WalletAddressServiceRepository {
suspend fun validateAddress(userWalletId: UserWalletId, network: Network, address: String): Boolean
fun validateMemo(network: Network, memo: String): Boolean
suspend fun validateMemo(userWalletId: UserWalletId, network: Network, memo: String): Boolean
suspend fun parseSharedAddress(input: String, network: Network): ParsedQrCode
}

View file

@ -3,7 +3,8 @@ package com.tangem.domain.transaction.usecase
import arrow.core.Either
import arrow.core.left
import arrow.core.right
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.transaction.WalletAddressServiceRepository
import com.tangem.domain.transaction.error.ValidateMemoError
@ -14,9 +15,17 @@ class ValidateWalletMemoUseCase(
private val walletAddressServiceRepository: WalletAddressServiceRepository,
) {
operator fun invoke(network: Network, memo: String): Either<ValidateMemoError, Unit> {
suspend operator fun invoke(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
memo: String,
): Either<ValidateMemoError, Unit> {
return try {
val isValidMemo = walletAddressServiceRepository.validateMemo(network, memo)
val isValidMemo = walletAddressServiceRepository.validateMemo(
userWalletId = userWalletId,
network = cryptoCurrency.network,
memo = memo,
)
if (isValidMemo) {
Unit.right()
} else {

View file

@ -323,8 +323,9 @@ internal class SendDestinationModel @Inject constructor(
senderAddresses = senderAddresses.value,
)
val memoValidationResult = validateWalletMemoUseCase(
userWalletId = userWalletId,
cryptoCurrency = cryptoCurrency,
memo = memo.orEmpty(),
network = cryptoCurrency.network,
)
if (type != null) {

View file

@ -5,7 +5,7 @@
# https://github.com/tangem/tangem-sdk-android/
# https://github.com/tangem/vico
tangemBlockchainSdk = "releases-5.34-1428"
tangemBlockchainSdk = "releases-5.34-1430"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "releases-5.34-579"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^