Updated on 2026-08-14
This commit is contained in:
commit
59b02e2e7a
24 changed files with 224 additions and 186 deletions
|
|
@ -125,7 +125,7 @@ class AmountStateConverterV2(
|
|||
resourceReference(R.string.common_crypto_fiat_format, wrappedList(crypto, fiat))
|
||||
},
|
||||
tokenName = stringReference(cryptoCurrencyStatus.currency.name),
|
||||
tokenIconState = iconStateConverter.convert(cryptoCurrencyStatus),
|
||||
tokenIconState = iconStateConverter.convert(cryptoCurrencyStatus.currency),
|
||||
amountTextField = amountFieldConverter.convert(value.value),
|
||||
isPrimaryButtonEnabled = false,
|
||||
appCurrency = appCurrency,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ dependencies {
|
|||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.legacy)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.quotes)
|
||||
implementation(projects.domain.networks)
|
||||
implementation(projects.domain.staking.models)
|
||||
implementation(projects.domain.staking)
|
||||
|
||||
/** Tangem SDK */
|
||||
implementation(tangemDeps.blockchain) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.data.swap
|
||||
|
||||
import arrow.core.right
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.data.common.api.safeApiCall
|
||||
import com.tangem.data.swap.converter.SwapDataConverter
|
||||
|
|
@ -21,12 +22,15 @@ import com.tangem.domain.express.models.ExpressProvider
|
|||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.domain.express.models.ExpressRateType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.NetworkStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
|
||||
import com.tangem.domain.swap.SwapRepositoryV2
|
||||
import com.tangem.domain.swap.models.*
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
||||
import com.tangem.domain.tokens.utils.CurrencyStatusProxyCreator
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.async
|
||||
|
|
@ -44,8 +48,10 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
|
|||
private val expressRepository: ExpressRepository,
|
||||
private val coroutineDispatcher: CoroutineDispatcherProvider,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val currencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
private val dataSignatureVerifier: DataSignatureVerifier,
|
||||
private val singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
|
||||
private val singleQuoteStatusFetcher: SingleQuoteStatusFetcher,
|
||||
private val currencyStatusProxyCreator: CurrencyStatusProxyCreator,
|
||||
@NetworkMoshi moshi: Moshi,
|
||||
) : SwapRepositoryV2 {
|
||||
|
||||
|
|
@ -102,10 +108,11 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
|
|||
}.awaitAll().filterNotNull()
|
||||
}
|
||||
|
||||
override suspend fun getPairsOnly(
|
||||
override suspend fun getSupportedPairs(
|
||||
userWallet: UserWallet,
|
||||
initialCurrency: CryptoCurrency,
|
||||
cryptoCurrencyList: List<CryptoCurrency>,
|
||||
filterProviderTypes: List<ExpressProviderType>,
|
||||
): List<SwapPairModel> = withContext(coroutineDispatcher.io) {
|
||||
val allPairs = getPairsInternal(
|
||||
userWallet = userWallet,
|
||||
|
|
@ -113,6 +120,12 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
|
|||
cryptoCurrencyList = cryptoCurrencyList,
|
||||
)
|
||||
|
||||
val providers = expressRepository.getProviders(
|
||||
userWallet = userWallet,
|
||||
filterProviderTypes = filterProviderTypes,
|
||||
)
|
||||
val mappedProviders = providers.associateBy(ExpressProvider::providerId)
|
||||
|
||||
allPairs.map { pair ->
|
||||
async {
|
||||
val statusFromDeferred = async {
|
||||
|
|
@ -130,11 +143,20 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
createPairModelOnly(
|
||||
currencyFrom = statusFromDeferred.await(),
|
||||
currencyTo = statusToDeferred.await(),
|
||||
userWalletId = userWallet.walletId,
|
||||
)
|
||||
val currencyStatusFrom = createSendWithSwapCryptoCurrencyStatus(statusFromDeferred.await())
|
||||
val currencyStatusTo = createSendWithSwapCryptoCurrencyStatus(statusToDeferred.await())
|
||||
|
||||
if (currencyStatusFrom != null && currencyStatusTo != null) {
|
||||
SwapPairModel(
|
||||
from = currencyStatusFrom,
|
||||
to = currencyStatusTo,
|
||||
providers = pair.providers.mapNotNull {
|
||||
mappedProviders[it.providerId]
|
||||
},
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}.awaitAll().filterNotNull()
|
||||
}
|
||||
|
|
@ -176,15 +198,14 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
|
|||
override suspend fun getSwapData(
|
||||
userWallet: UserWallet,
|
||||
fromCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toCryptoCurrency: CryptoCurrency,
|
||||
fromAmount: String,
|
||||
toAddress: String?,
|
||||
toAddress: String,
|
||||
expressProvider: ExpressProvider,
|
||||
rateType: ExpressRateType,
|
||||
): SwapDataModel = withContext(coroutineDispatcher.io) {
|
||||
val requestId = UUID.randomUUID().toString()
|
||||
val fromCryptoCurrency = fromCryptoCurrencyStatus.currency
|
||||
val toCryptoCurrency = toCryptoCurrencyStatus.currency
|
||||
|
||||
val refundData = when (expressProvider.type) {
|
||||
ExpressProviderType.CEX,
|
||||
|
|
@ -203,7 +224,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
|
|||
fromNetwork = fromCryptoCurrency.network.backendId,
|
||||
toNetwork = toCryptoCurrency.network.backendId,
|
||||
fromAddress = fromCryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value.orEmpty(),
|
||||
toAddress = toAddress ?: toCryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value.orEmpty(),
|
||||
toAddress = toAddress,
|
||||
fromDecimals = fromCryptoCurrency.decimals,
|
||||
toDecimals = toCryptoCurrency.decimals,
|
||||
fromAmount = fromAmount,
|
||||
|
|
@ -329,33 +350,38 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
|
|||
},
|
||||
)
|
||||
|
||||
private suspend fun createPairModelOnly(
|
||||
currencyFrom: CryptoCurrency?,
|
||||
currencyTo: CryptoCurrency?,
|
||||
userWalletId: UserWalletId,
|
||||
): SwapPairModel? {
|
||||
return if (currencyFrom != null && currencyTo != null) {
|
||||
val statusFrom = currencyStatusOperations.getCurrencyStatusSync(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencyId = currencyFrom.id,
|
||||
).getOrNull()
|
||||
val statusTo = currencyStatusOperations.getCurrencyStatusSync(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencyId = currencyTo.id,
|
||||
).getOrNull()
|
||||
/**
|
||||
* Send with swap specific currency status creation
|
||||
* We support sending to any available to swap and supported network
|
||||
* It is possible that currency not added to wallet so we ignore network status
|
||||
*/
|
||||
private suspend fun createSendWithSwapCryptoCurrencyStatus(cryptoCurrency: CryptoCurrency?): CryptoCurrencyStatus? {
|
||||
val rawCurrencyId = cryptoCurrency?.id?.rawCurrencyId ?: return null
|
||||
|
||||
if (statusFrom != null && statusTo != null) {
|
||||
SwapPairModel(
|
||||
from = statusFrom,
|
||||
to = statusTo,
|
||||
providers = emptyList(),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
null
|
||||
val quote = singleQuoteStatusSupplier.getSyncOrNull(
|
||||
params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawCurrencyId),
|
||||
)?.right()
|
||||
|
||||
if (quote == null) {
|
||||
singleQuoteStatusFetcher.invoke(
|
||||
params = SingleQuoteStatusFetcher.Params(
|
||||
rawCurrencyId = rawCurrencyId,
|
||||
appCurrencyId = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return currencyStatusProxyCreator.createCurrencyStatus(
|
||||
currency = cryptoCurrency,
|
||||
maybeQuoteStatus = quote ?: singleQuoteStatusSupplier.getSyncOrNull(
|
||||
params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawCurrencyId),
|
||||
).right(),
|
||||
maybeNetworkStatus = NetworkStatus(
|
||||
network = cryptoCurrency.network,
|
||||
value = NetworkStatus.MissedDerivation, // Caution!!! Do not change this status
|
||||
).right(),
|
||||
maybeYieldBalance = null,
|
||||
).getOrNull()
|
||||
}
|
||||
|
||||
private fun parseTxDetails(txDetailsJson: String): TxDetails? {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,13 @@ import com.tangem.datasource.crypto.DataSignatureVerifier
|
|||
import com.tangem.datasource.di.NetworkMoshi
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.domain.express.ExpressRepository
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.swap.SwapErrorResolver
|
||||
import com.tangem.domain.swap.SwapRepositoryV2
|
||||
import com.tangem.domain.swap.SwapTransactionRepository
|
||||
import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
||||
import com.tangem.domain.tokens.utils.CurrencyStatusProxyCreator
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -43,8 +46,10 @@ internal object SwapDataModule {
|
|||
expressRepository: ExpressRepository,
|
||||
coroutineDispatcher: CoroutineDispatcherProvider,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
currencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
dataSignatureVerifier: DataSignatureVerifier,
|
||||
singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
|
||||
singleQuoteStatusFetcher: SingleQuoteStatusFetcher,
|
||||
stakingRepository: StakingRepository,
|
||||
@NetworkMoshi moshi: Moshi,
|
||||
): SwapRepositoryV2 {
|
||||
return DefaultSwapRepositoryV2(
|
||||
|
|
@ -52,9 +57,11 @@ internal object SwapDataModule {
|
|||
expressRepository = expressRepository,
|
||||
coroutineDispatcher = coroutineDispatcher,
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
currencyStatusOperations = currencyStatusOperations,
|
||||
dataSignatureVerifier = dataSignatureVerifier,
|
||||
moshi = moshi,
|
||||
singleQuoteStatusSupplier = singleQuoteStatusSupplier,
|
||||
singleQuoteStatusFetcher = singleQuoteStatusFetcher,
|
||||
currencyStatusProxyCreator = CurrencyStatusProxyCreator(stakingRepository),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -216,7 +216,9 @@ sealed class CryptoCurrency {
|
|||
private const val DERIVATION_PATH_DELIMITER = '\u2192' // →
|
||||
|
||||
private const val ID_PARTS_COUNT = 3
|
||||
|
||||
const val MAIN_NETWORK_TYPE_NAME = "MAIN"
|
||||
const val MAIN_NETWORK_L2_TYPE_NAME = "MAIN L2"
|
||||
|
||||
/**
|
||||
* Creates an [ID] from a string [value].
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ data class SwapCurrencies(
|
|||
/**
|
||||
* Return swap group depending on [swapDirection]
|
||||
*/
|
||||
fun SwapCurrencies.getGroupWithReverse(swapDirection: SwapDirection): SwapCurrenciesGroup {
|
||||
fun SwapCurrencies.getGroupWithDirection(swapDirection: SwapDirection): SwapCurrenciesGroup {
|
||||
return when (swapDirection) {
|
||||
SwapDirection.Reverse -> fromGroup
|
||||
SwapDirection.Direct -> toGroup
|
||||
SwapDirection.Reverse -> toGroup
|
||||
SwapDirection.Direct -> fromGroup
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import com.tangem.domain.express.models.ExpressProvider
|
|||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.domain.express.models.ExpressRateType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.swap.models.SwapDataModel
|
||||
import com.tangem.domain.swap.models.SwapPairModel
|
||||
import com.tangem.domain.swap.models.SwapQuoteModel
|
||||
import com.tangem.domain.swap.models.SwapStatusModel
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -21,10 +21,10 @@ interface SwapRepositoryV2 {
|
|||
/**
|
||||
* Express swap pairs, both direct and reversed
|
||||
*
|
||||
* @param userWallet selected user wallet
|
||||
* @param initialCurrency currency being swapped (either to or from)
|
||||
* @param cryptoCurrencyStatusList list of currencies might be swapped
|
||||
* @param filterProviderTypes filters only specified provider types, if empty returns providers as is
|
||||
* @param userWallet selected user wallet
|
||||
* @param initialCurrency currency being swapped (either to or from)
|
||||
* @param cryptoCurrencyStatusList list of currencies might be swapped
|
||||
* @param filterProviderTypes filters only specified provider types, if empty returns providers as is
|
||||
*/
|
||||
suspend fun getPairs(
|
||||
userWallet: UserWallet,
|
||||
|
|
@ -33,22 +33,27 @@ interface SwapRepositoryV2 {
|
|||
filterProviderTypes: List<ExpressProviderType>,
|
||||
): List<SwapPairModel>
|
||||
|
||||
/** Express getPairs request variant without providers request */
|
||||
suspend fun getPairsOnly(
|
||||
/**
|
||||
* Express getPairs request variant for all pairs of crypto currency supported by Tangem Wallet
|
||||
* Therefore return list may and will include currencies not added to user wallet.
|
||||
* Used in [Send With Swap]
|
||||
*/
|
||||
suspend fun getSupportedPairs(
|
||||
userWallet: UserWallet,
|
||||
initialCurrency: CryptoCurrency,
|
||||
cryptoCurrencyList: List<CryptoCurrency>,
|
||||
filterProviderTypes: List<ExpressProviderType>,
|
||||
): List<SwapPairModel>
|
||||
|
||||
/**
|
||||
* Returns swap quotes on selected pair
|
||||
*
|
||||
* @param userWallet selected user wallet
|
||||
* @param fromCryptoCurrency currency being swapped from
|
||||
* @param toCryptoCurrency currency being swapped to
|
||||
* @param fromAmount swap amount
|
||||
* @param provider selected express provider
|
||||
* @param rateType rate type
|
||||
* @param userWallet selected user wallet
|
||||
* @param fromCryptoCurrency currency being swapped from
|
||||
* @param toCryptoCurrency currency being swapped to
|
||||
* @param fromAmount swap amount
|
||||
* @param provider selected express provider
|
||||
* @param rateType rate type
|
||||
*/
|
||||
suspend fun getSwapQuote(
|
||||
userWallet: UserWallet,
|
||||
|
|
@ -62,20 +67,20 @@ interface SwapRepositoryV2 {
|
|||
/**
|
||||
* Returns swap data [SwapDataModel] ready to sign and send on selected quote
|
||||
*
|
||||
* @param userWallet selected user wallet
|
||||
* @param fromCryptoCurrencyStatus currency status being swapped from
|
||||
* @param toCryptoCurrencyStatus currency status being swapped to
|
||||
* @param fromAmount swap amount
|
||||
* @param toAddress destination address (optional, if null send to self)
|
||||
* @param expressProvider selected swap provider
|
||||
* @param rateType selected provider rate type
|
||||
* @param userWallet selected user wallet
|
||||
* @param fromCryptoCurrencyStatus currency status being swapped from
|
||||
* @param toCryptoCurrency currency being swapped to
|
||||
* @param fromAmount swap amount
|
||||
* @param toAddress destination address
|
||||
* @param expressProvider selected swap provider
|
||||
* @param rateType selected provider rate type
|
||||
*/
|
||||
suspend fun getSwapData(
|
||||
userWallet: UserWallet,
|
||||
fromCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toCryptoCurrency: CryptoCurrency,
|
||||
fromAmount: String,
|
||||
toAddress: String?,
|
||||
toAddress: String,
|
||||
expressProvider: ExpressProvider,
|
||||
rateType: ExpressRateType,
|
||||
): SwapDataModel
|
||||
|
|
@ -83,12 +88,12 @@ interface SwapRepositoryV2 {
|
|||
/**
|
||||
* Send ExpressApi info that swap transaction occurred
|
||||
*
|
||||
* @param userWallet selected user wallet
|
||||
* @param fromCryptoCurrencyStatus currency status being swapped from
|
||||
* @param toAddress swap destination address
|
||||
* @param txId transaction id in ExpressApi
|
||||
* @param txHash transaction hash in blockchain
|
||||
* @param txExtraId extra transaction id in ExpressApi
|
||||
* @param userWallet selected user wallet
|
||||
* @param fromCryptoCurrencyStatus currency status being swapped from
|
||||
* @param toAddress swap destination address
|
||||
* @param txId transaction id in ExpressApi
|
||||
* @param txHash transaction hash in blockchain
|
||||
* @param txExtraId extra transaction id in ExpressApi
|
||||
*/
|
||||
suspend fun swapTransactionSent(
|
||||
userWallet: UserWallet,
|
||||
|
|
@ -102,8 +107,8 @@ interface SwapRepositoryV2 {
|
|||
/**
|
||||
* Returns status [SwapStatusModel] on active swap
|
||||
*
|
||||
* @param userWallet selected user wallet
|
||||
* @param txId transaction id in ExpressApi
|
||||
* @param userWallet selected user wallet
|
||||
* @param txId transaction id in ExpressApi
|
||||
*/
|
||||
suspend fun getExchangeStatus(userWallet: UserWallet, txId: String): SwapStatusModel
|
||||
}
|
||||
|
|
@ -4,11 +4,12 @@ import arrow.core.Either
|
|||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.express.models.ExpressRateType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.swap.SwapErrorResolver
|
||||
import com.tangem.domain.swap.SwapRepositoryV2
|
||||
import com.tangem.domain.swap.models.SwapDataModel
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
class GetSwapDataUseCase(
|
||||
|
|
@ -20,8 +21,8 @@ class GetSwapDataUseCase(
|
|||
userWallet: UserWallet,
|
||||
fromCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
fromAmount: String,
|
||||
toCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toAddress: String?,
|
||||
toCryptoCurrency: CryptoCurrency,
|
||||
toAddress: String,
|
||||
expressProvider: ExpressProvider,
|
||||
rateType: ExpressRateType,
|
||||
): Either<ExpressError, SwapDataModel> = Either.catch {
|
||||
|
|
@ -29,7 +30,7 @@ class GetSwapDataUseCase(
|
|||
userWallet = userWallet,
|
||||
fromCryptoCurrencyStatus = fromCryptoCurrencyStatus,
|
||||
fromAmount = fromAmount,
|
||||
toCryptoCurrencyStatus = toCryptoCurrencyStatus,
|
||||
toCryptoCurrency = toCryptoCurrency,
|
||||
toAddress = toAddress,
|
||||
expressProvider = expressProvider,
|
||||
rateType = rateType,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.domain.swap.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.swap.SwapErrorResolver
|
||||
import com.tangem.domain.swap.SwapRepositoryV2
|
||||
import com.tangem.domain.swap.models.SwapCryptoCurrency
|
||||
|
|
@ -9,7 +11,6 @@ import com.tangem.domain.swap.models.SwapCurrencies
|
|||
import com.tangem.domain.swap.models.SwapCurrenciesGroup
|
||||
import com.tangem.domain.swap.models.SwapPairModel
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
||||
/**
|
||||
* Returns pais
|
||||
|
|
@ -23,11 +24,13 @@ class GetSwapSupportedPairsUseCase(
|
|||
userWallet: UserWallet,
|
||||
initialCurrency: CryptoCurrency,
|
||||
cryptoCurrencyList: List<CryptoCurrency>,
|
||||
filterProviderTypes: List<ExpressProviderType>,
|
||||
) = Either.catch {
|
||||
val pairs = swapRepositoryV2.getPairsOnly(
|
||||
val pairs = swapRepositoryV2.getSupportedPairs(
|
||||
userWallet = userWallet,
|
||||
initialCurrency = initialCurrency,
|
||||
cryptoCurrencyList = cryptoCurrencyList,
|
||||
filterProviderTypes = filterProviderTypes,
|
||||
)
|
||||
|
||||
val filteredOutInitial = cryptoCurrencyList.filterNot { it.id == initialCurrency.id }
|
||||
|
|
@ -74,7 +77,7 @@ class GetSwapSupportedPairsUseCase(
|
|||
SwapCryptoCurrency(
|
||||
CryptoCurrencyStatus(
|
||||
currency = currency,
|
||||
value = CryptoCurrencyStatus.Loading, // todo select token unavailable
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
),
|
||||
emptyList(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
package com.tangem.domain.swap.usecase
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.swap.SwapTransactionRepository
|
||||
import com.tangem.domain.swap.models.SwapCurrencies
|
||||
import com.tangem.domain.swap.models.SwapCurrenciesGroup
|
||||
import com.tangem.domain.swap.models.SwapDirection
|
||||
import com.tangem.domain.swap.models.getGroupWithReverse
|
||||
import com.tangem.domain.swap.models.getGroupWithDirection
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.utils.extensions.orZero
|
||||
|
||||
/**
|
||||
|
|
@ -31,7 +31,7 @@ class SelectInitialPairUseCase(
|
|||
swapCurrencies: SwapCurrencies,
|
||||
swapDirection: SwapDirection,
|
||||
): CryptoCurrencyStatus? {
|
||||
val swapCurrenciesGroup = swapCurrencies.getGroupWithReverse(swapDirection)
|
||||
val swapCurrenciesGroup = swapCurrencies.getGroupWithDirection(swapDirection)
|
||||
return tryToGetAlreadySelectedCurrency(secondaryCryptoCurrency, swapCurrenciesGroup)
|
||||
?: tryGetFromCache(userWallet, primaryCryptoCurrency, swapCurrenciesGroup)
|
||||
?: tryGetWithMaxAmount(swapCurrenciesGroup)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ dependencies {
|
|||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.swap.models)
|
||||
|
||||
/* AndroidX */
|
||||
implementation(deps.androidx.activity.compose)
|
||||
|
|
|
|||
|
|
@ -62,11 +62,11 @@ internal class DefaultChooseManagedTokensComponent @AssistedInject constructor(
|
|||
initialCurrency = config.initialCurrency,
|
||||
token = config.token,
|
||||
onDismiss = model.bottomSheetNavigation::dismiss,
|
||||
onResult = {
|
||||
onResult = { swapCurrencies, cryptoCurrency ->
|
||||
componentScope.launch {
|
||||
swapChooseTokenNetworkTrigger.trigger(it)
|
||||
swapChooseTokenNetworkTrigger.trigger(swapCurrencies, cryptoCurrency)
|
||||
router.pop()
|
||||
}
|
||||
router.pop()
|
||||
},
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
|||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.swap.models.SwapCurrencies
|
||||
|
||||
interface SwapChooseTokenNetworkComponent : ComposableBottomSheetComponent {
|
||||
|
||||
|
|
@ -13,7 +14,7 @@ interface SwapChooseTokenNetworkComponent : ComposableBottomSheetComponent {
|
|||
val initialCurrency: CryptoCurrency,
|
||||
val token: ManagedCryptoCurrency.Token,
|
||||
val onDismiss: () -> Unit,
|
||||
val onResult: (CryptoCurrency) -> Unit,
|
||||
val onResult: (SwapCurrencies, CryptoCurrency) -> Unit,
|
||||
)
|
||||
|
||||
interface Factory : ComponentFactory<Params, SwapChooseTokenNetworkComponent>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.swap.v2.api.choosetoken
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapCurrencies
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
|
||||
/**
|
||||
|
|
@ -8,12 +9,12 @@ import kotlinx.coroutines.flow.SharedFlow
|
|||
*/
|
||||
interface SwapChooseTokenNetworkTrigger {
|
||||
|
||||
suspend fun trigger(cryptoCurrency: CryptoCurrency)
|
||||
suspend fun trigger(swapCurrencies: SwapCurrencies, cryptoCurrency: CryptoCurrency)
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to swap token selection
|
||||
*/
|
||||
interface SwapChooseTokenNetworkListener {
|
||||
val swapChooseTokenNetworkResultFlow: SharedFlow<CryptoCurrency>
|
||||
val swapChooseTokenNetworkResultFlow: SharedFlow<Pair<SwapCurrencies, CryptoCurrency>>
|
||||
}
|
||||
|
|
@ -17,14 +17,14 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapCurrencies
|
||||
import com.tangem.domain.swap.models.SwapDirection
|
||||
import com.tangem.domain.swap.models.SwapDirection.Companion.withSwapDirection
|
||||
import com.tangem.domain.swap.models.SwapQuoteModel
|
||||
import com.tangem.domain.swap.usecase.GetSwapPairsUseCase
|
||||
import com.tangem.domain.swap.models.getGroupWithDirection
|
||||
import com.tangem.domain.swap.usecase.GetSwapQuoteUseCase
|
||||
import com.tangem.domain.swap.usecase.SelectInitialPairUseCase
|
||||
import com.tangem.domain.tokens.GetMinimumTransactionAmountSyncUseCase
|
||||
import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.transaction.usecase.GetAllowanceUseCase
|
||||
import com.tangem.features.send.v2.api.subcomponents.feeSelector.FeeSelectorReloadTrigger
|
||||
|
|
@ -60,8 +60,6 @@ import com.tangem.utils.transformer.update as transformerUpdate
|
|||
internal class SwapAmountModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val getSwapPairsUseCase: GetSwapPairsUseCase,
|
||||
private val getMultiCryptoCurrencyStatusUseCase: GetMultiCryptoCurrencyStatusUseCase,
|
||||
private val getMinimumTransactionAmountSyncUseCase: GetMinimumTransactionAmountSyncUseCase,
|
||||
private val selectInitialPairUseCase: SelectInitialPairUseCase,
|
||||
private val getSwapQuoteUseCase: GetSwapQuoteUseCase,
|
||||
|
|
@ -304,10 +302,10 @@ internal class SwapAmountModel @Inject constructor(
|
|||
|
||||
private fun observeChooseSelectToken() {
|
||||
swapChooseTokenNetworkListener.swapChooseTokenNetworkResultFlow
|
||||
.onEach { currency ->
|
||||
.onEach { (swapCurrencies, currency) ->
|
||||
uiState.update { amountUM ->
|
||||
if (amountUM is SwapAmountUM.Content) {
|
||||
initPairs(currency)
|
||||
initPairs(swapCurrencies, currency)
|
||||
amountUM.copy(
|
||||
isPrimaryButtonEnabled = false,
|
||||
secondaryAmount = SwapAmountFieldUM.Loading(
|
||||
|
|
@ -322,65 +320,42 @@ internal class SwapAmountModel @Inject constructor(
|
|||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun initPairs(secondaryCryptoCurrency: CryptoCurrency?) {
|
||||
private fun initPairs(swapCurrencies: SwapCurrencies, secondaryCryptoCurrency: CryptoCurrency?) {
|
||||
modelScope.launch {
|
||||
val cryptoCurrencyStatusList = getMultiCryptoCurrencyStatusUseCase
|
||||
.invokeMultiWalletSync(userWallet.walletId)
|
||||
.getOrElse { emptyList() }
|
||||
|
||||
val cryptoCurrencyStatusListExceptPrimary = cryptoCurrencyStatusList.filter {
|
||||
val statusFilter = it.value is CryptoCurrencyStatus.Loaded || it.value is CryptoCurrencyStatus.NoAccount
|
||||
val notCustomTokenFilter = !it.currency.isCustom
|
||||
statusFilter && notCustomTokenFilter
|
||||
}
|
||||
|
||||
getSwapPairsUseCase(
|
||||
val secondaryStatus = selectInitialPairUseCase(
|
||||
primaryCryptoCurrency = primaryCryptoCurrency,
|
||||
secondaryCryptoCurrency = secondaryCryptoCurrency,
|
||||
userWallet = userWallet,
|
||||
initialCurrency = primaryCryptoCurrency,
|
||||
cryptoCurrencyStatusList = cryptoCurrencyStatusListExceptPrimary,
|
||||
filterProviderTypes = params.filterProviderTypes,
|
||||
).fold(
|
||||
ifRight = { swapCurrencies ->
|
||||
val secondaryStatus = selectInitialPairUseCase(
|
||||
primaryCryptoCurrency = primaryCryptoCurrency,
|
||||
secondaryCryptoCurrency = secondaryCryptoCurrency,
|
||||
swapCurrencies = swapCurrencies,
|
||||
swapDirection = params.swapDirection,
|
||||
)
|
||||
|
||||
val primaryStatus = (uiState.value as? SwapAmountUM.Content)?.primaryCryptoCurrencyStatus
|
||||
if (secondaryStatus != null && primaryStatus != null) {
|
||||
initCurrencies(primaryStatus, secondaryStatus)
|
||||
uiState.transformerUpdate(
|
||||
SwapAmountSecondaryReadyStateTransformer(
|
||||
userWallet = userWallet,
|
||||
swapCurrencies = swapCurrencies,
|
||||
swapDirection = params.swapDirection,
|
||||
)
|
||||
|
||||
val primaryStatus = (uiState.value as? SwapAmountUM.Content)?.primaryCryptoCurrencyStatus
|
||||
if (secondaryStatus != null && primaryStatus != null) {
|
||||
initCurrencies(primaryStatus, secondaryStatus)
|
||||
uiState.transformerUpdate(
|
||||
SwapAmountSecondaryReadyStateTransformer(
|
||||
userWallet = userWallet,
|
||||
swapCurrencies = swapCurrencies,
|
||||
primaryCryptoCurrencyStatus = primaryStatus,
|
||||
secondaryCryptoCurrencyStatus = secondaryStatus,
|
||||
appCurrency = appCurrency,
|
||||
swapDirection = swapDirection,
|
||||
clickIntents = this@SwapAmountModel,
|
||||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||
),
|
||||
)
|
||||
loadQuotes()
|
||||
} else {
|
||||
Timber.e(
|
||||
"""
|
||||
Invalid cryptocurrencies status:
|
||||
| Primary -> $primaryStatus
|
||||
| Secondary -> $secondaryStatus
|
||||
""".trimIndent(),
|
||||
)
|
||||
showErrorAlert(errorMessage = null)
|
||||
}
|
||||
},
|
||||
ifLeft = { error ->
|
||||
Timber.e(error)
|
||||
showErrorAlert(errorMessage = error.message)
|
||||
},
|
||||
)
|
||||
primaryCryptoCurrencyStatus = primaryStatus,
|
||||
secondaryCryptoCurrencyStatus = secondaryStatus,
|
||||
appCurrency = appCurrency,
|
||||
swapDirection = swapDirection,
|
||||
clickIntents = this@SwapAmountModel,
|
||||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||
),
|
||||
)
|
||||
loadQuotes()
|
||||
} else {
|
||||
Timber.e(
|
||||
"""
|
||||
Invalid cryptocurrencies status:
|
||||
| Primary -> $primaryStatus
|
||||
| Secondary -> $secondaryStatus
|
||||
""".trimIndent(),
|
||||
)
|
||||
showErrorAlert(errorMessage = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -428,15 +403,12 @@ internal class SwapAmountModel @Inject constructor(
|
|||
|
||||
val fromAmountValue = fromAmount?.amountTextField?.cryptoAmount?.value ?: return
|
||||
|
||||
val swapGroups = when (state.swapDirection) {
|
||||
SwapDirection.Direct -> state.swapCurrencies.toGroup.available
|
||||
SwapDirection.Reverse -> state.swapCurrencies.fromGroup.available
|
||||
}
|
||||
val swapGroups = state.swapCurrencies.getGroupWithDirection(state.swapDirection)
|
||||
|
||||
uiState.transformerUpdate(SwapQuoteLoadingStateTransformer)
|
||||
|
||||
modelScope.launch {
|
||||
val quotes = swapGroups.filter {
|
||||
val quotes = swapGroups.available.filter {
|
||||
it.currencyStatus.currency.id == toCryptoCurrency.id
|
||||
}.flatMap {
|
||||
it.providers
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ import com.tangem.core.ui.extensions.*
|
|||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.swap.models.SwapDirection
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.features.swap.v2.impl.R
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountFieldUM
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountType
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.swap.v2.impl.choosetoken.fromSupported
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapCurrencies
|
||||
import com.tangem.features.swap.v2.api.choosetoken.SwapChooseTokenNetworkListener
|
||||
import com.tangem.features.swap.v2.api.choosetoken.SwapChooseTokenNetworkTrigger
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
|
@ -13,10 +14,10 @@ internal class DefaultSwapChooseTokenNetworkTrigger @Inject constructor() :
|
|||
SwapChooseTokenNetworkTrigger,
|
||||
SwapChooseTokenNetworkListener {
|
||||
|
||||
override val swapChooseTokenNetworkResultFlow: SharedFlow<CryptoCurrency>
|
||||
field = MutableSharedFlow<CryptoCurrency>()
|
||||
override val swapChooseTokenNetworkResultFlow: SharedFlow<Pair<SwapCurrencies, CryptoCurrency>>
|
||||
field = MutableSharedFlow<Pair<SwapCurrencies, CryptoCurrency>>()
|
||||
|
||||
override suspend fun trigger(cryptoCurrency: CryptoCurrency) {
|
||||
swapChooseTokenNetworkResultFlow.emit(cryptoCurrency)
|
||||
override suspend fun trigger(swapCurrencies: SwapCurrencies, cryptoCurrency: CryptoCurrency) {
|
||||
swapChooseTokenNetworkResultFlow.emit(swapCurrencies to cryptoCurrency)
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ import com.tangem.features.swap.v2.impl.choosetoken.fromSupported.entity.SwapCho
|
|||
import com.tangem.features.swap.v2.impl.choosetoken.fromSupported.model.SwapChooseTokenFactory.getErrorMessage
|
||||
import com.tangem.features.swap.v2.impl.choosetoken.fromSupported.model.transformers.SwapChooseContentStateTransformer
|
||||
import com.tangem.features.swap.v2.impl.choosetoken.fromSupported.model.transformers.SwapChooseErrorStateTransformer
|
||||
import com.tangem.features.swap.v2.impl.common.SwapUtils.SEND_WITH_SWAP_PROVIDER_TYPES
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.transformer.update
|
||||
import kotlinx.coroutines.delay
|
||||
|
|
@ -79,6 +80,7 @@ internal class SwapChooseTokenNetworkModel @Inject constructor(
|
|||
userWallet = userWallet,
|
||||
initialCurrency = params.initialCurrency,
|
||||
cryptoCurrencyList = cryptoCurrencyList + params.initialCurrency,
|
||||
filterProviderTypes = SEND_WITH_SWAP_PROVIDER_TYPES,
|
||||
).getOrElse {
|
||||
Timber.e(it.toString())
|
||||
uiState.update(
|
||||
|
|
|
|||
|
|
@ -4,36 +4,48 @@ import com.tangem.core.ui.extensions.iconResId
|
|||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.express.models.ExpressRateType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency.ID.Companion.MAIN_NETWORK_L2_TYPE_NAME
|
||||
import com.tangem.domain.models.currency.CryptoCurrency.ID.Companion.MAIN_NETWORK_TYPE_NAME
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.swap.models.SwapCurrencies
|
||||
import com.tangem.features.swap.v2.impl.choosetoken.fromSupported.entity.SwapChooseNetworkUM
|
||||
import com.tangem.features.swap.v2.impl.choosetoken.fromSupported.entity.SwapChooseTokenNetworkContentUM
|
||||
import com.tangem.features.swap.v2.impl.choosetoken.fromSupported.entity.SwapChooseTokenNetworkUM
|
||||
import com.tangem.features.swap.v2.impl.choosetoken.fromSupported.model.SwapChooseTokenFactory.getErrorMessage
|
||||
import com.tangem.lib.crypto.BlockchainUtils
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
internal class SwapChooseContentStateTransformer(
|
||||
private val pairs: SwapCurrencies,
|
||||
private val tokenName: String,
|
||||
private val onNetworkClick: (CryptoCurrency) -> Unit,
|
||||
private val onNetworkClick: (SwapCurrencies, CryptoCurrency) -> Unit,
|
||||
private val onDismiss: () -> Unit,
|
||||
) : Transformer<SwapChooseTokenNetworkUM> {
|
||||
override fun transform(prevState: SwapChooseTokenNetworkUM): SwapChooseTokenNetworkUM {
|
||||
val swapNetworks = pairs.fromGroup.available.map {
|
||||
val network = it.currencyStatus.currency.network
|
||||
val isMain = it.currencyStatus.currency is CryptoCurrency.Coin
|
||||
val swapNetworks = pairs.fromGroup.available.map { availableCurrency ->
|
||||
val cryptoCurrency = availableCurrency.currencyStatus.currency
|
||||
val network = cryptoCurrency.network
|
||||
|
||||
val isMain = cryptoCurrency is CryptoCurrency.Coin
|
||||
val subtitle = when {
|
||||
BlockchainUtils.isL2Network(networkId = network.backendId) -> MAIN_NETWORK_L2_TYPE_NAME
|
||||
isMain -> MAIN_NETWORK_TYPE_NAME
|
||||
network.standardType !is Network.StandardType.Unspecified -> network.standardType.name
|
||||
else -> ""
|
||||
}
|
||||
|
||||
SwapChooseNetworkUM(
|
||||
title = stringReference(network.name),
|
||||
subtitle = if (isMain) {
|
||||
stringReference(MAIN_NETWORK_TYPE_NAME)
|
||||
} else {
|
||||
stringReference(network.standardType.name)
|
||||
},
|
||||
subtitle = stringReference(subtitle),
|
||||
iconResId = network.iconResId,
|
||||
isMainNetwork = isMain,
|
||||
hasFixedRate = it.providers.any { it.rateTypes.any { it == ExpressRateType.Fixed } },
|
||||
onNetworkClick = { onNetworkClick(it.currencyStatus.currency) },
|
||||
hasFixedRate = availableCurrency.providers.any { provider ->
|
||||
provider.rateTypes.any { rateType ->
|
||||
rateType == ExpressRateType.Fixed
|
||||
}
|
||||
},
|
||||
onNetworkClick = { onNetworkClick(pairs, availableCurrency.currencyStatus.currency) },
|
||||
)
|
||||
}.toPersistentList()
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,16 @@ import com.tangem.core.ui.extensions.wrappedList
|
|||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.simple
|
||||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.features.swap.v2.impl.R
|
||||
|
||||
internal object SwapUtils {
|
||||
const val INCREASE_GAS_LIMIT_FOR_DEX = 112 // 12%
|
||||
const val INCREASE_GAS_LIMIT_FOR_CEX = 105 // 5%
|
||||
|
||||
/** List of supported provider types in Send with Swap */
|
||||
internal val SEND_WITH_SWAP_PROVIDER_TYPES = listOf(ExpressProviderType.CEX)
|
||||
|
||||
fun getExpressErrorMessage(expressError: ExpressError): TextReference {
|
||||
return when (expressError) {
|
||||
is ExpressError.InternalError -> resourceReference(
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import com.tangem.core.decompose.navigation.inner.InnerRouter
|
|||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.decompose.getEmptyComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.domain.swap.models.R
|
||||
import com.tangem.domain.swap.models.SwapDirection
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.DestinationRoute
|
||||
|
|
@ -28,6 +27,7 @@ import com.tangem.features.swap.v2.api.SendWithSwapComponent
|
|||
import com.tangem.features.swap.v2.impl.amount.SwapAmountComponent
|
||||
import com.tangem.features.swap.v2.impl.amount.SwapAmountComponentParams
|
||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM
|
||||
import com.tangem.features.swap.v2.impl.common.SwapUtils.SEND_WITH_SWAP_PROVIDER_TYPES
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.confirm.SendWithSwapConfirmComponent
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.model.SendWithSwapModel
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.success.SendWithSwapSuccessComponent
|
||||
|
|
@ -199,9 +199,4 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
|||
params: SendWithSwapComponent.Params,
|
||||
): DefaultSendWithSwapComponent
|
||||
}
|
||||
|
||||
companion object {
|
||||
/** List of supported provider types in Send with Swap */
|
||||
internal val SEND_WITH_SWAP_PROVIDER_TYPES = listOf(ExpressProviderType.CEX)
|
||||
}
|
||||
}
|
||||
|
|
@ -21,10 +21,10 @@ import com.tangem.features.send.v2.api.subcomponents.destination.SendDestination
|
|||
import com.tangem.features.send.v2.api.subcomponents.destination.SendDestinationComponentParams
|
||||
import com.tangem.features.swap.v2.impl.amount.SwapAmountBlockComponent
|
||||
import com.tangem.features.swap.v2.impl.amount.SwapAmountComponentParams
|
||||
import com.tangem.features.swap.v2.impl.common.SwapUtils.SEND_WITH_SWAP_PROVIDER_TYPES
|
||||
import com.tangem.features.swap.v2.impl.common.entity.ConfirmUM
|
||||
import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM
|
||||
import com.tangem.features.swap.v2.impl.notifications.SwapNotificationsComponent
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.DefaultSendWithSwapComponent.Companion.SEND_WITH_SWAP_PROVIDER_TYPES
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.SendWithSwapRoute
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.confirm.model.SendWithSwapConfirmModel
|
||||
import com.tangem.features.swap.v2.impl.sendviaswap.confirm.ui.SendWithSwapConfirmContent
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase
|
||||
|
|
@ -226,7 +225,7 @@ internal class SendWithSwapConfirmModel @Inject constructor(
|
|||
isAmountSubtractAvailable = isAmountSubtractAvailable,
|
||||
onExpressError = { expressError ->
|
||||
swapAlertFactory.getGenericErrorState(
|
||||
expressError = ExpressError.UnknownError,
|
||||
expressError = expressError,
|
||||
onFailedTxEmailClick = {
|
||||
modelScope.launch {
|
||||
swapAlertFactory.onFailedTxEmailClick(
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.blockchain.common.transaction.Fee
|
|||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.express.models.ExpressProviderType
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.swap.models.SwapDataModel
|
||||
import com.tangem.domain.swap.models.SwapDataTransactionModel
|
||||
import com.tangem.domain.swap.usecase.GetSwapDataUseCase
|
||||
|
|
@ -14,7 +15,6 @@ import com.tangem.domain.transaction.error.SendTransactionError
|
|||
import com.tangem.domain.transaction.usecase.CreateTransferTransactionUseCase
|
||||
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
|
||||
import com.tangem.domain.utils.convertToSdkAmount
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.features.send.v2.api.subcomponents.feeSelector.utils.FeeCalculationUtils
|
||||
import com.tangem.features.swap.v2.impl.common.ConfirmData
|
||||
import dagger.assisted.Assisted
|
||||
|
|
@ -22,6 +22,7 @@ import dagger.assisted.AssistedFactory
|
|||
import dagger.assisted.AssistedInject
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SwapTransactionSender @AssistedInject constructor(
|
||||
|
|
@ -72,6 +73,7 @@ internal class SwapTransactionSender @AssistedInject constructor(
|
|||
val rateType = confirmData.rateType ?: return
|
||||
val amountValue = confirmData.enteredAmount ?: return
|
||||
val feeValue = confirmData.fee?.amount?.value ?: return
|
||||
val destination = confirmData.enteredDestination ?: return
|
||||
|
||||
val fromAmount = FeeCalculationUtils.checkAndCalculateSubtractedAmount(
|
||||
isAmountSubtractAvailable = isAmountSubtractAvailable,
|
||||
|
|
@ -85,8 +87,8 @@ internal class SwapTransactionSender @AssistedInject constructor(
|
|||
userWallet = userWallet,
|
||||
fromCryptoCurrencyStatus = fromStatus,
|
||||
fromAmount = fromAmount.toStringWithRightOffset(fromStatus.currency.decimals),
|
||||
toCryptoCurrencyStatus = toStatus,
|
||||
toAddress = confirmData.enteredDestination,
|
||||
toCryptoCurrency = toStatus.currency,
|
||||
toAddress = destination,
|
||||
expressProvider = provider,
|
||||
rateType = rateType,
|
||||
).getOrElse { onExpressError(it); return }
|
||||
|
|
@ -163,7 +165,7 @@ internal class SwapTransactionSender @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun BigDecimal.toStringWithRightOffset(decimals: Int): String {
|
||||
return movePointRight(decimals).toPlainString()
|
||||
return setScale(decimals, RoundingMode.HALF_DOWN).movePointRight(decimals).toPlainString()
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue