diff --git a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt
index c1262e0e1f..953ee95b85 100644
--- a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt
+++ b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt
@@ -11,6 +11,7 @@ import com.tangem.domain.wallets.legacy.WalletsStateHolder
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.common.extensions.dispatchOnMain
+import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.extensions.onUserWalletSelected
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.domain.TangemSdkManager
@@ -69,6 +70,10 @@ class AppStateHolder @Inject constructor() : WalletsStateHolder, ReduxNavControl
mainStore?.dispatch(action)
}
+ override suspend fun dispatchWithMain(action: Action) {
+ mainStore?.dispatchWithMain(action)
+ }
+
override suspend fun onUserWalletSelected(userWallet: UserWallet) {
mainStore?.onUserWalletSelected(userWallet)
}
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 5705d3bd04..744452a5fa 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -198,6 +198,7 @@
Провайдеры проводят транзакции, обеспечивая плавный и эффективный обмен токенами
Выберите провайдера
Курс обмена
+ Больше провайдеров на подходе.\nСледите за обновлениями!
Чтобы вернуть ваши деньги, посетите сайт провайдера
Операция не выполнена провайдером
Посетите сайт провайдера для проверки
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index b81d198635..55f40ad98b 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -196,6 +196,7 @@
Status
Providers facilitate transactions, ensuring smooth and efficient token swaps
Choose provider
+ More providers are coming soon.\nStay tuned!
Estimated amount
Exchange by %s
Visit provider’s website to refund your money
diff --git a/domain/legacy/src/main/java/com/tangem/domain/redux/ReduxStateHolder.kt b/domain/legacy/src/main/java/com/tangem/domain/redux/ReduxStateHolder.kt
index 61170a1927..58c0bb0dde 100644
--- a/domain/legacy/src/main/java/com/tangem/domain/redux/ReduxStateHolder.kt
+++ b/domain/legacy/src/main/java/com/tangem/domain/redux/ReduxStateHolder.kt
@@ -7,5 +7,7 @@ interface ReduxStateHolder {
fun dispatch(action: Action)
+ suspend fun dispatchWithMain(action: Action)
+
suspend fun onUserWalletSelected(userWallet: UserWallet)
}
\ No newline at end of file
diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt
index 765647a01e..d3ec1058b9 100644
--- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt
+++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt
@@ -2,7 +2,6 @@ package com.tangem.feature.swap.domain
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
-import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.feature.swap.domain.models.SwapAmount
import com.tangem.feature.swap.domain.models.domain.IncludeFeeInAmount
@@ -15,8 +14,6 @@ interface SwapInteractor {
suspend fun getTokensDataState(currency: CryptoCurrency): TokensDataStateExpress
- fun initDerivationPathAndNetwork(derivationPath: String?, network: Network)
-
/**
* Gives permission to swap, this starts scan card process
*
@@ -30,7 +27,6 @@ interface SwapInteractor {
* Find best quote for given tokens to swap
* under the hood calls different methods to receive data, depends on permission for given token
*
- * @param networkId network for tokens
* @param fromToken [Currency] from which want to swap
* @param toToken [Currency] that receive after swap
* @param amountToSwap amount you want to swap
@@ -39,7 +35,6 @@ interface SwapInteractor {
*/
@Throws(IllegalStateException::class)
suspend fun findBestQuote(
- networkId: String,
fromToken: CryptoCurrencyStatus,
toToken: CryptoCurrencyStatus,
providers: List,
@@ -62,7 +57,6 @@ interface SwapInteractor {
@Throws(IllegalStateException::class)
suspend fun onSwap(
swapProvider: SwapProvider,
- networkId: String,
swapData: SwapDataModel?,
currencyToSend: CryptoCurrencyStatus,
currencyToGet: CryptoCurrencyStatus,
@@ -76,7 +70,6 @@ interface SwapInteractor {
selectedFee: FeeType,
fromToken: CryptoCurrencyStatus,
amountToSwap: String,
- networkId: String,
): SwapState.QuotesLoadedState
/**
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 631d3e6d51..b2a70e5799 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
@@ -62,7 +62,6 @@ internal class SwapInteractorImpl @Inject constructor(
private val swapCurrencyConverter = SwapCurrencyConverter()
private val amountFormatter = AmountFormatter()
- private var derivationPath: String? = null
private var network: Network? = null
override suspend fun getTokensDataState(currency: CryptoCurrency): TokensDataStateExpress {
@@ -80,7 +79,7 @@ internal class SwapInteractorImpl @Inject constructor(
.filter {
val currencyFilter = it.currency.network.backendId != currency.network.backendId ||
it.currency.getContractAddress() != currency.getContractAddress()
- val statusFilter = it.value is CryptoCurrencyStatus.Loaded
+ val statusFilter = it.value is CryptoCurrencyStatus.Loaded || it.value is CryptoCurrencyStatus.NoAccount
val notCustomTokenFilter = !it.currency.isCustom
statusFilter && currencyFilter && notCustomTokenFilter
}
@@ -182,14 +181,9 @@ internal class SwapInteractorImpl @Inject constructor(
return repository.getPairs(initialCurrency, currenciesList)
}
- @Deprecated("used in old swap mechanism")
- override fun initDerivationPathAndNetwork(derivationPath: String?, network: Network) {
- this.derivationPath = derivationPath
- this.network = network
- }
-
@Deprecated("used in old swap mechanism")
override suspend fun givePermissionToSwap(networkId: String, permissionOptions: PermissionOptions): TxState {
+ val derivationPath = permissionOptions.fromToken.network.derivationPath.value
val dataToSign = if (permissionOptions.approveType == SwapApproveType.UNLIMITED) {
getApproveData(
networkId = networkId,
@@ -233,7 +227,6 @@ internal class SwapInteractorImpl @Inject constructor(
@Deprecated("used in old swap mechanism")
override suspend fun findBestQuote(
- networkId: String,
fromToken: CryptoCurrencyStatus,
toToken: CryptoCurrencyStatus,
providers: List,
@@ -249,7 +242,7 @@ internal class SwapInteractorImpl @Inject constructor(
}
val amount = SwapAmount(amountDecimal, getTokenDecimals(fromToken.currency))
val isBalanceWithoutFeeEnough = isBalanceEnough(fromToken, amount, null)
-
+ val networkId = fromToken.currency.network.backendId
when (provider.type) {
ExchangeProviderType.DEX -> {
manageDex(
@@ -310,7 +303,10 @@ internal class SwapInteractorImpl @Inject constructor(
if (isAllowedToSpend && allowPermissionsHandler.isAddressAllowanceInProgress(fromTokenAddress)) {
allowPermissionsHandler.removeAddressFromProgress(fromTokenAddress)
- transactionManager.updateWalletManager(networkId, derivationPath)
+ transactionManager.updateWalletManager(
+ networkId,
+ fromToken.currency.network.derivationPath.value,
+ )
}
return if (isAllowedToSpend && isBalanceWithoutFeeEnough) {
provider to loadDexSwapData(
@@ -361,7 +357,6 @@ internal class SwapInteractorImpl @Inject constructor(
override suspend fun onSwap(
swapProvider: SwapProvider,
- networkId: String,
swapData: SwapDataModel?,
currencyToSend: CryptoCurrencyStatus,
currencyToGet: CryptoCurrencyStatus,
@@ -389,7 +384,7 @@ internal class SwapInteractorImpl @Inject constructor(
}
ExchangeProviderType.DEX -> {
onSwapDex(
- networkId = networkId,
+ networkId = currencyToSend.currency.network.backendId,
swapData = requireNotNull(swapData),
currencyToSend = currencyToSend.currency,
currencyToGet = currencyToGet.currency,
@@ -405,7 +400,6 @@ internal class SwapInteractorImpl @Inject constructor(
selectedFee: FeeType,
fromToken: CryptoCurrencyStatus,
amountToSwap: String,
- networkId: String,
): SwapState.QuotesLoadedState {
val amountDecimal = toBigDecimalOrNull(amountToSwap)
if (amountDecimal == null || amountDecimal.signum() == 0) {
@@ -413,7 +407,7 @@ internal class SwapInteractorImpl @Inject constructor(
}
val amount = SwapAmount(amountDecimal, getTokenDecimals(fromToken.currency))
val includeFeeInAmount = getIncludeFeeInAmount(
- networkId = networkId,
+ networkId = fromToken.currency.network.backendId,
txFee = state.txFee,
amount = amount,
fromToken = fromToken.currency,
@@ -422,6 +416,7 @@ internal class SwapInteractorImpl @Inject constructor(
return state.copy(
permissionState = PermissionDataState.Empty,
preparedSwapConfigState = state.preparedSwapConfigState.copy(
+ isFeeEnough = includeFeeInAmount !is IncludeFeeInAmount.BalanceNotEnough,
isBalanceEnough = includeFeeInAmount !is IncludeFeeInAmount.BalanceNotEnough,
includeFeeInAmount = includeFeeInAmount,
),
@@ -438,6 +433,7 @@ internal class SwapInteractorImpl @Inject constructor(
): TxState {
val amountDecimal = requireNotNull(toBigDecimalOrNull(amountToSwap)) { "wrong amount format" }
val amount = SwapAmount(amountDecimal, getTokenDecimals(currencyToSend))
+ val derivationPath = currencyToSend.network.derivationPath.value
val result = transactionManager.sendTransaction(
txData = SwapTxData(
networkId = networkId,
@@ -481,6 +477,7 @@ internal class SwapInteractorImpl @Inject constructor(
}
}
+ @Suppress("LongMethod")
private suspend fun onSwapCex(
currencyToSend: CryptoCurrencyStatus,
currencyToGet: CryptoCurrencyStatus,
@@ -519,6 +516,7 @@ internal class SwapInteractorImpl @Inject constructor(
val externalUrl = (exchangeData.transaction as? ExpressTransactionModel.CEX)?.externalTxUrl
+ val derivationPath = currencyToSend.currency.network.derivationPath.value
return result.fold(
ifLeft = {
when (it) {
@@ -659,7 +657,7 @@ internal class SwapInteractorImpl @Inject constructor(
val allowance = repository.getAllowance(
userWalletId = userWallet.walletId,
networkId = networkId,
- derivationPath = derivationPath,
+ derivationPath = fromToken.network.derivationPath.value,
tokenDecimalCount = getTokenDecimals(fromToken),
tokenAddress = getTokenAddress(fromToken),
spenderAddress = spenderAddress,
@@ -832,7 +830,10 @@ internal class SwapInteractorImpl @Inject constructor(
}
val tokenForFeeBalance =
- userWalletManager.getNativeTokenBalance(networkId, derivationPath) ?: ProxyAmount.empty()
+ userWalletManager.getNativeTokenBalance(
+ networkId,
+ fromToken.network.derivationPath.value,
+ ) ?: ProxyAmount.empty()
if (amount.value > tokenForFeeBalance.value) {
return IncludeFeeInAmount.BalanceNotEnough
@@ -907,7 +908,7 @@ internal class SwapInteractorImpl @Inject constructor(
destinationAddress = swapData.transaction.txTo,
increaseBy = INCREASE_GAS_LIMIT_BY,
data = (swapData.transaction as ExpressTransactionModel.DEX).txData,
- derivationPath = derivationPath,
+ derivationPath = fromToken.currency.network.derivationPath.value,
)
val txFeeState = when (feeData) {
is ProxyFees.MultipleFees -> feeData.proxyFeesToFeeState(networkId)
@@ -1048,6 +1049,7 @@ internal class SwapInteractorImpl @Inject constructor(
permissionState = PermissionDataState.PermissionLoading,
)
}
+ val derivationPath = fromToken.network.derivationPath.value
// setting up amount for approve with given amount for swap [SwapApproveType.Limited]
val transactionData = getApproveData(
networkId = networkId,
@@ -1091,7 +1093,7 @@ internal class SwapInteractorImpl @Inject constructor(
permissionState = PermissionDataState.PermissionReadyForRequest(
currency = fromToken.symbol,
amount = INFINITY_SYMBOL,
- walletAddress = getWalletAddress(networkId),
+ walletAddress = getWalletAddress(networkId, derivationPath),
spenderAddress = getTokenAddress(fromToken),
requestApproveData = RequestApproveStateData(
fee = feeState,
@@ -1262,7 +1264,7 @@ internal class SwapInteractorImpl @Inject constructor(
}
}
- private suspend fun getWalletAddress(networkId: String): String {
+ private suspend fun getWalletAddress(networkId: String, derivationPath: String?): String {
return userWalletManager.getWalletAddress(networkId, derivationPath)
}
@@ -1286,7 +1288,10 @@ internal class SwapInteractorImpl @Inject constructor(
if (fee == null) {
return false
}
- val nativeTokenBalance = userWalletManager.getNativeTokenBalance(networkId, derivationPath)
+ val nativeTokenBalance = userWalletManager.getNativeTokenBalance(
+ networkId,
+ fromToken.network.derivationPath.value,
+ )
val percentsToFeeIncrease = BigDecimal.ONE
return when (fromToken) {
is CryptoCurrency.Coin -> {
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ChooseProviderBottomSheet.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ChooseProviderBottomSheet.kt
index 363085e36c..0621d0a12a 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ChooseProviderBottomSheet.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ChooseProviderBottomSheet.kt
@@ -4,11 +4,13 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
+import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
@@ -55,7 +57,12 @@ private fun ChooseProviderBottomSheetContent(content: ChooseProviderBottomSheetC
)
Column(
modifier = Modifier
- .padding(TangemTheme.dimens.spacing16)
+ .padding(
+ top = TangemTheme.dimens.spacing16,
+ start = TangemTheme.dimens.spacing16,
+ end = TangemTheme.dimens.spacing16,
+ bottom = TangemTheme.dimens.spacing14,
+ )
.background(
color = TangemTheme.colors.background.action,
shape = TangemTheme.shapes.roundedCornersXMedium,
@@ -76,6 +83,23 @@ private fun ChooseProviderBottomSheetContent(content: ChooseProviderBottomSheetC
)
}
}
+ Icon(
+ painterResource(id = R.drawable.ic_lightning_16),
+ contentDescription = null,
+ tint = TangemTheme.colors.icon.informative,
+ modifier = Modifier
+ .align(Alignment.CenterHorizontally),
+ )
+ Text(
+ text = stringResource(R.string.express_more_providers_soon),
+ style = TangemTheme.typography.caption2,
+ color = TangemTheme.colors.icon.informative,
+ modifier = Modifier
+ .padding(top = TangemTheme.dimens.spacing6, bottom = TangemTheme.dimens.spacing16)
+ .padding(horizontal = TangemTheme.dimens.spacing56)
+ .align(Alignment.CenterHorizontally),
+ textAlign = TextAlign.Center,
+ )
}
}
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
index ba5cc5a853..2b2ebd577e 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
@@ -74,16 +74,15 @@ internal fun SwapScreenContent(state: SwapStateHolder, modifier: Modifier = Modi
if (state.warnings.isNotEmpty()) SwapWarnings(warnings = state.warnings)
MainButton(state = state, onPermissionWarningClick = state.onShowPermissionBottomSheet)
- }
- }
- state.tosState?.let {
- ProviderTos(
- tosState = it,
- modifier = Modifier
- .align(Alignment.BottomCenter)
- .padding(bottom = TangemTheme.dimens.spacing16),
- )
+ state.tosState?.let {
+ ProviderTos(
+ tosState = it,
+ modifier = Modifier
+ .padding(top = TangemTheme.dimens.spacing16),
+ )
+ }
+ }
}
AnimatedVisibility(
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapProcessDataState.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapProcessDataState.kt
index 7b5bd446fa..7623970edf 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapProcessDataState.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapProcessDataState.kt
@@ -11,7 +11,6 @@ import com.tangem.feature.swap.models.ApproveType
data class SwapProcessDataState(
// Initial network id
- val networkId: String,
val fromCryptoCurrency: CryptoCurrencyStatus? = null,
val toCryptoCurrency: CryptoCurrencyStatus? = null,
// Amount from input
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt
index 399f3b6f79..b1438e8115 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt
@@ -79,7 +79,7 @@ internal class SwapViewModel @Inject constructor(
private val amountDebouncer = Debouncer()
private val singleTaskScheduler = SingleTaskScheduler