Updated on 2026-08-14
This commit is contained in:
parent
aa621dd48f
commit
c8b7934d93
5 changed files with 152 additions and 8 deletions
|
|
@ -26,7 +26,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.SupervisorJob
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
@Suppress("TooManyFunctions", "LargeClass")
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object TransactionDomainModule {
|
||||
|
|
@ -346,4 +346,21 @@ internal object TransactionDomainModule {
|
|||
getHotWalletSigner = tangemHotWalletSignerFactory::create,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideEstimateFeeForTokenUseCase(
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
gaslessTransactionRepository: GaslessTransactionRepository,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
getMultiCryptoCurrencyStatusUseCase: GetMultiCryptoCurrencyStatusUseCase,
|
||||
): EstimateFeeForTokenUseCase {
|
||||
return EstimateFeeForTokenUseCase(
|
||||
gaslessTransactionRepository = gaslessTransactionRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
demoConfig = DemoConfig,
|
||||
currenciesRepository = currenciesRepository,
|
||||
getMultiCryptoCurrencyStatusUseCase = getMultiCryptoCurrencyStatusUseCase,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ interface GaslessTxServiceApi {
|
|||
@GET("api/v1/tokens")
|
||||
suspend fun getSupportedTokens(): ApiResponse<GaslessServiceResponse<GaslessSupportedTokens>>
|
||||
|
||||
@POST("api/v1/sign")
|
||||
@POST("api/v1/transaction/sign")
|
||||
suspend fun signGaslessTransaction(
|
||||
@Body transaction: GaslessTransactionRequest,
|
||||
): ApiResponse<GaslessServiceResponse<GaslessSignedTransactionResultDTO>>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.data.transaction.convertes
|
||||
|
||||
import com.tangem.blockchain.extensions.formatHex
|
||||
import com.tangem.datasource.api.gasless.models.FeeData
|
||||
import com.tangem.datasource.api.gasless.models.TransactionData
|
||||
import com.tangem.domain.transaction.models.GaslessTransactionData
|
||||
|
|
@ -27,7 +28,7 @@ class GaslessTxDataToGaslessRequestConverter : Converter<GaslessTransactionData,
|
|||
return TransactionData(
|
||||
to = transaction.to,
|
||||
value = transaction.value.toString(),
|
||||
data = transaction.data.toHexString(),
|
||||
data = transaction.data.toHexString().formatHex(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -266,11 +266,6 @@ class CreateAndSendGaslessTransactionUseCase(
|
|||
}
|
||||
|
||||
private fun buildTransaction(transactionData: TransactionData.Uncompiled): GaslessTransactionData.Transaction {
|
||||
val amount = transactionData.amount.value
|
||||
?.movePointRight(transactionData.amount.decimals)
|
||||
?.toBigInteger()
|
||||
?: error("Transaction amount value is null")
|
||||
|
||||
val callData = (transactionData.extras as? EthereumTransactionExtras)?.callData
|
||||
?: error("Ethereum call data is required")
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
package com.tangem.domain.transaction.usecase.gasless
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.domain.demo.DemoTransactionSender
|
||||
import com.tangem.domain.demo.models.DemoConfig
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.transaction.GaslessTransactionRepository
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.domain.transaction.error.mapToFeeError
|
||||
import com.tangem.domain.transaction.models.TransactionFeeExtended
|
||||
import com.tangem.domain.transaction.raiseIllegalStateError
|
||||
import com.tangem.domain.utils.convertToSdkAmount
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import java.math.BigDecimal
|
||||
|
||||
class EstimateFeeForTokenUseCase(
|
||||
private val gaslessTransactionRepository: GaslessTransactionRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val demoConfig: DemoConfig,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val getMultiCryptoCurrencyStatusUseCase: GetMultiCryptoCurrencyStatusUseCase,
|
||||
) {
|
||||
|
||||
private val tokenFeeCalculator = TokenFeeCalculator(
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
gaslessTransactionRepository = gaslessTransactionRepository,
|
||||
demoConfig = demoConfig,
|
||||
)
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWallet: UserWallet,
|
||||
token: CryptoCurrency,
|
||||
amount: BigDecimal,
|
||||
): Either<GetFeeError, TransactionFeeExtended> {
|
||||
return either {
|
||||
if (!gaslessTransactionRepository.isNetworkSupported(token.network)) {
|
||||
raise(GetFeeError.GaslessError.NetworkIsNotSupported)
|
||||
}
|
||||
|
||||
val userCurrenciesStatusesByNetwork = getMultiCryptoCurrencyStatusUseCase.invokeMultiWalletSync(
|
||||
userWallet.walletId,
|
||||
).getOrNull()?.filter {
|
||||
it.currency.network.id == token.network.id
|
||||
} ?: raiseIllegalStateError("currencies list is null for userWalletId=${userWallet.walletId}")
|
||||
|
||||
val tokenCurrencyStatus = userCurrenciesStatusesByNetwork.find {
|
||||
it.currency.id == token.id
|
||||
} ?: raiseIllegalStateError("token currency not found for network ${token.network.id}")
|
||||
|
||||
val amountData = amount.convertToSdkAmount(tokenCurrencyStatus)
|
||||
val result = if (userWallet is UserWallet.Cold &&
|
||||
demoConfig.isDemoCardId(userWallet.scanResponse.card.cardId)
|
||||
) {
|
||||
demoTransactionSender(userWallet, token).estimateFee(
|
||||
amount = amountData,
|
||||
destination = "",
|
||||
)
|
||||
} else {
|
||||
walletManagersFacade.estimateFee(
|
||||
amount = amountData,
|
||||
userWalletId = userWallet.walletId,
|
||||
network = token.network,
|
||||
)
|
||||
}
|
||||
|
||||
val initialTxFee = when (result) {
|
||||
is Result.Success -> result.data
|
||||
is Result.Failure -> raise(result.mapToFeeError())
|
||||
null -> raise(GetFeeError.UnknownError)
|
||||
}
|
||||
|
||||
val initialFeeEth = initialTxFee.normal as? Fee.Ethereum
|
||||
?: raiseIllegalStateError(
|
||||
error = "only Fee.Ethereum supported, but was different",
|
||||
)
|
||||
|
||||
val nativeCurrency = currenciesRepository.getNetworkCoin(
|
||||
userWalletId = userWallet.walletId,
|
||||
networkId = token.network.id,
|
||||
derivationPath = token.network.derivationPath,
|
||||
)
|
||||
|
||||
val nativeCurrencyStatus = userCurrenciesStatusesByNetwork.find {
|
||||
it.currency.id == nativeCurrency.id
|
||||
} ?: raiseIllegalStateError("native currency not found for network ${token.network.id}")
|
||||
|
||||
val walletManager = prepareWalletManager(userWallet, token.network)
|
||||
|
||||
tokenFeeCalculator.calculateTokenFee(
|
||||
walletManager = walletManager,
|
||||
tokenForPayFeeStatus = tokenCurrencyStatus,
|
||||
nativeCurrencyStatus = nativeCurrencyStatus,
|
||||
initialFee = initialFeeEth,
|
||||
).bind()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NullableToStringCall")
|
||||
private suspend fun Raise<GetFeeError>.prepareWalletManager(
|
||||
userWallet: UserWallet,
|
||||
network: Network,
|
||||
): EthereumWalletManager {
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWallet.walletId,
|
||||
network = network,
|
||||
)
|
||||
val ethereumWalletManager = walletManager as? EthereumWalletManager
|
||||
?: raiseIllegalStateError("WalletManager type ${walletManager?.javaClass?.name} not supported")
|
||||
return ethereumWalletManager
|
||||
}
|
||||
|
||||
private suspend fun demoTransactionSender(
|
||||
userWallet: UserWallet,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
): DemoTransactionSender {
|
||||
return DemoTransactionSender(
|
||||
walletManagersFacade
|
||||
.getOrCreateWalletManager(userWallet.walletId, cryptoCurrency.network)
|
||||
?: error("WalletManager is null"),
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue