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 bf4f00059e..0066c2ae37 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,10 +4,7 @@ import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.demo.DemoConfig import com.tangem.domain.transaction.FeeRepository import com.tangem.domain.transaction.TransactionRepository -import com.tangem.domain.transaction.usecase.CreateTransactionUseCase -import com.tangem.domain.transaction.usecase.GetFeeUseCase -import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase -import com.tangem.domain.transaction.usecase.SendTransactionUseCase +import com.tangem.domain.transaction.usecase.* import com.tangem.domain.walletmanager.WalletManagersFacade import dagger.Module import dagger.Provides @@ -54,4 +51,10 @@ internal object TransactionDomainModule { fun provideIsFeeApproximateUseCase(feeRepository: FeeRepository): IsFeeApproximateUseCase { return IsFeeApproximateUseCase(feeRepository) } + + @Provides + @ViewModelScoped + fun provideValidateTransactionUseCase(transactionRepository: TransactionRepository): ValidateTransactionUseCase { + return ValidateTransactionUseCase(transactionRepository) + } } \ No newline at end of file diff --git a/data/transaction/build.gradle.kts b/data/transaction/build.gradle.kts index 6797014fd2..615758dcf6 100644 --- a/data/transaction/build.gradle.kts +++ b/data/transaction/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { implementation(deps.tangem.blockchain) /** Core */ + implementation(projects.core.datasource) implementation(projects.core.utils) /** Domain */ @@ -28,4 +29,6 @@ dependencies { /** DI */ implementation(deps.hilt.android) kapt(deps.hilt.kapt) + + implementation(deps.timber) } \ No newline at end of file diff --git a/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt b/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt index 934a88f5c9..cad609ee54 100644 --- a/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt +++ b/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt @@ -11,16 +11,19 @@ import com.tangem.blockchain.blockchains.ton.TonTransactionExtras import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder import com.tangem.blockchain.common.* import com.tangem.blockchain.common.transaction.Fee +import com.tangem.datasource.local.walletmanager.WalletManagersStore import com.tangem.domain.tokens.model.Network import com.tangem.domain.transaction.TransactionRepository import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.models.UserWalletId import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.withContext +import timber.log.Timber import java.math.BigDecimal internal class DefaultTransactionRepository( private val walletManagersFacade: WalletManagersFacade, + private val walletManagersStore: WalletManagersStore, private val coroutineDispatcherProvider: CoroutineDispatcherProvider, ) : TransactionRepository { @@ -41,17 +44,53 @@ internal class DefaultTransactionRepository( derivationPath = network.derivationPath.value, ) - val txAmount = if (isSwap) { - createAmountForSwap(amount) - } else { - amount - } - return@withContext walletManager?.createTransaction(txAmount, fee, destination)?.copy( + return@withContext walletManager?.createTransactionInternal( + amount = amount, + fee = fee, + memo = memo, + destination = destination, + network = network, + isSwap = isSwap, hash = hash, - extras = getMemoExtras(network.id.value, memo), ) } + override suspend fun validateTransaction( + amount: Amount, + fee: Fee, + memo: String?, + destination: String, + userWalletId: UserWalletId, + network: Network, + isSwap: Boolean, + hash: String?, + ): Result { + val walletManager = walletManagersStore.getSyncOrNull( + userWalletId = userWalletId, + blockchain = Blockchain.fromId(network.id.value), + derivationPath = network.derivationPath.value, + ) + + val validator = walletManager as? TransactionValidator + + return if (validator != null) { + val transaction = walletManager.createTransactionInternal( + amount = amount, + fee = fee, + memo = memo, + destination = destination, + network = network, + isSwap = isSwap, + hash = hash, + ) + + validator.validate(transaction = transaction) + } else { + Timber.e("${walletManager?.wallet?.blockchain} does not support transaction validation") + Result.success(Unit) + } + } + override suspend fun sendTransaction( txData: TransactionData, signer: CommonSigner, @@ -67,6 +106,28 @@ internal class DefaultTransactionRepository( (walletManager as TransactionSender).send(txData, signer) } + @Suppress("LongParameterList") + private fun WalletManager.createTransactionInternal( + amount: Amount, + fee: Fee, + memo: String?, + destination: String, + network: Network, + isSwap: Boolean, + hash: String?, + ): TransactionData { + val txAmount = if (isSwap) { + createAmountForSwap(amount) + } else { + amount + } + + return createTransaction(txAmount, fee, destination).copy( + hash = hash, + extras = getMemoExtras(network.id.value, memo), + ) + } + private fun getMemoExtras(networkId: String, memo: String?): TransactionExtras? { val blockchain = Blockchain.fromId(networkId) if (memo == null) return null diff --git a/data/transaction/src/main/java/com/tangem/data/transaction/di/TransactionDataModule.kt b/data/transaction/src/main/java/com/tangem/data/transaction/di/TransactionDataModule.kt index c8949d39c0..a6d7043d91 100644 --- a/data/transaction/src/main/java/com/tangem/data/transaction/di/TransactionDataModule.kt +++ b/data/transaction/src/main/java/com/tangem/data/transaction/di/TransactionDataModule.kt @@ -2,6 +2,7 @@ package com.tangem.data.transaction.di import com.tangem.data.transaction.DefaultFeeRepository import com.tangem.data.transaction.DefaultTransactionRepository +import com.tangem.datasource.local.walletmanager.WalletManagersStore import com.tangem.domain.transaction.FeeRepository import com.tangem.domain.transaction.TransactionRepository import com.tangem.domain.walletmanager.WalletManagersFacade @@ -20,10 +21,12 @@ internal object TransactionDataModule { @Singleton fun providesTransactionRepository( walletManagersFacade: WalletManagersFacade, + walletManagersStore: WalletManagersStore, coroutineDispatcherProvider: CoroutineDispatcherProvider, ): TransactionRepository { return DefaultTransactionRepository( walletManagersFacade = walletManagersFacade, + walletManagersStore = walletManagersStore, coroutineDispatcherProvider = coroutineDispatcherProvider, ) } diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt index c28e9dbea7..4acf080799 100644 --- a/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt @@ -22,6 +22,18 @@ interface TransactionRepository { hash: String?, ): TransactionData? + @Suppress("LongParameterList") + suspend fun validateTransaction( + amount: Amount, + fee: Fee, + memo: String?, + destination: String, + userWalletId: UserWalletId, + network: Network, + isSwap: Boolean, + hash: String?, + ): Result + suspend fun sendTransaction( txData: TransactionData, signer: CommonSigner, diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ValidateTransactionUseCase.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ValidateTransactionUseCase.kt new file mode 100644 index 0000000000..56c89954a4 --- /dev/null +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ValidateTransactionUseCase.kt @@ -0,0 +1,39 @@ +package com.tangem.domain.transaction.usecase + +import arrow.core.Either +import arrow.core.left +import arrow.core.right +import com.tangem.blockchain.common.Amount +import com.tangem.blockchain.common.transaction.Fee +import com.tangem.domain.tokens.model.Network +import com.tangem.domain.transaction.TransactionRepository +import com.tangem.domain.wallets.models.UserWalletId + +class ValidateTransactionUseCase( + private val transactionRepository: TransactionRepository, +) { + + @Suppress("LongParameterList") + suspend operator fun invoke( + amount: Amount, + fee: Fee, + memo: String?, + destination: String, + userWalletId: UserWalletId, + network: Network, + isSwap: Boolean = false, + hash: String? = null, + ): Either { + return transactionRepository.validateTransaction( + amount = amount, + fee = fee, + memo = memo, + destination = destination, + userWalletId = userWalletId, + network = network, + isSwap = isSwap, + hash = hash, + ) + .fold(onSuccess = { Unit.right() }, onFailure = { it.left() }) + } +} \ No newline at end of file diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 6e2f105776..7478a68a2b 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -86,7 +86,7 @@ room = "2.6.1" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "develop-621" +tangemBlockchainSdk = "develop-624" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-351" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^