Updated on 2026-08-14

This commit is contained in:
Tangem 2025-08-14 16:31:49 +05:00
parent b58df2dfb7
commit e3a7ba0a77
8 changed files with 122 additions and 8 deletions

View file

@ -18,6 +18,7 @@ import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Suppress("TooManyFunctions")
@Module
@InstallIn(SingletonComponent::class)
internal object TransactionDomainModule {
@ -184,6 +185,15 @@ internal object TransactionDomainModule {
return PrepareForSendUseCase(transactionRepository, cardSdkConfigRepository)
}
@Provides
@Singleton
fun providePrepareAndSignUseCase(
transactionRepository: TransactionRepository,
cardSdkConfigRepository: CardSdkConfigRepository,
): PrepareAndSignUseCase {
return PrepareAndSignUseCase(transactionRepository, cardSdkConfigRepository)
}
@Provides
@Singleton
fun provideSignUseCase(

View file

@ -381,6 +381,26 @@ internal class DefaultTransactionRepository(
preparer.prepareForSendMultiple(transactionData, signer)
}
override suspend fun prepareAndSign(
transactionData: TransactionData,
signer: TransactionSigner,
userWalletId: UserWalletId,
network: Network,
) = withContext(dispatchers.io) {
val preparer = getPreparer(network, userWalletId)
preparer.prepareAndSign(transactionData, signer)
}
override suspend fun prepareAndSignMultiple(
transactionData: List<TransactionData>,
signer: TransactionSigner,
userWalletId: UserWalletId,
network: Network,
) = withContext(dispatchers.io) {
val preparer = getPreparer(network, userWalletId)
preparer.prepareAndSignMultiple(transactionData, signer)
}
private suspend fun getPreparer(network: Network, userWalletId: UserWalletId): TransactionPreparer {
val blockchain = network.toBlockchain()
val walletManager = walletManagersFacade.getOrCreateWalletManager(

View file

@ -30,7 +30,7 @@ import com.tangem.blockchain.common.Amount as BlockchainAmount
internal class WcEthSignTransactionUseCase @AssistedInject constructor(
override val respondService: WcRespondService,
override val analytics: AnalyticsEventHandler,
private val prepareForSend: PrepareForSendUseCase,
private val prepareForSend: PrepareForSendUseCase, // TODO: TODO("[REDACTED_JIRA]")
private val ethTxHelper: WcEthTxHelper,
@Assisted override val context: WcMethodUseCaseContext,
@Assisted override val method: WcEthMethod.SignTransaction,

View file

@ -10,7 +10,7 @@ import com.tangem.data.walletconnect.sign.SignCollector
import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
import com.tangem.domain.transaction.usecase.PrepareForSendUseCase
import com.tangem.domain.transaction.usecase.PrepareAndSignUseCase
import com.tangem.domain.walletconnect.error.parseSendError
import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.usecase.method.BlockAidTransactionCheck
@ -29,7 +29,7 @@ import org.json.JSONObject
internal class WcSolanaSignAllTransactionUseCase @AssistedInject constructor(
override val respondService: WcRespondService,
override val analytics: AnalyticsEventHandler,
private val prepareForSend: PrepareForSendUseCase,
private val prepareAndSign: PrepareAndSignUseCase,
@Assisted override val context: WcMethodUseCaseContext,
@Assisted override val method: WcSolanaMethod.SignAllTransaction,
blockAidDelegate: BlockAidVerificationDelegate,
@ -46,7 +46,7 @@ internal class WcSolanaSignAllTransactionUseCase @AssistedInject constructor(
).map { lce -> lce.map { result -> BlockAidTransactionCheck.Result.Plain(result) } }
override suspend fun SignCollector<List<TransactionData>>.onSign(state: WcSignState<List<TransactionData>>) {
val hash = prepareForSend.invoke(transactionData = state.signModel, userWallet = wallet, network = network)
val hash = prepareAndSign.invoke(transactionData = state.signModel, userWallet = wallet, network = network)
.onLeft { error ->
emit(state.toResult(parseSendError(error).left()))
}

View file

@ -10,7 +10,7 @@ import com.tangem.data.walletconnect.sign.SignCollector
import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
import com.tangem.domain.transaction.usecase.PrepareForSendUseCase
import com.tangem.domain.transaction.usecase.PrepareAndSignUseCase
import com.tangem.domain.walletconnect.error.parseSendError
import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.usecase.method.BlockAidTransactionCheck
@ -27,7 +27,7 @@ import okio.ByteString.Companion.decodeBase64
internal class WcSolanaSignTransactionUseCase @AssistedInject constructor(
override val respondService: WcRespondService,
override val analytics: AnalyticsEventHandler,
private val prepareForSend: PrepareForSendUseCase,
private val prepareAndSign: PrepareAndSignUseCase,
@Assisted override val context: WcMethodUseCaseContext,
@Assisted override val method: WcSolanaMethod.SignTransaction,
blockAidDelegate: BlockAidVerificationDelegate,
@ -44,7 +44,7 @@ internal class WcSolanaSignTransactionUseCase @AssistedInject constructor(
).map { lce -> lce.map { result -> BlockAidTransactionCheck.Result.Plain(result) } }
override suspend fun SignCollector<TransactionData>.onSign(state: WcSignState<TransactionData>) {
val hash = prepareForSend.invoke(transactionData = state.signModel, userWallet = wallet, network = network)
val hash = prepareAndSign.invoke(transactionData = state.signModel, userWallet = wallet, network = network)
.onLeft { error ->
emit(state.toResult(parseSendError(error).left()))
}

View file

@ -109,4 +109,18 @@ interface TransactionRepository {
userWalletId: UserWalletId,
network: Network,
): com.tangem.blockchain.extensions.Result<List<ByteArray>>
suspend fun prepareAndSign(
transactionData: TransactionData,
signer: TransactionSigner,
userWalletId: UserWalletId,
network: Network,
): com.tangem.blockchain.extensions.Result<ByteArray>
suspend fun prepareAndSignMultiple(
transactionData: List<TransactionData>,
signer: TransactionSigner,
userWalletId: UserWalletId,
network: Network,
): com.tangem.blockchain.extensions.Result<List<ByteArray>>
}

View file

@ -0,0 +1,70 @@
package com.tangem.domain.transaction.usecase
import arrow.core.Either
import arrow.core.left
import arrow.core.right
import com.tangem.blockchain.common.TransactionData
import com.tangem.blockchain.common.TransactionSigner
import com.tangem.blockchain.extensions.Result
import com.tangem.domain.card.common.TapWorkarounds.isTangemTwins
import com.tangem.domain.card.models.TwinKey
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.requireColdWallet
import com.tangem.domain.transaction.TransactionRepository
import com.tangem.domain.transaction.error.SendTransactionError
class PrepareAndSignUseCase(
private val transactionRepository: TransactionRepository,
private val cardSdkConfigRepository: CardSdkConfigRepository,
) {
suspend operator fun invoke(
transactionData: TransactionData,
userWallet: UserWallet,
network: Network,
): Either<SendTransactionError, ByteArray> {
val signer = createSigner(userWallet)
val result = transactionRepository.prepareAndSign(
transactionData = transactionData,
userWalletId = userWallet.walletId,
network = network,
signer = signer,
)
return when (result) {
is Result.Failure -> SendTransactionUseCase.handleError(result).left()
is Result.Success -> result.data.right()
}
}
suspend operator fun invoke(
transactionData: List<TransactionData>,
userWallet: UserWallet,
network: Network,
): Either<SendTransactionError, List<ByteArray>> {
val signer = createSigner(userWallet)
val result = transactionRepository.prepareAndSignMultiple(
transactionData = transactionData,
userWalletId = userWallet.walletId,
network = network,
signer = signer,
)
return when (result) {
is Result.Failure -> SendTransactionUseCase.handleError(result).left()
is Result.Success -> result.data.right()
}
}
private fun createSigner(userWallet: UserWallet): TransactionSigner {
userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
val card = userWallet.scanResponse.card
val isCardNotBackedUp = card.backupStatus?.isActive != true && !card.isTangemTwins
val signer = cardSdkConfigRepository.getCommonSigner(
cardId = card.cardId.takeIf { isCardNotBackedUp },
twinKey = TwinKey.getOrNull(scanResponse = userWallet.scanResponse),
)
return signer
}
}

View file

@ -5,7 +5,7 @@
# https://github.com/tangem/tangem-sdk-android/
# https://github.com/tangem/vico
tangemBlockchainSdk = "releases-5.27.0-1142"
tangemBlockchainSdk = "releases-5.27.0-1147"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "releases-5.27.0-513"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^