Updated on 2026-08-14
This commit is contained in:
parent
8adc79a8c3
commit
f4bb2bbc2d
21 changed files with 327 additions and 236 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.domain.demo
|
||||
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.common.smartcontract.SmartContractCallData
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.blockchain.common.transaction.TransactionSendResult
|
||||
|
|
@ -24,8 +25,12 @@ class DemoTransactionSender(private val walletManager: WalletManager) : Transact
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun estimateFee(amount: Amount, destination: String): Result<TransactionFee> {
|
||||
return getFee(amount, walletManager.wallet.address)
|
||||
override suspend fun estimateFee(
|
||||
amount: Amount,
|
||||
destination: String,
|
||||
callData: SmartContractCallData?,
|
||||
): Result<TransactionFee> {
|
||||
return getFee(amount, walletManager.wallet.address, callData)
|
||||
}
|
||||
|
||||
override suspend fun send(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.blockchain.common.address.Address
|
|||
import com.tangem.blockchain.common.address.AddressType
|
||||
import com.tangem.blockchain.common.address.EstimationFeeAddressFactory
|
||||
import com.tangem.blockchain.common.pagination.Page
|
||||
import com.tangem.blockchain.common.smartcontract.SmartContractCallDataProviderFactory
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.blockchain.common.trustlines.AssetRequirementsManager
|
||||
|
|
@ -488,9 +489,20 @@ class DefaultWalletManagersFacade(
|
|||
|
||||
val destination = estimationFeeAddressFactory.makeAddress(blockchain)
|
||||
|
||||
val callData = if (amount.type is AmountType.Token) {
|
||||
SmartContractCallDataProviderFactory.getTokenTransferCallData(
|
||||
destinationAddress = destination,
|
||||
amount = amount,
|
||||
blockchain = blockchain,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
(walletManager as? TransactionSender)?.estimateFee(
|
||||
amount = amount,
|
||||
destination = destination,
|
||||
callData = callData,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
package com.tangem.domain.transaction
|
||||
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.common.smartcontract.SmartContractCallData
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionSendResult
|
||||
import com.tangem.blockchain.common.transaction.TransactionsSendResult
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.transaction.models.TransactionType
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
|
|
@ -22,7 +22,16 @@ interface TransactionRepository {
|
|||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
txExtras: TransactionExtras?,
|
||||
hash: String?,
|
||||
): TransactionData.Uncompiled
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
suspend fun createTransferTransaction(
|
||||
amount: Amount,
|
||||
fee: Fee,
|
||||
memo: String?,
|
||||
destination: String,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): TransactionData.Uncompiled
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
@ -34,7 +43,6 @@ interface TransactionRepository {
|
|||
spenderAddress: String,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
hash: String?,
|
||||
): TransactionData.Uncompiled
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
@ -45,9 +53,6 @@ interface TransactionRepository {
|
|||
destination: String,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
isSwap: Boolean = false,
|
||||
txExtras: TransactionExtras?,
|
||||
hash: String? = null,
|
||||
): Result<Unit>
|
||||
|
||||
suspend fun sendTransaction(
|
||||
|
|
@ -66,9 +71,8 @@ interface TransactionRepository {
|
|||
): com.tangem.blockchain.extensions.Result<TransactionsSendResult>
|
||||
|
||||
fun createTransactionDataExtras(
|
||||
data: String,
|
||||
callData: SmartContractCallData,
|
||||
network: Network,
|
||||
transactionType: TransactionType,
|
||||
nonce: BigInteger?,
|
||||
gasLimit: BigInteger?,
|
||||
): TransactionExtras
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import com.tangem.domain.utils.convertToSdkAmount
|
|||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Use case to create and get approval transaction
|
||||
*/
|
||||
class CreateApprovalTransactionUseCase(
|
||||
private val transactionRepository: TransactionRepository,
|
||||
) {
|
||||
|
|
@ -20,7 +23,6 @@ class CreateApprovalTransactionUseCase(
|
|||
fee: Fee,
|
||||
contractAddress: String,
|
||||
spenderAddress: String,
|
||||
hash: String? = null,
|
||||
) = Either.catch {
|
||||
transactionRepository.createApprovalTransaction(
|
||||
amount = BigDecimal.ZERO.convertToSdkAmount(cryptoCurrency),
|
||||
|
|
@ -30,7 +32,6 @@ class CreateApprovalTransactionUseCase(
|
|||
userWalletId = userWalletId,
|
||||
network = cryptoCurrency.network,
|
||||
fee = fee,
|
||||
hash = hash,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,25 @@
|
|||
package com.tangem.domain.transaction.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.blockchain.common.smartcontract.CompiledSmartContractCallData
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.models.TransactionType
|
||||
import java.math.BigInteger
|
||||
|
||||
class CreateTransactionDataExtrasUseCase(
|
||||
private val transactionRepository: TransactionRepository,
|
||||
) {
|
||||
|
||||
operator fun invoke(
|
||||
data: String,
|
||||
network: Network,
|
||||
transactionType: TransactionType,
|
||||
gasLimit: BigInteger? = null,
|
||||
nonce: BigInteger? = null,
|
||||
) = Either.catch {
|
||||
requireNotNull(
|
||||
transactionRepository.createTransactionDataExtras(
|
||||
data = data,
|
||||
network = network,
|
||||
transactionType = transactionType,
|
||||
nonce = nonce,
|
||||
gasLimit = gasLimit,
|
||||
),
|
||||
) { "Failed to create transaction" }
|
||||
}
|
||||
operator fun invoke(data: String, network: Network, gasLimit: BigInteger? = null, nonce: BigInteger? = null) =
|
||||
Either.catch {
|
||||
requireNotNull(
|
||||
transactionRepository.createTransactionDataExtras(
|
||||
callData = CompiledSmartContractCallData(data.hexToBytes()),
|
||||
network = network,
|
||||
nonce = nonce,
|
||||
gasLimit = gasLimit,
|
||||
),
|
||||
) { "Failed to create transaction" }
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,12 @@ import com.tangem.domain.tokens.model.Network
|
|||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
/**
|
||||
* Use case to create and get transaction
|
||||
*
|
||||
* !!!IMPORTANT
|
||||
* Use when transaction data is already compiled by external service or provider
|
||||
*/
|
||||
class CreateTransactionUseCase(
|
||||
private val transactionRepository: TransactionRepository,
|
||||
) {
|
||||
|
|
@ -24,7 +30,6 @@ class CreateTransactionUseCase(
|
|||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
txExtras: TransactionExtras? = null,
|
||||
hash: String? = null,
|
||||
) = Either.catch {
|
||||
transactionRepository.createTransaction(
|
||||
amount = amount,
|
||||
|
|
@ -34,7 +39,6 @@ class CreateTransactionUseCase(
|
|||
userWalletId = userWalletId,
|
||||
network = network,
|
||||
txExtras = txExtras,
|
||||
hash = hash,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.tangem.domain.transaction.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
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
|
||||
|
||||
/**
|
||||
* Use case to create and get transfer transaction
|
||||
*
|
||||
* !!!IMPORTANT
|
||||
* Use when transaction data is compiled by us using BlockchainSDK methods
|
||||
*/
|
||||
class CreateTransferTransactionUseCase(
|
||||
private val transactionRepository: TransactionRepository,
|
||||
) {
|
||||
|
||||
/**
|
||||
* [REDACTED_TODO_COMMENT]
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
suspend operator fun invoke(
|
||||
amount: Amount,
|
||||
fee: Fee,
|
||||
memo: String?,
|
||||
destination: String,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
) = Either.catch {
|
||||
transactionRepository.createTransferTransaction(
|
||||
amount = amount,
|
||||
fee = fee,
|
||||
memo = memo,
|
||||
destination = destination,
|
||||
userWalletId = userWalletId,
|
||||
network = network,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,9 @@ import java.math.BigDecimal
|
|||
|
||||
/**
|
||||
* Use case to get transaction fee
|
||||
*
|
||||
* !!!IMPORTANT!!!
|
||||
* Use when transaction data is already compiled by external service or provider
|
||||
*/
|
||||
class GetFeeUseCase(
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
package com.tangem.domain.transaction.usecase
|
||||
|
||||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.common.smartcontract.SmartContractCallDataProviderFactory
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.demo.DemoTransactionSender
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.domain.transaction.error.mapToFeeError
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Use case to get transfer transaction fee
|
||||
*
|
||||
* !!!IMPORTANT
|
||||
* Use when transaction data is compiled by us using BlockchainSDK methods
|
||||
*/
|
||||
class GetTransferFeeUseCase(
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val demoConfig: DemoConfig,
|
||||
) {
|
||||
suspend operator fun invoke(
|
||||
amount: BigDecimal,
|
||||
destination: String,
|
||||
userWallet: UserWallet,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
) = either {
|
||||
catch(
|
||||
block = {
|
||||
val amountData = convertCryptoCurrencyToAmount(cryptoCurrency, amount)
|
||||
|
||||
val result = if (demoConfig.isDemoCardId(userWallet.scanResponse.card.cardId)) {
|
||||
demoTransactionSender(userWallet, cryptoCurrency).getFee(
|
||||
amount = amountData,
|
||||
destination = destination,
|
||||
)
|
||||
} else {
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWallet.walletId,
|
||||
network = cryptoCurrency.network,
|
||||
)
|
||||
val smartContractCallData = if (amountData.type is AmountType.Token) {
|
||||
SmartContractCallDataProviderFactory.getTokenTransferCallData(
|
||||
amount = amountData,
|
||||
destinationAddress = destination,
|
||||
blockchain = Blockchain.fromId(cryptoCurrency.network.id.value),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
(walletManager as? TransactionSender)?.getFee(
|
||||
amount = amountData,
|
||||
destination = destination,
|
||||
callData = smartContractCallData,
|
||||
) ?: error("Fee is null")
|
||||
}
|
||||
|
||||
val maybeFee = when (result) {
|
||||
is Result.Success -> result.data
|
||||
is Result.Failure -> raise(result.mapToFeeError())
|
||||
}
|
||||
maybeFee
|
||||
},
|
||||
catch = {
|
||||
raise(GetFeeError.DataError(it))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun demoTransactionSender(
|
||||
userWallet: UserWallet,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
): DemoTransactionSender {
|
||||
return DemoTransactionSender(
|
||||
walletManagersFacade
|
||||
.getOrCreateWalletManager(userWallet.walletId, cryptoCurrency.network)
|
||||
?: error("WalletManager is null"),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertCryptoCurrencyToAmount(cryptoCurrency: CryptoCurrency, amount: BigDecimal) = Amount(
|
||||
currencySymbol = cryptoCurrency.symbol,
|
||||
value = amount,
|
||||
decimals = cryptoCurrency.decimals,
|
||||
type = when (cryptoCurrency) {
|
||||
is CryptoCurrency.Coin -> AmountType.Coin
|
||||
is CryptoCurrency.Token -> AmountType.Token(
|
||||
token = Token(
|
||||
symbol = cryptoCurrency.symbol,
|
||||
contractAddress = cryptoCurrency.contractAddress,
|
||||
decimals = cryptoCurrency.decimals,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -21,8 +21,6 @@ class ValidateTransactionUseCase(
|
|||
destination: String,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
isSwap: Boolean = false,
|
||||
hash: String? = null,
|
||||
): Either<Throwable, Unit> {
|
||||
return transactionRepository.validateTransaction(
|
||||
amount = amount,
|
||||
|
|
@ -31,10 +29,6 @@ class ValidateTransactionUseCase(
|
|||
destination = destination,
|
||||
userWalletId = userWalletId,
|
||||
network = network,
|
||||
isSwap = isSwap,
|
||||
txExtras = null,
|
||||
hash = hash,
|
||||
)
|
||||
.fold(onSuccess = { Unit.right() }, onFailure = { it.left() })
|
||||
).fold(onSuccess = { Unit.right() }, onFailure = { it.left() })
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue