Updated on 2026-08-14
This commit is contained in:
parent
a30e44b1cf
commit
0907ba002c
23 changed files with 217 additions and 65 deletions
|
|
@ -4,6 +4,7 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.feature.swap.api.SwapFeatureToggleManager
|
||||
import com.tangem.feature.swap.domain.SwapInteractor
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.models.PendingTransaction
|
||||
|
|
@ -36,22 +37,26 @@ data class WalletData(
|
|||
return exchangeManager.availableForSell(currency)
|
||||
}
|
||||
|
||||
fun isAvailableToSwap(swapInteractor: SwapInteractor, isExchangeFeatureOn: Boolean): Boolean {
|
||||
fun isAvailableToSwap(
|
||||
swapFeatureToggleManager: SwapFeatureToggleManager,
|
||||
swapInteractor: SwapInteractor,
|
||||
): Boolean {
|
||||
val isOptimismEnabled =
|
||||
currency.blockchain.id == Blockchain.Optimism.id && swapFeatureToggleManager.isOptimismSwapEnabled
|
||||
return swapInteractor.isAvailableToSwap(currency.blockchain.toNetworkId()) &&
|
||||
currency.blockchain.id != Blockchain.Optimism.id && // disable optimism blockchain for now
|
||||
isExchangeFeatureOn &&
|
||||
isOptimismEnabled &&
|
||||
!currency.isCustomCurrency(null)
|
||||
}
|
||||
|
||||
fun getAvailableActions(
|
||||
swapInteractor: SwapInteractor,
|
||||
exchangeManager: CurrencyExchangeManager,
|
||||
isExchangeFeatureOn: Boolean,
|
||||
swapFeatureToggleManager: SwapFeatureToggleManager,
|
||||
): Set<CurrencyAction> {
|
||||
return setOfNotNull(
|
||||
if (isAvailableToBuy(exchangeManager)) CurrencyAction.Buy else null,
|
||||
if (isAvailableToSell(exchangeManager)) CurrencyAction.Sell else null,
|
||||
if (isAvailableToSwap(swapInteractor, isExchangeFeatureOn)) CurrencyAction.Swap else null,
|
||||
if (isAvailableToSwap(swapFeatureToggleManager, swapInteractor)) CurrencyAction.Swap else null,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.tangem.common.extensions.guard
|
|||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.common.TapWorkarounds.derivationStyle
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.feature.swap.api.SwapFeatureToggleManager
|
||||
import com.tangem.feature.swap.domain.SwapInteractor
|
||||
import com.tangem.sdk.extensions.dpToPx
|
||||
import com.tangem.tap.common.SnackbarHandler
|
||||
|
|
@ -75,6 +76,9 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
@Inject
|
||||
lateinit var swapInteractor: SwapInteractor
|
||||
|
||||
@Inject
|
||||
lateinit var swapFeatureToggleManager: SwapFeatureToggleManager
|
||||
|
||||
private lateinit var pendingTransactionAdapter: PendingTransactionsAdapter
|
||||
private lateinit var warningMessagesAdapter: WalletDetailWarningMessagesAdapter
|
||||
|
||||
|
|
@ -290,7 +294,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
WalletAction.DialogAction.ChooseTradeActionDialog(
|
||||
buyAllowed = selectedWallet.isAvailableToBuy(exchangeManager),
|
||||
sellAllowed = selectedWallet.isAvailableToSell(exchangeManager),
|
||||
swapAllowed = selectedWallet.isAvailableToSwap(swapInteractor, isExchangeServiceFeatureOn),
|
||||
swapAllowed = selectedWallet.isAvailableToSwap(swapFeatureToggleManager, swapInteractor),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -298,7 +302,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
val actions = selectedWallet.getAvailableActions(
|
||||
swapInteractor = swapInteractor,
|
||||
exchangeManager = exchangeManager,
|
||||
isExchangeFeatureOn = isExchangeServiceFeatureOn,
|
||||
swapFeatureToggleManager = swapFeatureToggleManager,
|
||||
)
|
||||
binding.rowButtons.updateButtonsVisibility(
|
||||
actions = actions,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import coil.size.Scale
|
|||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.ui.fragments.setStatusBarColor
|
||||
import com.tangem.core.ui.utils.OneTouchClickListener
|
||||
import com.tangem.feature.swap.api.SwapFeatureToggleManager
|
||||
import com.tangem.feature.swap.domain.SwapInteractor
|
||||
import com.tangem.tap.MainActivity
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
|
|
@ -56,6 +57,9 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
@Inject
|
||||
lateinit var swapInteractor: SwapInteractor
|
||||
|
||||
@Inject
|
||||
lateinit var swapFeatureToggleManager: SwapFeatureToggleManager
|
||||
|
||||
private lateinit var warningsAdapter: WarningMessagesAdapter
|
||||
|
||||
private val binding: FragmentWalletBinding by viewBinding(FragmentWalletBinding::bind)
|
||||
|
|
@ -170,6 +174,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
}
|
||||
|
||||
walletView.swapInteractor = swapInteractor
|
||||
walletView.swapFeatureToggleManager = swapFeatureToggleManager
|
||||
|
||||
walletView.onNewState(state)
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ class SingleWalletView : WalletView() {
|
|||
isExchangeServiceFeatureEnabled: Boolean,
|
||||
) {
|
||||
val swapInteractor = this.swapInteractor ?: return
|
||||
val swapFeatureToggleManager = this.swapFeatureToggleManager ?: return
|
||||
|
||||
val exchangeManager = store.state.globalState.exchangeManager
|
||||
binding?.rowButtons?.apply {
|
||||
|
|
@ -154,7 +155,7 @@ class SingleWalletView : WalletView() {
|
|||
val actions = walletData.getAvailableActions(
|
||||
swapInteractor = swapInteractor,
|
||||
exchangeManager = exchangeManager,
|
||||
isExchangeFeatureOn = isExchangeServiceFeatureEnabled,
|
||||
swapFeatureToggleManager = swapFeatureToggleManager,
|
||||
)
|
||||
binding?.rowButtons?.updateButtonsVisibility(
|
||||
actions = actions,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.features.wallet.ui.wallet
|
||||
|
||||
import com.tangem.feature.swap.api.SwapFeatureToggleManager
|
||||
import com.tangem.feature.swap.domain.SwapInteractor
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.features.wallet.ui.WalletFragment
|
||||
|
|
@ -8,6 +9,7 @@ import com.tangem.wallet.databinding.FragmentWalletBinding
|
|||
abstract class WalletView {
|
||||
|
||||
var swapInteractor: SwapInteractor? = null
|
||||
var swapFeatureToggleManager: SwapFeatureToggleManager? = null
|
||||
|
||||
protected var fragment: WalletFragment? = null
|
||||
protected var binding: FragmentWalletBinding? = null
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics
|
|||
import com.tangem.Message
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||
import com.tangem.blockchain.blockchains.optimism.OptimismWalletManager
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.BlockchainSdkError
|
||||
|
|
@ -155,56 +156,31 @@ class TransactionManagerImpl(
|
|||
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
|
||||
val walletManager = getActualWalletManager(blockchain, derivationPath)
|
||||
if (walletManager is EthereumWalletManager) {
|
||||
val gasLimit = getGasLimit(
|
||||
evmWalletManager = walletManager,
|
||||
if (walletManager is OptimismWalletManager) {
|
||||
return getFeeForOptimismBlockchain(
|
||||
walletManager = walletManager,
|
||||
amount = createAmount(amountToSend, currencyToSend, blockchain),
|
||||
destinationAddress = destinationAddress,
|
||||
data = data,
|
||||
)
|
||||
}
|
||||
return getFeeForEthereumBlockchain(
|
||||
walletManager = walletManager,
|
||||
blockchain = blockchain,
|
||||
amount = amountToSend,
|
||||
amountToSend = amountToSend,
|
||||
currency = currencyToSend,
|
||||
destinationAddress = destinationAddress,
|
||||
data = data,
|
||||
).let {
|
||||
if (increaseBy != null && increaseBy != 0) {
|
||||
it.multiply(increaseBy.toBigInteger()).divide(BigInteger("100"))
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
return when (val gasPrice = walletManager.getGasPrice()) {
|
||||
is Result.Success -> {
|
||||
val fee = gasLimit.multiply(gasPrice.data).toBigDecimal(
|
||||
scale = blockchain.decimals(),
|
||||
mathContext = MathContext(blockchain.decimals(), RoundingMode.HALF_EVEN),
|
||||
)
|
||||
ProxyFee(
|
||||
gasLimit = gasLimit,
|
||||
fee = ProxyAmount(
|
||||
currencySymbol = blockchain.currency,
|
||||
value = fee,
|
||||
decimals = blockchain.decimals(),
|
||||
),
|
||||
)
|
||||
}
|
||||
is Result.Failure -> {
|
||||
error(gasPrice.error.message ?: gasPrice.error.customMessage)
|
||||
}
|
||||
}
|
||||
increaseBy = increaseBy,
|
||||
)
|
||||
} else {
|
||||
val fee = (walletManager as? TransactionSender)?.getFee(
|
||||
amount = createAmount(amountToSend, currencyToSend, blockchain),
|
||||
destination = destinationAddress,
|
||||
) ?: error("Cannot cast to TransactionSender")
|
||||
when (fee) {
|
||||
is Result.Success -> {
|
||||
// for not EVM blockchains set gasLimit ZERO for now
|
||||
return ProxyFee(
|
||||
gasLimit = BigInteger.ZERO,
|
||||
fee = convertToProxyAmount(fee.data.firstOrNull() ?: error("no fee found")),
|
||||
)
|
||||
}
|
||||
is Result.Failure -> {
|
||||
error(fee.error.message ?: fee.error.customMessage)
|
||||
}
|
||||
}
|
||||
return getFeeForBlockchain(
|
||||
walletManager = walletManager,
|
||||
amountToSend = amountToSend,
|
||||
currency = currencyToSend,
|
||||
blockchain = blockchain,
|
||||
destinationAddress = destinationAddress,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -217,6 +193,100 @@ class TransactionManagerImpl(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun getFeeForBlockchain(
|
||||
walletManager: WalletManager,
|
||||
amountToSend: BigDecimal,
|
||||
currency: Currency,
|
||||
blockchain: Blockchain,
|
||||
destinationAddress: String,
|
||||
): ProxyFee {
|
||||
val fee = (walletManager as? TransactionSender)?.getFee(
|
||||
amount = createAmount(amountToSend, currency, blockchain),
|
||||
destination = destinationAddress,
|
||||
) ?: error("Cannot cast to TransactionSender")
|
||||
return when (fee) {
|
||||
is Result.Success -> {
|
||||
// for not EVM blockchains set gasLimit ZERO for now
|
||||
ProxyFee(
|
||||
gasLimit = BigInteger.ZERO,
|
||||
fee = convertToProxyAmount(fee.data.firstOrNull() ?: error("no fee found")),
|
||||
)
|
||||
}
|
||||
is Result.Failure -> {
|
||||
error(fee.error.message ?: fee.error.customMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
private suspend fun getFeeForEthereumBlockchain(
|
||||
walletManager: EthereumWalletManager,
|
||||
blockchain: Blockchain,
|
||||
amountToSend: BigDecimal,
|
||||
currency: Currency,
|
||||
destinationAddress: String,
|
||||
data: String?,
|
||||
increaseBy: Int?,
|
||||
): ProxyFee {
|
||||
val gasLimit = getGasLimit(
|
||||
evmWalletManager = walletManager,
|
||||
blockchain = blockchain,
|
||||
amount = amountToSend,
|
||||
currency = currency,
|
||||
destinationAddress = destinationAddress,
|
||||
data = data,
|
||||
).let {
|
||||
if (increaseBy != null && increaseBy != 0) {
|
||||
it.multiply(increaseBy.toBigInteger()).divide(BigInteger("100"))
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
return when (val gasPrice = walletManager.getGasPrice()) {
|
||||
is Result.Success -> {
|
||||
val fee = gasLimit.multiply(gasPrice.data).toBigDecimal(
|
||||
scale = blockchain.decimals(),
|
||||
mathContext = MathContext(blockchain.decimals(), RoundingMode.HALF_EVEN),
|
||||
)
|
||||
ProxyFee(
|
||||
gasLimit = gasLimit,
|
||||
fee = ProxyAmount(
|
||||
currencySymbol = blockchain.currency,
|
||||
value = fee,
|
||||
decimals = blockchain.decimals(),
|
||||
),
|
||||
)
|
||||
}
|
||||
is Result.Failure -> {
|
||||
error(gasPrice.error.message ?: gasPrice.error.customMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getFeeForOptimismBlockchain(
|
||||
walletManager: OptimismWalletManager,
|
||||
amount: Amount,
|
||||
destinationAddress: String,
|
||||
data: String?,
|
||||
): ProxyFee {
|
||||
val fee = if (data.isNullOrEmpty()) {
|
||||
walletManager.getFee(amount, destinationAddress)
|
||||
} else {
|
||||
walletManager.getFee(amount, destinationAddress, data)
|
||||
}
|
||||
when (fee) {
|
||||
is Result.Success -> {
|
||||
return ProxyFee(
|
||||
gasLimit = walletManager.gasLimit ?: BigInteger.ZERO,
|
||||
fee = convertToProxyAmount(fee.data.lastOrNull() ?: error("no fee found")),
|
||||
)
|
||||
}
|
||||
is Result.Failure -> {
|
||||
error(fee.error.message ?: fee.error.customMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
private suspend fun getGasLimit(
|
||||
evmWalletManager: EthereumWalletManager,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue