diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt
index 40c3483f16..7496a0a8e2 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt
@@ -31,6 +31,9 @@ data class ExchangeDataResponse(
)
data class TxDetails(
+ @Json(name = "payoutAddress")
+ val payoutAddress: String,
+
@Json(name = "requestId")
val requestId: String,
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 42f9f8b591..c2cdf27727 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -193,6 +193,7 @@
Вы отправляете
Мои токены
У вас нет добавленных токенов. Добавьте токены для обмена
+ Токены не найдены. Пожалуйста, попробуйте другой запрос
Недоступен для обмена с %s
Кроме того, в курс обмена включена комиссия сети за отправку обмененных средств на ваш адрес
Статус
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 1150c0349b..94f6ed4c2e 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -192,6 +192,7 @@
You send
My tokens
You haven\'t added any tokens yet. Add tokens via Market to swap
+ No tokens found. Please try another request
Cannot be swapped for %s
Additionally, the network fee for sending the exchanged funds back to your address is included in the rate
Status
diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt
index 7a4c0df381..772502d688 100644
--- a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt
+++ b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt
@@ -292,6 +292,9 @@ internal class DefaultSwapRepository @Inject constructor(
if (txDetails.requestId != requestId) {
return@withContext DataError.InvalidRequestIdError().left()
}
+ if (toAddress != txDetails.payoutAddress) {
+ return@withContext DataError.InvalidPayoutAddressError().left()
+ }
expressDataConverter.convert(
ExchangeDataResponseWithTxDetails(
dataResponse = response,
diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExchangeStatusConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExchangeStatusConverter.kt
index f5901e8c69..30ea8ec4cd 100644
--- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExchangeStatusConverter.kt
+++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExchangeStatusConverter.kt
@@ -13,7 +13,7 @@ internal class ExchangeStatusConverter : Converter,
val unavailable: List,
+ val afterSearch: Boolean,
)
\ No newline at end of file
diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TxState.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TxState.kt
index 132327e4cb..14259bc672 100644
--- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TxState.kt
+++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TxState.kt
@@ -9,9 +9,8 @@ sealed class TxState {
val fromAmountValue: BigDecimal? = null,
val toAmount: String? = null,
val toAmountValue: BigDecimal? = null,
- val txAddress: String,
+ val txHash: String,
val txExternalUrl: String? = null,
- val txUrl: String? = null,
val timestamp: Long,
) : TxState()
diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractor.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractor.kt
index 8883e0f1a3..ceab0eb503 100644
--- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractor.kt
+++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractor.kt
@@ -11,5 +11,5 @@ interface BlockchainInteractor {
*/
fun getBlockchainInfo(networkId: String): NetworkInfo
- fun getExplorerTransactionLink(networkId: String, txAddress: String): String
+ fun getExplorerTransactionLink(networkId: String, txHash: String): String
}
\ No newline at end of file
diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultBlockchainInteractor.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultBlockchainInteractor.kt
index 836f193fe3..ea6207fece 100644
--- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultBlockchainInteractor.kt
+++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultBlockchainInteractor.kt
@@ -18,7 +18,7 @@ internal class DefaultBlockchainInteractor @Inject constructor(
}
}
- override fun getExplorerTransactionLink(networkId: String, txAddress: String): String {
- return transactionManager.getExplorerTransactionLink(networkId, txAddress)
+ override fun getExplorerTransactionLink(networkId: String, txHash: String): String {
+ return transactionManager.getExplorerTransactionLink(networkId, txHash)
}
}
\ No newline at end of file
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 19a88c1d4a..aa1167d436 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
@@ -54,7 +54,6 @@ internal class SwapInteractorImpl @Inject constructor(
private val dispatcher: CoroutineDispatcherProvider,
private val swapTransactionRepository: SwapTransactionRepository,
private val initialToCurrencyResolver: InitialToCurrencyResolver,
- private val blockchainInteractor: BlockchainInteractor,
) : SwapInteractor {
private val estimateFeeUseCase by lazy(LazyThreadSafetyMode.NONE) {
@@ -148,6 +147,7 @@ internal class SwapInteractorImpl @Inject constructor(
return CurrenciesGroup(
available = availableCryptoCurrencies,
unavailable = unavailableCryptoCurrencies.map { CryptoCurrencySwapInfo(it, emptyList()) },
+ afterSearch = false,
)
}
@@ -214,7 +214,7 @@ internal class SwapInteractorImpl @Inject constructor(
is SendTxResult.Success -> {
allowPermissionsHandler.addAddressToInProgress(permissionOptions.forTokenContractAddress)
TxState.TxSent(
- txAddress = userWalletManager.getLastTransactionHash(networkId, derivationPath).orEmpty(),
+ txHash = userWalletManager.getLastTransactionHash(networkId, derivationPath).orEmpty(),
timestamp = System.currentTimeMillis(),
)
}
@@ -462,7 +462,7 @@ internal class SwapInteractorImpl @Inject constructor(
currencyToGet.symbol,
),
toAmountValue = swapData.toTokenAmount.value,
- txAddress = userWalletManager.getLastTransactionHash(networkId, derivationPath).orEmpty(),
+ txHash = userWalletManager.getLastTransactionHash(networkId, derivationPath).orEmpty(),
timestamp = System.currentTimeMillis(),
)
}
@@ -536,10 +536,6 @@ internal class SwapInteractorImpl @Inject constructor(
},
ifRight = {
val timestamp = System.currentTimeMillis()
- val txUrl = blockchainInteractor.getExplorerTransactionLink(
- networkId = currencyToSend.currency.network.backendId,
- txAddress = exchangeData.transaction.txTo,
- )
storeSwapTransaction(
currencyToSend = currencyToSend,
currencyToGet = currencyToGet,
@@ -547,7 +543,7 @@ internal class SwapInteractorImpl @Inject constructor(
swapProvider = swapProvider,
swapDataModel = exchangeData,
timestamp = timestamp,
- txUrl = txUrl,
+ txExternalUrl = externalUrl.orEmpty(),
)
storeLastCryptoCurrencyId(currencyToGet.currency)
TxState.TxSent(
@@ -561,12 +557,11 @@ internal class SwapInteractorImpl @Inject constructor(
currencyToGet.currency.symbol,
),
toAmountValue = exchangeData.toTokenAmount.value,
- txAddress = userWalletManager.getLastTransactionHash(
+ txHash = userWalletManager.getLastTransactionHash(
currencyToSend.currency.network.backendId,
derivationPath,
).orEmpty(),
txExternalUrl = externalUrl,
- txUrl = txUrl,
timestamp = timestamp,
)
},
@@ -601,7 +596,7 @@ internal class SwapInteractorImpl @Inject constructor(
swapProvider: SwapProvider,
swapDataModel: SwapDataModel,
timestamp: Long,
- txUrl: String,
+ txExternalUrl: String,
) {
swapTransactionRepository.storeTransaction(
userWalletId = UserWalletId(userWalletManager.getWalletId()),
@@ -617,7 +612,7 @@ internal class SwapInteractorImpl @Inject constructor(
providerId = swapProvider.providerId,
status = ExchangeStatus.New,
txId = swapDataModel.transaction.txId,
- txUrl = txUrl,
+ txExternalUrl = txExternalUrl,
),
),
)
diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt
index 518d7c9fc8..d299f7824e 100644
--- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt
+++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt
@@ -42,7 +42,6 @@ class SwapDomainModule {
walletManagersFacade: WalletManagersFacade,
coroutineDispatcherProvider: CoroutineDispatcherProvider,
initialToCurrencyResolver: InitialToCurrencyResolver,
- blockchainInteractor: BlockchainInteractor,
): SwapInteractor {
return SwapInteractorImpl(
transactionManager = transactionManager,
@@ -57,7 +56,6 @@ class SwapDomainModule {
dispatcher = coroutineDispatcherProvider,
swapTransactionRepository = swapTransactionRepository,
initialToCurrencyResolver = initialToCurrencyResolver,
- blockchainInteractor = blockchainInteractor,
)
}
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt
index 895fcb1ea5..d475bad6f2 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt
@@ -49,6 +49,7 @@ class TokensDataConverter(
.toImmutableList(),
onSearchEntered = onSearchEntered,
onTokenSelected = onTokenSelected,
+ afterSearch = value.afterSearch,
)
}
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSelectTokenStateHolder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSelectTokenStateHolder.kt
index ac6762d7b7..585afb1921 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSelectTokenStateHolder.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapSelectTokenStateHolder.kt
@@ -7,6 +7,7 @@ import kotlinx.collections.immutable.ImmutableList
data class SwapSelectTokenStateHolder(
val availableTokens: ImmutableList,
val unavailableTokens: ImmutableList,
+ val afterSearch: Boolean,
val onSearchEntered: (String) -> Unit,
val onTokenSelected: (String) -> Unit,
)
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt
index 83d86eee5b..577c2e96af 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt
@@ -72,7 +72,6 @@ sealed class SwapCardState {
data class SwapButton(
val enabled: Boolean,
- val loading: Boolean = false,
val onClick: () -> Unit,
)
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt
index 4a217bcbfe..c1a94da8f7 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt
@@ -260,7 +260,9 @@ private fun ProviderLoadingState(modifier: Modifier = Modifier) {
),
) {
CircularProgressIndicator(
- modifier = Modifier.size(TangemTheme.dimens.size16),
+ modifier = Modifier
+ .size(TangemTheme.dimens.size16)
+ .align(Alignment.CenterVertically),
color = TangemTheme.colors.icon.informative,
strokeWidth = TangemTheme.dimens.size2,
)
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt
index f02e5006fe..b7c7418dae 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt
@@ -79,7 +79,7 @@ internal class StateBuilder(
),
fee = FeeItemState.Empty,
networkCurrency = networkInfo.blockchainCurrency,
- swapButton = SwapButton(enabled = false, loading = true, onClick = {}),
+ swapButton = SwapButton(enabled = false, onClick = {}),
onRefresh = {},
onBackClicked = actions.onBackClicked,
onChangeCardsClicked = actions.onChangeCardsClicked,
@@ -138,7 +138,6 @@ internal class StateBuilder(
fee = FeeItemState.Empty,
swapButton = SwapButton(
enabled = false,
- loading = false,
onClick = { },
),
changeCardsButtonState = ChangeCardsButtonState.DISABLED,
@@ -187,7 +186,7 @@ internal class StateBuilder(
),
warnings = emptyList(),
fee = FeeItemState.Empty,
- swapButton = SwapButton(enabled = false, loading = true, onClick = {}),
+ swapButton = SwapButton(enabled = false, onClick = {}),
providerState = ProviderState.Loading(),
permissionState = uiStateHolder.permissionState,
changeCardsButtonState = ChangeCardsButtonState.UPDATE_IN_PROGRESS,
@@ -260,7 +259,6 @@ internal class StateBuilder(
fee = feeState,
swapButton = SwapButton(
enabled = getSwapButtonEnabled(quoteModel.preparedSwapConfigState),
- loading = false,
onClick = actions.onSwapClick,
),
changeCardsButtonState = if (isReverseSwapPossible) {
@@ -454,7 +452,6 @@ internal class StateBuilder(
fee = FeeItemState.Empty,
swapButton = SwapButton(
enabled = false,
- loading = false,
onClick = actions.onSwapClick,
),
changeCardsButtonState = if (isReverseSwapPossible) {
@@ -566,7 +563,6 @@ internal class StateBuilder(
fee = FeeItemState.Empty,
swapButton = SwapButton(
enabled = false,
- loading = false,
onClick = { },
),
changeCardsButtonState = if (isReverseSwapPossible) {
@@ -582,7 +578,6 @@ internal class StateBuilder(
fun createSwapInProgressState(uiState: SwapStateHolder): SwapStateHolder {
return uiState.copy(
swapButton = uiState.swapButton.copy(
- loading = true,
enabled = false,
),
)
@@ -737,6 +732,7 @@ internal class StateBuilder(
dataState: SwapProcessDataState,
onExploreClick: () -> Unit,
onStatusClick: () -> Unit,
+ txUrl: String,
): SwapStateHolder {
val fee = requireNotNull(dataState.selectedFee)
val fromCryptoCurrency = requireNotNull(dataState.fromCryptoCurrency)
@@ -751,7 +747,7 @@ internal class StateBuilder(
return uiState.copy(
successState = SwapSuccessStateHolder(
timestamp = txState.timestamp,
- txUrl = txState.txUrl.orEmpty(),
+ txUrl = txUrl,
providerName = stringReference(providerState.name),
providerType = stringReference(providerState.type),
showStatusButton = providerState.type == ExchangeProviderType.CEX.name,
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 b211130172..571a1b51f1 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
@@ -399,7 +399,6 @@ private fun MainButton(state: SwapStateHolder, onPermissionWarningClick: () -> U
modifier = Modifier.fillMaxWidth(),
text = stringResource(id = R.string.swapping_insufficient_funds),
enabled = false,
- showProgress = state.swapButton.loading,
onClick = state.swapButton.onClick,
)
}
@@ -408,7 +407,6 @@ private fun MainButton(state: SwapStateHolder, onPermissionWarningClick: () -> U
modifier = Modifier.fillMaxWidth(),
text = stringResource(id = R.string.swapping_give_permission),
enabled = true,
- showProgress = state.swapButton.loading,
onClick = onPermissionWarningClick,
)
}
@@ -418,7 +416,6 @@ private fun MainButton(state: SwapStateHolder, onPermissionWarningClick: () -> U
text = stringResource(id = R.string.common_swap),
iconResId = R.drawable.ic_tangem_24,
enabled = state.swapButton.enabled,
- showProgress = state.swapButton.loading,
onClick = state.swapButton.onClick,
)
}
@@ -487,7 +484,7 @@ private val state = SwapStateHolder(
),
),
networkCurrency = "MATIC",
- swapButton = SwapButton(enabled = true, loading = false, onClick = {}),
+ swapButton = SwapButton(enabled = true, onClick = {}),
onRefresh = {},
onBackClicked = {},
onChangeCardsClicked = {},
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt
index 4057aba9af..87a82413f1 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapSelectTokenScreen.kt
@@ -42,10 +42,16 @@ fun SwapSelectTokenScreen(state: SwapSelectTokenStateHolder, onBack: () -> Unit)
.background(color = TangemTheme.colors.background.secondary),
content = { padding ->
val modifier = Modifier.padding(padding)
- if (state.availableTokens.isEmpty() && state.unavailableTokens.isEmpty()) {
- EmptyTokensList(modifier)
- } else {
- ListOfTokens(state = state, modifier = modifier)
+ when {
+ state.availableTokens.isEmpty() && state.unavailableTokens.isEmpty() && state.afterSearch -> {
+ TokensNotFound(modifier)
+ }
+ state.availableTokens.isEmpty() && state.unavailableTokens.isEmpty() && !state.afterSearch -> {
+ EmptyTokensList(modifier)
+ }
+ else -> {
+ ListOfTokens(state = state, modifier = modifier)
+ }
}
},
topBar = {
@@ -91,6 +97,26 @@ private fun EmptyTokensList(modifier: Modifier = Modifier) {
}
}
+@Composable
+private fun TokensNotFound(modifier: Modifier = Modifier) {
+ Box(
+ modifier = modifier
+ .background(TangemTheme.colors.background.secondary)
+ .fillMaxSize(),
+ ) {
+ Text(
+ modifier = Modifier
+ .padding(top = TangemTheme.dimens.spacing32)
+ .padding(horizontal = TangemTheme.dimens.spacing30)
+ .align(Alignment.TopCenter),
+ text = stringResource(id = R.string.express_token_list_empty_search),
+ style = TangemTheme.typography.subtitle1,
+ color = TangemTheme.colors.text.tertiary,
+ textAlign = TextAlign.Center,
+ )
+ }
+}
+
@Composable
private fun ListOfTokens(state: SwapSelectTokenStateHolder, modifier: Modifier = Modifier) {
val screenBackgroundColor = TangemTheme.colors.background.secondary
@@ -283,6 +309,7 @@ private fun TokenScreenPreview() {
state = SwapSelectTokenStateHolder(
availableTokens = listOf(title, token, token, token).toImmutableList(),
unavailableTokens = listOf(title, token, token, token).toImmutableList(),
+ afterSearch = false,
onSearchEntered = {},
onTokenSelected = {},
),
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt
index 0aec67858b..45d37e07de 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/TransactionCard.kt
@@ -418,7 +418,7 @@ private fun TokenIcon(
contentAlignment = Alignment.Center,
) {
Image(
- modifier = Modifier.padding(all = TangemTheme.dimens.spacing0_5),
+ modifier = Modifier.padding(all = TangemTheme.dimens.spacing2),
painter = painterResource(id = networkIconRes),
contentDescription = null,
)
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 a511e6ab43..955d5e5f74 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
@@ -12,8 +12,11 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase
+import com.tangem.domain.tokens.UpdateDelayedNetworkStatusUseCase
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.analytics.SwapEvents
import com.tangem.feature.swap.domain.BlockchainInteractor
import com.tangem.feature.swap.domain.SwapInteractor
@@ -32,6 +35,7 @@ import com.tangem.feature.swap.ui.StateBuilder
import com.tangem.utils.coroutines.*
import com.tangem.utils.isNullOrZero
import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -57,6 +61,7 @@ internal class SwapViewModel @Inject constructor(
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val getCryptoCurrencyStatusUseCase: GetCryptoCurrencyStatusSyncUseCase,
+ private val updateDelayedCurrencyStatusUseCase: UpdateDelayedNetworkStatusUseCase,
savedStateHandle: SavedStateHandle,
) : ViewModel(), DefaultLifecycleObserver {
@@ -93,6 +98,11 @@ internal class SwapViewModel @Inject constructor(
private var isOrderReversed = false
private val lastAmount = mutableStateOf(INITIAL_AMOUNT)
private var swapRouter: SwapRouter by Delegates.notNull()
+
+ private val isExchangeTooSmallAmountError: (SwapState) -> Boolean = {
+ it is SwapState.SwapError && it.error is DataError.ExchangeTooSmallAmountError
+ }
+
val currentScreen: SwapNavScreen
get() = swapRouter.currentScreen
@@ -380,13 +390,17 @@ internal class SwapViewModel @Inject constructor(
}
private fun selectProvider(state: Map): SwapProvider {
- val stateSuccess = state.getLastLoadedSuccessStates()
- return if (stateSuccess.isNotEmpty()) {
+ val consideredProviders = state.filter {
+ it.value is SwapState.QuotesLoadedState || isExchangeTooSmallAmountError(it.value)
+ }
+
+ return if (consideredProviders.isNotEmpty()) {
val currentSelected = dataState.selectedProvider
- if (currentSelected != null && stateSuccess.keys.contains(currentSelected)) {
+ if (currentSelected != null && consideredProviders.keys.contains(currentSelected)) {
currentSelected
} else {
- findBestQuoteProvider(stateSuccess) ?: stateSuccess.keys.first()
+ findBestQuoteProvider(consideredProviders.getLastLoadedSuccessStates())
+ ?: consideredProviders.keys.first()
}
} else {
state.keys.first()
@@ -448,14 +462,19 @@ internal class SwapViewModel @Inject constructor(
}.onSuccess {
when (it) {
is TxState.TxSent -> {
+ val url = blockchainInteractor.getExplorerTransactionLink(
+ networkId = fromCurrency.currency.network.backendId,
+ txHash = it.txHash,
+ )
+ updateWalletBalance()
uiState = stateBuilder.createSuccessState(
uiState = uiState,
txState = it,
dataState = dataState,
+ txUrl = url,
onExploreClick = {
- val txUrl = it.txUrl
- if (!txUrl.isNullOrBlank()) {
- swapRouter.openUrl(txUrl)
+ if (it.txHash.isNotEmpty()) {
+ swapRouter.openUrl(url)
}
analyticsEventHandler.send(
event = SwapEvents.ButtonExplore(initialCryptoCurrency.symbol),
@@ -580,13 +599,16 @@ internal class SwapViewModel @Inject constructor(
fromGroup = tokenDataState.fromGroup.copy(
available = available,
unavailable = unavailable,
+ afterSearch = true,
),
+
)
} else {
tokenDataState.copy(
toGroup = tokenDataState.toGroup.copy(
available = available,
unavailable = unavailable,
+ afterSearch = true,
),
)
}
@@ -957,10 +979,32 @@ internal class SwapViewModel @Inject constructor(
}
}
+ private fun updateWalletBalance() {
+ swapInteractor.getSelectedWallet()?.let { userWallet ->
+ dataState.fromCryptoCurrency?.currency?.network?.let { network ->
+ viewModelScope.launch {
+ withContext(NonCancellable) {
+ updateForBalance(userWallet, network)
+ }
+ }
+ }
+ }
+ }
+
+ private suspend fun updateForBalance(userWallet: UserWallet, network: Network) {
+ updateDelayedCurrencyStatusUseCase(
+ userWalletId = userWallet.walletId,
+ network = network,
+ delayMillis = UPDATE_BALANCE_DELAY_MILLIS,
+ refresh = true,
+ )
+ }
+
companion object {
private const val loggingTag = "SwapViewModel"
private const val INITIAL_AMOUNT = ""
private const val UPDATE_DELAY = 10000L
private const val DEBOUNCE_AMOUNT_DELAY = 1000L
+ private const val UPDATE_BALANCE_DELAY_MILLIS = 11000L
}
}
\ No newline at end of file
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt
index fd13879bc9..514afc7709 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt
@@ -66,7 +66,7 @@ internal class TokenDetailsSwapTransactionsStateConverter(
SwapTransactionsState(
txId = transaction.txId,
provider = transaction.provider,
- txUrl = transaction.status?.txUrl,
+ txUrl = transaction.status?.txExternalUrl,
timestamp = TextReference.Str("${timestamp.toDateFormat()}, ${timestamp.toTimeFormat()}"),
fiatSymbol = appCurrency.symbol,
statuses = getStatuses(transaction.status?.status),
@@ -74,7 +74,7 @@ internal class TokenDetailsSwapTransactionsStateConverter(
activeStatus = transaction.status?.status,
notification = getNotification(
transaction.status?.status,
- transaction.status?.txUrl,
+ transaction.status?.txExternalUrl,
),
toCryptoCurrencyId = toCurrency.currency.id,
toCryptoAmount = BigDecimalFormatter.formatCryptoAmount(
@@ -112,9 +112,9 @@ internal class TokenDetailsSwapTransactionsStateConverter(
return tx.copy(
activeStatus = statusModel.status,
hasFailed = hasFailed,
- notification = getNotification(statusModel.status, statusModel.txUrl),
+ notification = getNotification(statusModel.status, statusModel.txExternalUrl),
statuses = getStatuses(statusModel.status, hasFailed),
- txUrl = statusModel.txUrl,
+ txUrl = statusModel.txExternalUrl,
)
}