Updated on 2026-08-14
This commit is contained in:
parent
22a32ec8f1
commit
99cdc003c8
16 changed files with 156 additions and 121 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5ba0959d72f41e49a22f792e9a3d53e5e24e7713
|
Subproject commit 098662beb5b0123b11f5ee4873d4bd667ac93c73
|
||||||
|
|
@ -116,9 +116,6 @@ class DefaultGaslessTransactionRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
|
||||||
const val TOKEN_RECEIVER_ADDRESS = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
|
|
||||||
|
|
||||||
val BASE_GAS_FOR_TRANSACTION: BigInteger = BigInteger("100000")
|
val BASE_GAS_FOR_TRANSACTION: BigInteger = BigInteger("100000")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.domain.tokens
|
package com.tangem.domain.tokens
|
||||||
|
|
||||||
import arrow.core.Either
|
import arrow.core.Either
|
||||||
|
import com.tangem.blockchain.common.transaction.Fee
|
||||||
import com.tangem.domain.models.currency.CryptoCurrency
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.domain.tokens.model.FeePaidCurrency
|
import com.tangem.domain.tokens.model.FeePaidCurrency
|
||||||
|
|
@ -16,9 +17,15 @@ class IsAmountSubtractAvailableUseCase(
|
||||||
suspend operator fun invoke(
|
suspend operator fun invoke(
|
||||||
userWalletId: UserWalletId,
|
userWalletId: UserWalletId,
|
||||||
currency: CryptoCurrency,
|
currency: CryptoCurrency,
|
||||||
isGaslessEthTx: Boolean = false,
|
maybeGaslessFee: Pair<CryptoCurrency.ID, Fee>? = null,
|
||||||
): Either<Throwable, Boolean> = Either.catch {
|
): Either<Throwable, Boolean> = Either.catch {
|
||||||
if (isGaslessEthTx) return@catch true
|
val maybeTokenCurrency = currency as? CryptoCurrency.Token
|
||||||
|
if (maybeGaslessFee != null &&
|
||||||
|
maybeGaslessFee.second is Fee.Ethereum.TokenCurrency &&
|
||||||
|
maybeGaslessFee.first.contractAddress.equals(maybeTokenCurrency?.contractAddress, true)
|
||||||
|
) {
|
||||||
|
return@catch true
|
||||||
|
}
|
||||||
when (val feeCurrency = currenciesRepository.getFeePaidCurrency(userWalletId, currency.network)) {
|
when (val feeCurrency = currenciesRepository.getFeePaidCurrency(userWalletId, currency.network)) {
|
||||||
is FeePaidCurrency.Coin -> currency is CryptoCurrency.Coin
|
is FeePaidCurrency.Coin -> currency is CryptoCurrency.Coin
|
||||||
is FeePaidCurrency.SameCurrency -> true
|
is FeePaidCurrency.SameCurrency -> true
|
||||||
|
|
|
||||||
|
|
@ -14,5 +14,6 @@ sealed class GetFeeError {
|
||||||
data object NetworkIsNotSupported : GaslessError()
|
data object NetworkIsNotSupported : GaslessError()
|
||||||
data object NoSupportedTokensFound : GaslessError()
|
data object NoSupportedTokensFound : GaslessError()
|
||||||
data object NotEnoughFunds : GaslessError()
|
data object NotEnoughFunds : GaslessError()
|
||||||
|
data class DataError(val cause: Throwable?) : GaslessError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +89,7 @@ class EstimateFeeForGaslessTxUseCase(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
catch = {
|
catch = {
|
||||||
raise(GetFeeError.DataError(it))
|
raise(GaslessError.DataError(it))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.tangem.domain.transaction.usecase.gasless
|
||||||
|
|
||||||
import arrow.core.Either
|
import arrow.core.Either
|
||||||
import arrow.core.raise.Raise
|
import arrow.core.raise.Raise
|
||||||
|
import arrow.core.raise.catch
|
||||||
import arrow.core.raise.either
|
import arrow.core.raise.either
|
||||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||||
import com.tangem.blockchain.common.transaction.Fee
|
import com.tangem.blockchain.common.transaction.Fee
|
||||||
|
|
@ -17,6 +18,7 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||||
import com.tangem.domain.tokens.repository.CurrencyChecksRepository
|
import com.tangem.domain.tokens.repository.CurrencyChecksRepository
|
||||||
import com.tangem.domain.transaction.GaslessTransactionRepository
|
import com.tangem.domain.transaction.GaslessTransactionRepository
|
||||||
import com.tangem.domain.transaction.error.GetFeeError
|
import com.tangem.domain.transaction.error.GetFeeError
|
||||||
|
import com.tangem.domain.transaction.error.GetFeeError.GaslessError
|
||||||
import com.tangem.domain.transaction.error.mapToFeeError
|
import com.tangem.domain.transaction.error.mapToFeeError
|
||||||
import com.tangem.domain.transaction.models.TransactionFeeExtended
|
import com.tangem.domain.transaction.models.TransactionFeeExtended
|
||||||
import com.tangem.domain.transaction.raiseIllegalStateError
|
import com.tangem.domain.transaction.raiseIllegalStateError
|
||||||
|
|
@ -45,62 +47,69 @@ class EstimateFeeForTokenUseCase(
|
||||||
amount: BigDecimal,
|
amount: BigDecimal,
|
||||||
): Either<GetFeeError, TransactionFeeExtended> {
|
): Either<GetFeeError, TransactionFeeExtended> {
|
||||||
return either {
|
return either {
|
||||||
val token = tokenCurrencyStatus.currency
|
catch(
|
||||||
if (!currencyChecksRepository.isNetworkSupportedForGaslessTx(token.network)) {
|
block = {
|
||||||
raise(GetFeeError.GaslessError.NetworkIsNotSupported)
|
val token = tokenCurrencyStatus.currency
|
||||||
}
|
if (!currencyChecksRepository.isNetworkSupportedForGaslessTx(token.network)) {
|
||||||
|
raise(GetFeeError.GaslessError.NetworkIsNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
val amountData = amount.convertToSdkAmount(tokenCurrencyStatus)
|
val amountData = amount.convertToSdkAmount(tokenCurrencyStatus)
|
||||||
val result = if (userWallet is UserWallet.Cold &&
|
val result = if (userWallet is UserWallet.Cold &&
|
||||||
demoConfig.isDemoCardId(userWallet.scanResponse.card.cardId)
|
demoConfig.isDemoCardId(userWallet.scanResponse.card.cardId)
|
||||||
) {
|
) {
|
||||||
demoTransactionSender(userWallet, token).estimateFee(
|
demoTransactionSender(userWallet, token).estimateFee(
|
||||||
amount = amountData,
|
amount = amountData,
|
||||||
destination = "",
|
destination = "",
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
walletManagersFacade.estimateFee(
|
walletManagersFacade.estimateFee(
|
||||||
amount = amountData,
|
amount = amountData,
|
||||||
userWalletId = userWallet.walletId,
|
userWalletId = userWallet.walletId,
|
||||||
network = token.network,
|
network = token.network,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val initialTxFee = when (result) {
|
val initialTxFee = when (result) {
|
||||||
is Result.Success -> result.data
|
is Result.Success -> result.data
|
||||||
is Result.Failure -> raise(result.mapToFeeError())
|
is Result.Failure -> raise(result.mapToFeeError())
|
||||||
null -> raise(GetFeeError.UnknownError)
|
null -> raise(GetFeeError.UnknownError)
|
||||||
}
|
}
|
||||||
|
|
||||||
val initialFeeEth = initialTxFee.normal as? Fee.Ethereum
|
val initialFeeEth = initialTxFee.normal as? Fee.Ethereum
|
||||||
?: raiseIllegalStateError(
|
?: raiseIllegalStateError(
|
||||||
error = "only Fee.Ethereum supported, but was different",
|
error = "only Fee.Ethereum supported, but was different",
|
||||||
)
|
)
|
||||||
|
|
||||||
val nativeCurrency = currenciesRepository.getNetworkCoin(
|
val nativeCurrency = currenciesRepository.getNetworkCoin(
|
||||||
userWalletId = userWallet.walletId,
|
userWalletId = userWallet.walletId,
|
||||||
networkId = token.network.id,
|
networkId = token.network.id,
|
||||||
derivationPath = token.network.derivationPath,
|
derivationPath = token.network.derivationPath,
|
||||||
|
)
|
||||||
|
|
||||||
|
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 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()
|
||||||
|
},
|
||||||
|
catch = {
|
||||||
|
raise(GaslessError.DataError(it))
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
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 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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ class GetAvailableFeeTokensUseCase(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
catch = {
|
catch = {
|
||||||
raise(GetFeeError.DataError(it))
|
raise(GetFeeError.GaslessError.DataError(it))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ class GetFeeForGaslessUseCase(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
catch = {
|
catch = {
|
||||||
raise(GetFeeError.DataError(it))
|
raise(GaslessError.DataError(it))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.tangem.domain.transaction.usecase.gasless
|
||||||
|
|
||||||
import arrow.core.Either
|
import arrow.core.Either
|
||||||
import arrow.core.raise.Raise
|
import arrow.core.raise.Raise
|
||||||
|
import arrow.core.raise.catch
|
||||||
import arrow.core.raise.either
|
import arrow.core.raise.either
|
||||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||||
import com.tangem.blockchain.common.TransactionData
|
import com.tangem.blockchain.common.TransactionData
|
||||||
|
|
@ -15,6 +16,7 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||||
import com.tangem.domain.tokens.repository.CurrencyChecksRepository
|
import com.tangem.domain.tokens.repository.CurrencyChecksRepository
|
||||||
import com.tangem.domain.transaction.GaslessTransactionRepository
|
import com.tangem.domain.transaction.GaslessTransactionRepository
|
||||||
import com.tangem.domain.transaction.error.GetFeeError
|
import com.tangem.domain.transaction.error.GetFeeError
|
||||||
|
import com.tangem.domain.transaction.error.GetFeeError.GaslessError
|
||||||
import com.tangem.domain.transaction.models.TransactionFeeExtended
|
import com.tangem.domain.transaction.models.TransactionFeeExtended
|
||||||
import com.tangem.domain.transaction.raiseIllegalStateError
|
import com.tangem.domain.transaction.raiseIllegalStateError
|
||||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||||
|
|
@ -40,50 +42,57 @@ class GetFeeForTokenUseCase(
|
||||||
transactionData: TransactionData,
|
transactionData: TransactionData,
|
||||||
): Either<GetFeeError, TransactionFeeExtended> {
|
): Either<GetFeeError, TransactionFeeExtended> {
|
||||||
return either {
|
return either {
|
||||||
if (!currencyChecksRepository.isNetworkSupportedForGaslessTx(token.network)) {
|
catch(
|
||||||
raise(GetFeeError.GaslessError.NetworkIsNotSupported)
|
block = {
|
||||||
}
|
if (!currencyChecksRepository.isNetworkSupportedForGaslessTx(token.network)) {
|
||||||
|
raise(GaslessError.NetworkIsNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
val walletManager = prepareWalletManager(userWallet, token.network)
|
val walletManager = prepareWalletManager(userWallet, token.network)
|
||||||
|
|
||||||
val initialTxFee = tokenFeeCalculator.calculateInitialFee(
|
val initialTxFee = tokenFeeCalculator.calculateInitialFee(
|
||||||
userWallet = userWallet,
|
userWallet = userWallet,
|
||||||
network = token.network,
|
network = token.network,
|
||||||
walletManager = walletManager,
|
walletManager = walletManager,
|
||||||
transactionData = transactionData,
|
transactionData = transactionData,
|
||||||
).bind()
|
).bind()
|
||||||
|
|
||||||
val initialFeeEth = initialTxFee.normal as? Fee.Ethereum
|
val initialFeeEth = initialTxFee.normal as? Fee.Ethereum
|
||||||
?: raiseIllegalStateError(
|
?: raiseIllegalStateError(
|
||||||
error = "only Fee.Ethereum supported, but was different",
|
error = "only Fee.Ethereum supported, but was different",
|
||||||
)
|
)
|
||||||
|
|
||||||
val nativeCurrency = currenciesRepository.getNetworkCoin(
|
val nativeCurrency = currenciesRepository.getNetworkCoin(
|
||||||
userWalletId = userWallet.walletId,
|
userWalletId = userWallet.walletId,
|
||||||
networkId = token.network.id,
|
networkId = token.network.id,
|
||||||
derivationPath = token.network.derivationPath,
|
derivationPath = token.network.derivationPath,
|
||||||
|
)
|
||||||
|
|
||||||
|
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 nativeCurrencyStatus = userCurrenciesStatusesByNetwork.find {
|
||||||
|
it.currency.id == nativeCurrency.id
|
||||||
|
} ?: raiseIllegalStateError("native currency not found for network ${token.network.id}")
|
||||||
|
|
||||||
|
val tokenCurrencyStatus = userCurrenciesStatusesByNetwork.find {
|
||||||
|
it.currency.id == token.id
|
||||||
|
} ?: raiseIllegalStateError("token currency not found for network ${token.network.id}")
|
||||||
|
|
||||||
|
tokenFeeCalculator.calculateTokenFee(
|
||||||
|
walletManager = walletManager,
|
||||||
|
tokenForPayFeeStatus = tokenCurrencyStatus,
|
||||||
|
nativeCurrencyStatus = nativeCurrencyStatus,
|
||||||
|
initialFee = initialFeeEth,
|
||||||
|
).bind()
|
||||||
|
},
|
||||||
|
catch = {
|
||||||
|
raise(GaslessError.DataError(it))
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
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 nativeCurrencyStatus = userCurrenciesStatusesByNetwork.find {
|
|
||||||
it.currency.id == nativeCurrency.id
|
|
||||||
} ?: raiseIllegalStateError("native currency not found for network ${token.network.id}")
|
|
||||||
|
|
||||||
val tokenCurrencyStatus = userCurrenciesStatusesByNetwork.find {
|
|
||||||
it.currency.id == token.id
|
|
||||||
} ?: raiseIllegalStateError("token currency not found for network ${token.network.id}")
|
|
||||||
|
|
||||||
tokenFeeCalculator.calculateTokenFee(
|
|
||||||
walletManager = walletManager,
|
|
||||||
tokenForPayFeeStatus = tokenCurrencyStatus,
|
|
||||||
nativeCurrencyStatus = nativeCurrencyStatus,
|
|
||||||
initialFee = initialFeeEth,
|
|
||||||
).bind()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import com.tangem.domain.transaction.raiseIllegalStateError
|
||||||
import com.tangem.domain.utils.convertToSdkAmount
|
import com.tangem.domain.utils.convertToSdkAmount
|
||||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
import java.math.BigInteger
|
||||||
import java.math.RoundingMode
|
import java.math.RoundingMode
|
||||||
|
|
||||||
internal class TokenFeeCalculator(
|
internal class TokenFeeCalculator(
|
||||||
|
|
@ -51,7 +52,7 @@ internal class TokenFeeCalculator(
|
||||||
|
|
||||||
val maybeFee = when (val result = transactionSender.getFee(transactionData = transactionData)) {
|
val maybeFee = when (val result = transactionSender.getFee(transactionData = transactionData)) {
|
||||||
is Result.Success -> result.data
|
is Result.Success -> result.data
|
||||||
is Result.Failure -> raise(result.mapToFeeError())
|
is Result.Failure -> raise(GaslessError.DataError(result.error))
|
||||||
}
|
}
|
||||||
maybeFee
|
maybeFee
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +116,7 @@ internal class TokenFeeCalculator(
|
||||||
val feeTransferGasLimit = when (feeTransferGasLimitResult) {
|
val feeTransferGasLimit = when (feeTransferGasLimitResult) {
|
||||||
is Result.Failure -> raise(GetFeeError.DataError(feeTransferGasLimitResult.error))
|
is Result.Failure -> raise(GetFeeError.DataError(feeTransferGasLimitResult.error))
|
||||||
is Result.Success -> feeTransferGasLimitResult.data
|
is Result.Success -> feeTransferGasLimitResult.data
|
||||||
}
|
}.increaseByPercent(PERCENT_TO_INCREASE_TRANSFER_GASLIMIT)
|
||||||
|
|
||||||
val baseGas = gaslessTransactionRepository.getBaseGasForTransaction()
|
val baseGas = gaslessTransactionRepository.getBaseGasForTransaction()
|
||||||
|
|
||||||
|
|
@ -197,6 +198,7 @@ internal class TokenFeeCalculator(
|
||||||
/** Gas price safety multiplier for fee calculation */
|
/** Gas price safety multiplier for fee calculation */
|
||||||
const val GAS_PRICE_MULTIPLIER = 2
|
const val GAS_PRICE_MULTIPLIER = 2
|
||||||
const val PERCENT_TO_INCREASE_TOKEN_PRICE = 1
|
const val PERCENT_TO_INCREASE_TOKEN_PRICE = 1
|
||||||
|
const val PERCENT_TO_INCREASE_TRANSFER_GASLIMIT = 10
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases BigDecimal value by specified percentage.
|
* Increases BigDecimal value by specified percentage.
|
||||||
|
|
@ -216,5 +218,11 @@ internal class TokenFeeCalculator(
|
||||||
val multiplier = BigDecimal.ONE.add(BigDecimal(percent).divide(BigDecimal("100")))
|
val multiplier = BigDecimal.ONE.add(BigDecimal(percent).divide(BigDecimal("100")))
|
||||||
return this.multiply(multiplier)
|
return this.multiply(multiplier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun BigInteger.increaseByPercent(percent: Int): BigInteger {
|
||||||
|
require(percent >= 0) { "Percent must be non-negative" }
|
||||||
|
val multiplier = BigDecimal.ONE.add(BigDecimal(percent).divide(BigDecimal("100")))
|
||||||
|
return BigDecimal(this).multiply(multiplier).toBigInteger()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +110,7 @@ class TokenFeeCalculatorTest {
|
||||||
// Then
|
// Then
|
||||||
assertTrue(result.isLeft())
|
assertTrue(result.isLeft())
|
||||||
result.onLeft { error ->
|
result.onLeft { error ->
|
||||||
assertTrue(error is GetFeeError.DataError)
|
assertTrue(error is GetFeeError.GaslessError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,7 +363,7 @@ class TokenFeeCalculatorTest {
|
||||||
// Expected
|
// Expected
|
||||||
|
|
||||||
val expectedAmount = Amount(
|
val expectedAmount = Amount(
|
||||||
value = BigDecimal("36.200000000000000000000000000000000000"),
|
value = BigDecimal("37.400000000000000000000000000000000000"),
|
||||||
token = Token(
|
token = Token(
|
||||||
name = "USDC",
|
name = "USDC",
|
||||||
symbol = "USDC",
|
symbol = "USDC",
|
||||||
|
|
@ -371,9 +371,9 @@ class TokenFeeCalculatorTest {
|
||||||
decimals = 6,
|
decimals = 6,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val expectedGasLimit = "181000".toBigInteger()
|
val expectedGasLimit = "187000".toBigInteger()
|
||||||
val expectedCoinPriceInToken = BigInteger("2020000000") // 2000 * 1.01 * 10^6
|
val expectedCoinPriceInToken = BigInteger("2020000000") // 2000 * 1.01 * 10^6
|
||||||
val expectedFeeTransferLimit = "60000".toBigInteger()
|
val expectedFeeTransferLimit = "66000".toBigInteger()
|
||||||
val expectedBaseGas = "21000".toBigInteger()
|
val expectedBaseGas = "21000".toBigInteger()
|
||||||
|
|
||||||
// Given
|
// Given
|
||||||
|
|
|
||||||
|
|
@ -628,14 +628,14 @@ internal class SendConfirmModel @Inject constructor(
|
||||||
|
|
||||||
private fun updateAmountSubtractAvailability() {
|
private fun updateAmountSubtractAvailability() {
|
||||||
modelScope.launch {
|
modelScope.launch {
|
||||||
val isGaslessEthTx =
|
val fee = feeUMV2?.feeExtraInfo?.transactionFeeExtended?.transactionFee?.normal
|
||||||
feeUMV2?.feeExtraInfo?.transactionFeeExtended?.transactionFee?.normal is Fee.Ethereum.TokenCurrency
|
// we assume if feeExtraInfo is empty then pay fee in the main currency
|
||||||
isAmountSubtractAvailable =
|
val feeTokenId = feeUMV2?.feeExtraInfo?.transactionFeeExtended?.feeTokenId ?: cryptoCurrency.id
|
||||||
isAmountSubtractAvailableUseCase(
|
isAmountSubtractAvailable = isAmountSubtractAvailableUseCase(
|
||||||
userWalletId = userWallet.walletId,
|
userWalletId = userWallet.walletId,
|
||||||
currency = cryptoCurrency,
|
currency = cryptoCurrency,
|
||||||
isGaslessEthTx = isGaslessEthTx,
|
maybeGaslessFee = fee?.let { feeTokenId to fee },
|
||||||
).getOrElse { false }
|
).getOrElse { false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,10 +106,12 @@ internal class NotificationsModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun checkIfSubtractAvailable() {
|
private suspend fun checkIfSubtractAvailable() {
|
||||||
|
val feeCurrencyId = notificationData.feeCryptoCurrencyStatus.currency.id
|
||||||
|
val fee = notificationData.fee
|
||||||
isAmountSubtractAvailable = isAmountSubtractAvailableUseCase(
|
isAmountSubtractAvailable = isAmountSubtractAvailableUseCase(
|
||||||
userWalletId = userWalletId,
|
userWalletId = userWalletId,
|
||||||
currency = currency,
|
currency = currency,
|
||||||
isGaslessEthTx = notificationData.fee is Fee.Ethereum.TokenCurrency,
|
maybeGaslessFee = fee?.let { feeCurrencyId to fee },
|
||||||
).getOrElse { false }
|
).getOrElse { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1439,8 +1439,10 @@ internal class StakingModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun checkIfSubtractAvailable() {
|
private suspend fun checkIfSubtractAvailable() {
|
||||||
isAmountSubtractAvailable = isAmountSubtractAvailableUseCase(userWalletId, cryptoCurrencyStatus.currency)
|
isAmountSubtractAvailable = isAmountSubtractAvailableUseCase(
|
||||||
.getOrElse { false }
|
userWalletId = userWalletId,
|
||||||
|
currency = cryptoCurrencyStatus.currency,
|
||||||
|
).getOrElse { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isTopHeatupCase(): Boolean {
|
private fun isTopHeatupCase(): Boolean {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package com.tangem.features.swap.v2.impl.sendviaswap.confirm.model
|
||||||
import arrow.core.Either
|
import arrow.core.Either
|
||||||
import arrow.core.getOrElse
|
import arrow.core.getOrElse
|
||||||
import arrow.core.left
|
import arrow.core.left
|
||||||
import com.tangem.blockchain.common.transaction.Fee
|
|
||||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||||
import com.tangem.common.routing.AppRouter
|
import com.tangem.common.routing.AppRouter
|
||||||
import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer
|
import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer
|
||||||
|
|
@ -349,13 +348,14 @@ internal class SendWithSwapConfirmModel @Inject constructor(
|
||||||
|
|
||||||
private fun updateAmountSubtractAvailability() {
|
private fun updateAmountSubtractAvailability() {
|
||||||
modelScope.launch {
|
modelScope.launch {
|
||||||
val isGaslessEthTx =
|
val fee = feeUMV2?.feeExtraInfo?.transactionFeeExtended?.transactionFee?.normal
|
||||||
feeUMV2?.feeExtraInfo?.transactionFeeExtended?.transactionFee?.normal is Fee.Ethereum.TokenCurrency
|
val feeTokenId =
|
||||||
|
feeUMV2?.feeExtraInfo?.transactionFeeExtended?.feeTokenId ?: primaryCurrencyStatus.currency.id
|
||||||
isAmountSubtractAvailable =
|
isAmountSubtractAvailable =
|
||||||
isAmountSubtractAvailableUseCase(
|
isAmountSubtractAvailableUseCase(
|
||||||
userWalletId = params.userWallet.walletId,
|
userWalletId = params.userWallet.walletId,
|
||||||
currency = primaryCurrencyStatus.currency,
|
currency = primaryCurrencyStatus.currency,
|
||||||
isGaslessEthTx = isGaslessEthTx,
|
maybeGaslessFee = fee?.let { feeTokenId to fee },
|
||||||
).getOrElse { false }
|
).getOrElse { false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
# https://github.com/tangem/tangem-sdk-android/
|
# https://github.com/tangem/tangem-sdk-android/
|
||||||
# https://github.com/tangem/vico
|
# https://github.com/tangem/vico
|
||||||
|
|
||||||
tangemBlockchainSdk = "develop-1364"
|
tangemBlockchainSdk = "develop-1365"
|
||||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||||
tangemCardSdk = "develop-573"
|
tangemCardSdk = "develop-573"
|
||||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue