Updated on 2026-08-14
This commit is contained in:
commit
768666b267
5 changed files with 97 additions and 67 deletions
|
|
@ -46,11 +46,11 @@
|
|||
},
|
||||
{
|
||||
"name": "GASLESS_APPROVAL_ENABLED",
|
||||
"version": "undefined"
|
||||
"version": "5.37"
|
||||
},
|
||||
{
|
||||
"name": "TANGEM_PAY_ACCOUNTS_REFACTOR_ENABLED",
|
||||
"version": "undefined"
|
||||
"version": "5.37"
|
||||
},
|
||||
{
|
||||
"name": "DYNAMIC_ADDRESSES_ENABLED",
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
},
|
||||
{
|
||||
"name": "NEW_PROMO_BANNERS_ENABLED",
|
||||
"version": "undefined"
|
||||
"version": "5.37"
|
||||
},
|
||||
{
|
||||
"name": "VIRTUAL_ACCOUNTS_ENABLED",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.tangem.domain.markets.GetTokenMarketCryptoCurrency
|
|||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.domain.markets.TokenMarketParams
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.account.filterCryptoPortfolio
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -27,9 +28,9 @@ import com.tangem.features.feed.components.market.details.portfolio.impl.analyti
|
|||
import com.tangem.features.feed.impl.R
|
||||
import com.tangem.features.feed.model.earn.analytics.EarnAnalyticsEvent
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.*
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import java.math.BigDecimal
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -172,12 +173,11 @@ internal class AddToPortfolioPreselectedDataModel @Inject constructor(
|
|||
|
||||
val availableToAddInWallets = portfolioData.balances.mapNotNull { (walletId, balance) ->
|
||||
val wallet = balance.userWallet
|
||||
val accounts = balance.accountsBalance.accountStatuses
|
||||
val accounts = balance.accountsBalance.accountStatuses.filterCryptoPortfolio()
|
||||
|
||||
val availableToAddAccounts = accounts.mapNotNull { accountStatus ->
|
||||
val accountIndex = when (accountStatus) {
|
||||
is AccountStatus.CryptoPortfolio -> accountStatus.account.derivationIndex
|
||||
is AccountStatus.Payment -> TODO("[REDACTED_JIRA]")
|
||||
}
|
||||
|
||||
val cryptoCurrency = getTokenMarketCryptoCurrency(
|
||||
|
|
@ -224,7 +224,7 @@ internal class AddToPortfolioPreselectedDataModel @Inject constructor(
|
|||
): CryptoCurrency? {
|
||||
val accountIndex = when (val accountStatus = account.account) {
|
||||
is AccountStatus.CryptoPortfolio -> accountStatus.account.derivationIndex
|
||||
is AccountStatus.Payment -> TODO("[REDACTED_JIRA]")
|
||||
is AccountStatus.Payment -> return null
|
||||
}
|
||||
return getTokenMarketCryptoCurrency(
|
||||
userWalletId = userWallet.walletId,
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ internal class SwapAmountModel @Inject constructor(
|
|||
if (content.swapRateMode != SwapRateMode.FLOAT_ONLY) {
|
||||
ExpressRateType.Fixed
|
||||
} else {
|
||||
onSelectTokenClick()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.swap.v2.impl.amount.model.converter
|
||||
|
||||
import com.tangem.common.ui.account.AccountTitleUM
|
||||
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
||||
import com.tangem.common.ui.amountScreen.converters.AmountAccountConverter
|
||||
import com.tangem.common.ui.amountScreen.converters.AmountStateConverter
|
||||
|
|
@ -66,15 +67,20 @@ internal class SwapAmountFieldConverter(
|
|||
maxEnterAmount = maxEnterAmountConverter.convert(cryptoCurrencyStatus),
|
||||
iconStateConverter = iconStateConverter,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
accountTitleUM = AmountAccountConverter(
|
||||
isAccountsMode = isAccountsMode,
|
||||
walletTitle = walletTitle,
|
||||
prefixText = when {
|
||||
swapAmountType.isEnteringField() -> resourceReference(R.string.common_from)
|
||||
swapAmountType.isViewingField() -> resourceReference(R.string.common_to)
|
||||
else -> TextReference.Companion.EMPTY
|
||||
},
|
||||
).convert(account),
|
||||
accountTitleUM = if (swapAmountType.isViewingField()) {
|
||||
AccountTitleUM.Text(
|
||||
resourceReference(R.string.send_with_swap_recipient_get_amount, wrappedList("")),
|
||||
)
|
||||
} else {
|
||||
AmountAccountConverter(
|
||||
isAccountsMode = isAccountsMode,
|
||||
walletTitle = walletTitle,
|
||||
prefixText = when {
|
||||
swapAmountType.isEnteringField() -> resourceReference(R.string.common_from)
|
||||
else -> TextReference.Companion.EMPTY
|
||||
},
|
||||
).convert(account)
|
||||
},
|
||||
).convert(
|
||||
AmountParameters(
|
||||
title = walletTitle,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,11 @@ import com.tangem.utils.logging.TangemLogger
|
|||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.supervisorScope
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
import java.math.RoundingMode
|
||||
|
|
@ -346,63 +350,82 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
""".trimIndent(),
|
||||
)
|
||||
|
||||
return providers.map { provider ->
|
||||
val amountDecimal = toBigDecimalOrNull(amountToSwap)
|
||||
if (amountDecimal == null || amountDecimal.signum() == 0) {
|
||||
return providers.associateWith { createEmptyAmountState() }
|
||||
}
|
||||
val amount = SwapAmount(amountDecimal, fromToken.currency.decimals)
|
||||
val isBalanceWithoutFeeEnough = when (fromAccount) {
|
||||
is Account.Payment -> true
|
||||
else -> isBalanceEnough(fromToken, amount, null)
|
||||
}
|
||||
val networkId = fromToken.currency.network.backendId
|
||||
when (provider.type) {
|
||||
ExchangeProviderType.DEX, ExchangeProviderType.DEX_BRIDGE -> {
|
||||
if (isSolana(networkId)) {
|
||||
manageDexSolana(
|
||||
networkId = networkId,
|
||||
val amountDecimal = toBigDecimalOrNull(amountToSwap)
|
||||
if (amountDecimal == null || amountDecimal.signum() == 0) {
|
||||
return providers.associateWith { createEmptyAmountState() }
|
||||
}
|
||||
val amount = SwapAmount(amountDecimal, fromToken.currency.decimals)
|
||||
val isBalanceWithoutFeeEnough = when (fromAccount) {
|
||||
is Account.Payment -> true
|
||||
else -> isBalanceEnough(fromToken, amount, null)
|
||||
}
|
||||
val networkId = fromToken.currency.network.backendId
|
||||
|
||||
return supervisorScope {
|
||||
providers.map { provider ->
|
||||
async {
|
||||
try {
|
||||
when (provider.type) {
|
||||
ExchangeProviderType.DEX, ExchangeProviderType.DEX_BRIDGE -> {
|
||||
if (isSolana(networkId)) {
|
||||
manageDexSolana(
|
||||
networkId = networkId,
|
||||
fromToken = fromToken,
|
||||
fromAccount = fromAccount,
|
||||
toToken = toToken,
|
||||
toAccount = toAccount,
|
||||
provider = provider,
|
||||
txFeeSealedState = txFeeSealedState,
|
||||
amount = amount,
|
||||
isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough,
|
||||
expressOperationType = ExpressOperationType.SWAP,
|
||||
)
|
||||
} else {
|
||||
manageDex(
|
||||
networkId = networkId,
|
||||
fromToken = fromToken,
|
||||
fromAccount = fromAccount,
|
||||
toToken = toToken,
|
||||
toAccount = toAccount,
|
||||
provider = provider,
|
||||
txFeeSealedState = txFeeSealedState,
|
||||
amount = amount,
|
||||
isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough,
|
||||
expressOperationType = ExpressOperationType.SWAP,
|
||||
)
|
||||
}
|
||||
}
|
||||
ExchangeProviderType.CEX -> {
|
||||
manageCex(
|
||||
networkId = networkId,
|
||||
fromToken = fromToken,
|
||||
fromAccount = fromAccount,
|
||||
toToken = toToken,
|
||||
toAccount = toAccount,
|
||||
provider = provider,
|
||||
amount = amount,
|
||||
reduceBalanceBy = reduceBalanceBy,
|
||||
isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough,
|
||||
txFeeSealedState = txFeeSealedState,
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
if (e is CancellationException) {
|
||||
throw e
|
||||
}
|
||||
TangemLogger.e("Failed to find quote for provider: ${provider.providerId}", e)
|
||||
provider to createSwapErrorWith(
|
||||
fromToken = fromToken,
|
||||
fromAccount = fromAccount,
|
||||
toToken = toToken,
|
||||
toAccount = toAccount,
|
||||
provider = provider,
|
||||
txFeeSealedState = txFeeSealedState,
|
||||
amount = amount,
|
||||
isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough,
|
||||
expressOperationType = ExpressOperationType.SWAP,
|
||||
)
|
||||
} else {
|
||||
manageDex(
|
||||
networkId = networkId,
|
||||
fromToken = fromToken,
|
||||
fromAccount = fromAccount,
|
||||
toToken = toToken,
|
||||
toAccount = toAccount,
|
||||
provider = provider,
|
||||
txFeeSealedState = txFeeSealedState,
|
||||
amount = amount,
|
||||
isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough,
|
||||
expressOperationType = ExpressOperationType.SWAP,
|
||||
includeFeeInAmount = IncludeFeeInAmount.Excluded,
|
||||
expressDataError = ExpressDataError.UnknownError,
|
||||
)
|
||||
}
|
||||
}
|
||||
ExchangeProviderType.CEX -> {
|
||||
manageCex(
|
||||
networkId = networkId,
|
||||
fromToken = fromToken,
|
||||
fromAccount = fromAccount,
|
||||
toToken = toToken,
|
||||
toAccount = toAccount,
|
||||
provider = provider,
|
||||
amount = amount,
|
||||
reduceBalanceBy = reduceBalanceBy,
|
||||
isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough,
|
||||
txFeeSealedState = txFeeSealedState,
|
||||
)
|
||||
}
|
||||
}
|
||||
}.toMap()
|
||||
}.awaitAll().toMap()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue