diff --git a/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt index 87b23e1c2d..621ce6f4e9 100644 --- a/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt @@ -111,6 +111,14 @@ class TransactionManagerImpl( gasPremium = normalFee.gasPremium, ) } + is Fee.Sui -> { + ProxyFee.Sui( + gasLimit = BigInteger.ZERO, + fee = convertToProxyAmount(amount = normalFee.amount), + gasPrice = normalFee.gasPrice, + gasBudget = normalFee.gasBudget, + ) + } else -> { ProxyFee.Common( gasLimit = BigInteger.ZERO, diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt index 854e53526b..115737ec2b 100644 --- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt +++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt @@ -113,8 +113,21 @@ data class TxFee( val decimals: Int, val cryptoSymbol: String, val feeType: FeeType, - val gasPremium: Long?, -) + val params: Params?, +) { + + sealed class Params { + + data class Filecoin( + val gasPremium: Long, + ) : Params() + + data class Sui( + val gasBudget: Long, + val gasPrice: Long, + ) : Params() + } +} enum class FeeType { NORMAL, PRIORITY diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index b892338148..97ad3eb467 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -867,6 +867,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( } } + @Suppress("LongMethod") private fun getFeeForTransaction(fee: TxFee, blockchain: Blockchain): Fee { val feeAmountValue = fee.feeValue val feeAmount = Amount( @@ -876,50 +877,192 @@ internal class SwapInteractorImpl @AssistedInject constructor( type = AmountType.Coin, ) - return when { - blockchain.isEvm() -> { - val feeAmountWithDecimals = feeAmountValue.movePointRight(fee.decimals) - Fee.Ethereum.Legacy( - amount = feeAmount, - gasLimit = fee.gasLimit.toBigInteger(), - gasPrice = (feeAmountWithDecimals / fee.gasLimit.toBigDecimal()).toBigInteger(), - ) - } - blockchain == Blockchain.VeChain -> Fee.VeChain( + return if (blockchain.isEvm()) { + val feeAmountWithDecimals = feeAmountValue.movePointRight(fee.decimals) + + Fee.Ethereum.Legacy( amount = feeAmount, - gasPriceCoef = Fee.VeChain.getGasPriceCoef(fee.gasLimit.toLong(), fee.feeValue), - gasLimit = fee.gasLimit.toLong(), + gasLimit = fee.gasLimit.toBigInteger(), + gasPrice = (feeAmountWithDecimals / fee.gasLimit.toBigDecimal()).toBigInteger(), ) - blockchain == Blockchain.Aptos -> { - val gasUnitPrice = fee.feeValue.divide( - fee.gasLimit.toBigDecimal(), - Blockchain.Aptos.decimals(), - RoundingMode.HALF_UP, - ) - Fee.Aptos( - amount = feeAmount, - gasUnitPrice = gasUnitPrice - .movePointRight(Blockchain.Aptos.decimals()) - .toLong(), - gasLimit = fee.gasLimit.toLong(), - ) + } else { + when (blockchain) { + // region Blockchains with their own fees + Blockchain.VeChain, + Blockchain.VeChainTestnet, + -> { + Fee.VeChain( + amount = feeAmount, + gasPriceCoef = Fee.VeChain.getGasPriceCoef(fee.gasLimit.toLong(), fee.feeValue), + gasLimit = fee.gasLimit.toLong(), + ) + } + Blockchain.Aptos, + Blockchain.AptosTestnet, + -> { + val gasUnitPrice = fee.feeValue.divide( + fee.gasLimit.toBigDecimal(), + Blockchain.Aptos.decimals(), + RoundingMode.HALF_UP, + ) + + Fee.Aptos( + amount = feeAmount, + gasUnitPrice = gasUnitPrice + .movePointRight(Blockchain.Aptos.decimals()) + .toLong(), + gasLimit = fee.gasLimit.toLong(), + ) + } + Blockchain.Filecoin, + -> { + val gasUnitPrice = fee.feeValue.divide( + BigDecimal(fee.gasLimit), + Blockchain.Filecoin.decimals(), + RoundingMode.HALF_UP, + ) + val feeParams = requireNotNull(fee.params as? TxFee.Params.Filecoin) + + Fee.Filecoin( + amount = feeAmount, + gasUnitPrice = gasUnitPrice + .movePointRight(Blockchain.Filecoin.decimals()) + .toLong(), + gasLimit = fee.gasLimit.toLong(), + gasPremium = feeParams.gasPremium, + ) + } + Blockchain.Sui, + Blockchain.SuiTestnet, + -> { + val feeParams = requireNotNull(fee.params as? TxFee.Params.Sui) + + Fee.Sui( + amount = feeAmount, + gasPrice = feeParams.gasPrice, + gasBudget = feeParams.gasBudget, + ) + } + // endregion + // region Blockchains with common fees or EVM-like fees + Blockchain.Unknown, + Blockchain.Arbitrum, + Blockchain.ArbitrumTestnet, + Blockchain.Avalanche, + Blockchain.AvalancheTestnet, + Blockchain.Binance, + Blockchain.BinanceTestnet, + Blockchain.BSC, + Blockchain.BSCTestnet, + Blockchain.Bitcoin, + Blockchain.BitcoinTestnet, + Blockchain.BitcoinCash, + Blockchain.BitcoinCashTestnet, + Blockchain.Cardano, + Blockchain.Cosmos, + Blockchain.CosmosTestnet, + Blockchain.Dogecoin, + Blockchain.Ducatus, + Blockchain.Ethereum, + Blockchain.EthereumTestnet, + Blockchain.EthereumClassic, + Blockchain.EthereumClassicTestnet, + Blockchain.Fantom, + Blockchain.FantomTestnet, + Blockchain.Litecoin, + Blockchain.Near, + Blockchain.NearTestnet, + Blockchain.Polkadot, + Blockchain.PolkadotTestnet, + Blockchain.Kava, + Blockchain.KavaTestnet, + Blockchain.Kusama, + Blockchain.Polygon, + Blockchain.PolygonTestnet, + Blockchain.RSK, + Blockchain.Sei, + Blockchain.SeiTestnet, + Blockchain.Stellar, + Blockchain.StellarTestnet, + Blockchain.Solana, + Blockchain.SolanaTestnet, + Blockchain.Tezos, + Blockchain.Tron, + Blockchain.TronTestnet, + Blockchain.XRP, + Blockchain.Gnosis, + Blockchain.Dash, + Blockchain.Optimism, + Blockchain.OptimismTestnet, + Blockchain.Dischain, + Blockchain.EthereumPow, + Blockchain.EthereumPowTestnet, + Blockchain.Kaspa, + Blockchain.Telos, + Blockchain.TelosTestnet, + Blockchain.TON, + Blockchain.TONTestnet, + Blockchain.Ravencoin, + Blockchain.RavencoinTestnet, + Blockchain.TerraV1, + Blockchain.TerraV2, + Blockchain.Cronos, + Blockchain.AlephZero, + Blockchain.AlephZeroTestnet, + Blockchain.OctaSpace, + Blockchain.OctaSpaceTestnet, + Blockchain.Chia, + Blockchain.ChiaTestnet, + Blockchain.Decimal, + Blockchain.DecimalTestnet, + Blockchain.XDC, + Blockchain.XDCTestnet, + Blockchain.Playa3ull, + Blockchain.Shibarium, + Blockchain.ShibariumTestnet, + Blockchain.Algorand, + Blockchain.AlgorandTestnet, + Blockchain.Hedera, + Blockchain.HederaTestnet, + Blockchain.Aurora, + Blockchain.AuroraTestnet, + Blockchain.Areon, + Blockchain.AreonTestnet, + Blockchain.PulseChain, + Blockchain.PulseChainTestnet, + Blockchain.ZkSyncEra, + Blockchain.ZkSyncEraTestnet, + Blockchain.Nexa, + Blockchain.NexaTestnet, + Blockchain.Moonbeam, + Blockchain.MoonbeamTestnet, + Blockchain.Manta, + Blockchain.MantaTestnet, + Blockchain.PolygonZkEVM, + Blockchain.PolygonZkEVMTestnet, + Blockchain.Radiant, + Blockchain.Base, + Blockchain.BaseTestnet, + Blockchain.Moonriver, + Blockchain.MoonriverTestnet, + Blockchain.Mantle, + Blockchain.MantleTestnet, + Blockchain.Flare, + Blockchain.FlareTestnet, + Blockchain.Taraxa, + Blockchain.TaraxaTestnet, + Blockchain.Koinos, + Blockchain.KoinosTestnet, + Blockchain.Joystream, + Blockchain.Bittensor, + Blockchain.Blast, + Blockchain.BlastTestnet, + Blockchain.Cyber, + Blockchain.CyberTestnet, + Blockchain.InternetComputer, + -> Fee.Common(feeAmount) + // endregion } - blockchain == Blockchain.Filecoin -> { - val gasUnitPrice = fee.feeValue.divide( - BigDecimal(fee.gasLimit), - Blockchain.Filecoin.decimals(), - RoundingMode.HALF_UP, - ) - Fee.Filecoin( - amount = feeAmount, - gasUnitPrice = gasUnitPrice - .movePointRight(Blockchain.Filecoin.decimals()) - .toLong(), - gasLimit = fee.gasLimit.toLong(), - gasPremium = requireNotNull(fee.gasPremium), - ) - } - else -> Fee.Common(feeAmount) } } @@ -1615,7 +1758,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( decimals = minFee.fee.decimals, cryptoSymbol = minFee.fee.currencySymbol, feeType = FeeType.NORMAL, - gasPremium = (minFee as? ProxyFee.Filecoin)?.gasPremium, + params = getSwapFeeParams(minFee), ), priorityFee = TxFee( feeValue = priorityFeeValue, @@ -1628,7 +1771,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( decimals = normalFee.fee.decimals, cryptoSymbol = normalFee.fee.currencySymbol, feeType = FeeType.PRIORITY, - gasPremium = (normalFee as? ProxyFee.Filecoin)?.gasPremium, + params = getSwapFeeParams(normalFee), ), ) } @@ -1671,7 +1814,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( decimals = singleFee.fee.decimals, cryptoSymbol = singleFee.fee.currencySymbol, feeType = FeeType.NORMAL, - gasPremium = (singleFee as? ProxyFee.Filecoin)?.gasPremium, + params = getSwapFeeParams(singleFee), ), ) } @@ -1727,7 +1870,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( decimals = normalFee.amount.decimals, cryptoSymbol = normalFee.amount.currencySymbol, feeType = FeeType.NORMAL, - gasPremium = (normalFee as? Fee.Filecoin)?.gasPremium, + params = getSwapFeeParams(normalFee), ), priorityFee = TxFee( feeValue = feePriority, @@ -1740,7 +1883,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( decimals = priorityFee.amount.decimals, cryptoSymbol = priorityFee.amount.currencySymbol, feeType = FeeType.PRIORITY, - gasPremium = (priorityFee as? Fee.Filecoin)?.gasPremium, + params = getSwapFeeParams(priorityFee), ), ) } @@ -1772,13 +1915,46 @@ internal class SwapInteractorImpl @AssistedInject constructor( decimals = normal.amount.decimals, cryptoSymbol = normal.amount.currencySymbol, feeType = FeeType.NORMAL, - gasPremium = (normal as? Fee.Filecoin)?.gasPremium, + params = getSwapFeeParams(normal), ), ) } } } + private fun getSwapFeeParams(fee: Fee): TxFee.Params? = when (fee) { + is Fee.Filecoin -> TxFee.Params.Filecoin( + gasPremium = fee.gasPremium, + ) + is Fee.Sui -> TxFee.Params.Sui( + gasPrice = fee.gasPrice, + gasBudget = fee.gasBudget, + ) + is Fee.Aptos, + is Fee.Bitcoin, + is Fee.CardanoToken, + is Fee.Common, + is Fee.Ethereum.EIP1559, + is Fee.Ethereum.Legacy, + is Fee.Kaspa, + is Fee.Tron, + is Fee.VeChain, + -> null + } + + private fun getSwapFeeParams(proxyFee: ProxyFee): TxFee.Params? = when (proxyFee) { + is ProxyFee.Filecoin -> TxFee.Params.Filecoin( + gasPremium = proxyFee.gasPremium, + ) + is ProxyFee.Sui -> TxFee.Params.Sui( + gasPrice = proxyFee.gasPrice, + gasBudget = proxyFee.gasBudget, + ) + is ProxyFee.CardanoToken, + is ProxyFee.Common, + -> null + } + private fun createNativeAmountForDex(txValueAmount: String, network: Network): Amount { val nativeDecimals = Blockchain.fromNetworkId(network.backendId)?.decimals() ?: error("Blockchain not found") diff --git a/libs/crypto/src/main/java/com/tangem/lib/crypto/models/ProxyFee.kt b/libs/crypto/src/main/java/com/tangem/lib/crypto/models/ProxyFee.kt index 77b655eb1f..6cb324fcef 100644 --- a/libs/crypto/src/main/java/com/tangem/lib/crypto/models/ProxyFee.kt +++ b/libs/crypto/src/main/java/com/tangem/lib/crypto/models/ProxyFee.kt @@ -24,4 +24,11 @@ sealed interface ProxyFee { override val fee: ProxyAmount, val gasPremium: Long, ) : ProxyFee + + data class Sui( + override val gasLimit: BigInteger, + override val fee: ProxyAmount, + val gasPrice: Long, + val gasBudget: Long, + ) : ProxyFee } \ No newline at end of file