Updated on 2026-08-14

This commit is contained in:
Tangem 2023-11-29 16:53:26 +03:00
commit 40dd71d7f2
7 changed files with 67 additions and 62 deletions

View file

@ -3,14 +3,13 @@ package com.tangem.core.ui.components.appbar
import androidx.annotation.DrawableRes
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
@ -49,7 +48,11 @@ fun AppBarWithBackButton(
contentDescription = null,
modifier = Modifier
.size(size = TangemTheme.dimens.size24)
.clickable { onBackClick() },
.clickable(
indication = rememberRipple(bounded = false),
interactionSource = remember { MutableInteractionSource() },
onClick = onBackClick,
),
tint = TangemTheme.colors.icon.primary1,
)
if (!text.isNullOrBlank()) {

View file

@ -213,7 +213,10 @@ internal class SwapInteractorImpl @Inject constructor(
return when (result) {
is SendTxResult.Success -> {
allowPermissionsHandler.addAddressToInProgress(permissionOptions.forTokenContractAddress)
TxState.TxSent(txAddress = userWalletManager.getLastTransactionHash(networkId, derivationPath) ?: "")
TxState.TxSent(
txAddress = userWalletManager.getLastTransactionHash(networkId, derivationPath).orEmpty(),
timestamp = System.currentTimeMillis(),
)
}
SendTxResult.UserCancelledError -> TxState.UserCancelled
is SendTxResult.BlockchainSdkError -> TxState.BlockchainError
@ -370,7 +373,7 @@ internal class SwapInteractorImpl @Inject constructor(
currencyToGet = currencyToGet,
amount = amount,
fee = fee,
providerId = swapProvider.providerId,
swapProvider = swapProvider,
userWalletId = requireNotNull(getSelectedWallet()).walletId,
)
}
@ -455,7 +458,8 @@ internal class SwapInteractorImpl @Inject constructor(
swapData.toTokenAmount,
currencyToGet.symbol,
),
txAddress = userWalletManager.getLastTransactionHash(networkId, derivationPath) ?: "",
txAddress = userWalletManager.getLastTransactionHash(networkId, derivationPath).orEmpty(),
timestamp = System.currentTimeMillis(),
)
}
SendTxResult.UserCancelledError -> TxState.UserCancelled
@ -471,7 +475,7 @@ internal class SwapInteractorImpl @Inject constructor(
currencyToGet: CryptoCurrencyStatus,
amount: SwapAmount,
fee: TxFee,
providerId: String,
swapProvider: SwapProvider,
userWalletId: UserWalletId,
): TxState {
val exchangeData = repository.getExchangeData(
@ -481,7 +485,7 @@ internal class SwapInteractorImpl @Inject constructor(
toNetwork = currencyToGet.currency.network.backendId,
fromAmount = amount.toStringWithRightOffset(),
fromDecimals = amount.decimals,
providerId = providerId,
providerId = swapProvider.providerId,
rateType = RateType.FLOAT,
toAddress = currencyToGet.value.networkAddress?.defaultAddress ?: "",
)
@ -501,14 +505,17 @@ internal class SwapInteractorImpl @Inject constructor(
network = currencyToSend.currency.network,
)
return result.fold(ifLeft = {
when (it) {
is SendTransactionError.NetworkError -> TxState.NetworkError
is SendTransactionError.DataError -> TxState.BlockchainError
SendTransactionError.DemoCardError -> TxState.UnknownError
else -> TxState.UnknownError
}
}, ifRight = {
return result.fold(
ifLeft = {
when (it) {
is SendTransactionError.NetworkError -> TxState.NetworkError
is SendTransactionError.DataError -> TxState.BlockchainError
SendTransactionError.DemoCardError -> TxState.UnknownError
else -> TxState.UnknownError
}
},
ifRight = {
val timestamp = System.currentTimeMillis()
TxState.TxSent(
fromAmount = amountFormatter.formatSwapAmountToUI(
amount,
@ -521,9 +528,11 @@ internal class SwapInteractorImpl @Inject constructor(
txAddress = userWalletManager.getLastTransactionHash(
currencyToSend.currency.network.backendId,
derivationPath,
) ?: "",
).orEmpty(),
timestamp = timestamp,
)
},)
},
)
}
@Deprecated("used in old swap mechanism")

View file

@ -6,6 +6,7 @@ sealed class TxState {
val fromAmount: String? = null,
val toAmount: String? = null,
val txAddress: String,
val timestamp: Long,
) : TxState()
object UserCancelled : TxState()

View file

@ -2,14 +2,15 @@ package com.tangem.feature.swap.models
import com.tangem.core.ui.components.currency.tokenicon.TokenIconState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.feature.swap.domain.models.domain.SwapProvider
data class SwapSuccessStateHolder(
val timestamp: Long,
val txUrl: String,
val fee: TextReference,
val rate: TextReference,
val selectedProvider: SwapProvider,
val providerName: TextReference,
val providerType: TextReference,
val providerIcon: String,
val fromTokenAmount: TextReference,
val toTokenAmount: TextReference,
val fromTokenFiatAmount: TextReference,

View file

@ -20,7 +20,6 @@ import com.tangem.feature.swap.domain.models.ui.*
import com.tangem.feature.swap.models.*
import com.tangem.feature.swap.models.states.*
import com.tangem.feature.swap.presentation.R
import com.tangem.feature.swap.viewmodels.SwapProcessDataState
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import java.math.BigDecimal
@ -459,39 +458,37 @@ internal class StateBuilder(
)
}
@Suppress("LongParameterList")
fun createSuccessState(
uiState: SwapStateHolder,
txState: TxState.TxSent,
dataState: SwapProcessDataState,
fromAmount: BigDecimal,
toAmount: BigDecimal,
txUrl: String,
onSecondaryBtnClick: () -> Unit,
): SwapStateHolder {
val fromToken = requireNotNull(uiState.sendCardData as? SwapCardState.SwapCardData)
val toToken = requireNotNull(uiState.receiveCardData as? SwapCardState.SwapCardData)
val fromTokenIconState = fromToken.token?.let(iconStateConverter::convert)
val toTokenIconState = toToken.token?.let(iconStateConverter::convert)
val providerState = uiState.providerState as ProviderState.Content
val fromToken = requireNotNull((uiState.sendCardData as? SwapCardState.SwapCardData)?.token)
val toToken = requireNotNull((uiState.receiveCardData as? SwapCardState.SwapCardData)?.token)
val fromTokenIconState = iconStateConverter.convert(fromToken)
val toTokenIconState = iconStateConverter.convert(toToken)
val fee = uiState.fee as? FeeItemState.Content ?: return uiState
val fromCryptoCurrencyStatus = requireNotNull(fromToken.token)
val toCryptoCurrencyStatus = requireNotNull(toToken.token)
val rate = txState.toAmount?.toBigDecimal()?.divide(
txState.fromAmount?.toBigDecimal(),
toCryptoCurrencyStatus.currency.decimals,
RoundingMode.HALF_UP,
)
val fromCurrencySymbol = fromCryptoCurrencyStatus.currency.symbol
val toCurrencySymbol = toCryptoCurrencyStatus.currency.symbol
val fromFiatAmount = getFormattedFiatAmount(fromToken.value.fiatRate?.multiply(fromAmount))
val toFiatAmount = getFormattedFiatAmount(toToken.value.fiatRate?.multiply(toAmount))
return uiState.copy(
successState = SwapSuccessStateHolder(
timestamp = System.currentTimeMillis(),
timestamp = txState.timestamp,
txUrl = txUrl,
selectedProvider = requireNotNull(dataState.selectedProvider),
providerName = TextReference.Str(providerState.name),
providerType = TextReference.Str(providerState.type),
providerIcon = providerState.iconUrl,
fee = TextReference.Str("${fee.amountCrypto} ${fee.symbolCrypto} (${fee.amountFiatFormatted})"),
rate = TextReference.Str("1 $fromCurrencySymbol$rate $toCurrencySymbol"),
fromTokenAmount = TextReference.Str("${txState.fromAmount.orEmpty()} ${fromToken.tokenCurrency}}"),
toTokenAmount = TextReference.Str("${txState.toAmount.orEmpty()} ${toToken.tokenCurrency}}"),
fromTokenFiatAmount = TextReference.Str(fromToken.amountEquivalent.orEmpty()),
toTokenFiatAmount = TextReference.Str(toToken.amountEquivalent.orEmpty()),
rate = TextReference.Str(providerState.rate),
fromTokenAmount = TextReference.Str(txState.fromAmount.orEmpty()),
toTokenAmount = TextReference.Str(txState.toAmount.orEmpty()),
fromTokenFiatAmount = TextReference.Str(fromFiatAmount),
toTokenFiatAmount = TextReference.Str(toFiatAmount),
fromTokenIconState = fromTokenIconState,
toTokenIconState = toTokenIconState,
onSecondaryButtonClick = onSecondaryBtnClick,
@ -892,7 +889,7 @@ internal class StateBuilder(
return BigDecimalFormatter.formatFiatAmount(fiatAmount, appCurrency.code, appCurrency.symbol)
}
private fun getFormattedFiatAmount(amount: BigDecimal): String {
private fun getFormattedFiatAmount(amount: BigDecimal?): String {
val appCurrency = appCurrencyProvider()
return BigDecimalFormatter.formatFiatAmount(amount, appCurrency.code, appCurrency.symbol)

View file

@ -23,7 +23,6 @@ import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.shareText
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.swap.domain.models.domain.ExchangeProviderType
import com.tangem.feature.swap.domain.models.domain.SwapProvider
import com.tangem.feature.swap.models.SwapSuccessStateHolder
import com.tangem.feature.swap.presentation.R
@ -60,7 +59,7 @@ private fun SwapSuccessScreenContent(state: SwapSuccessStateHolder, padding: Pad
.background(TangemTheme.colors.background.secondary)
.padding(horizontal = TangemTheme.dimens.spacing16),
) {
TransactionDoneTitle(titleRes = R.string.swapping_success_view_title, date = 0L)
TransactionDoneTitle(titleRes = R.string.swapping_success_view_title, date = state.timestamp)
SpacerH16()
InputRowImage(
title = TextReference.Res(R.string.swapping_success_from_title),
@ -83,9 +82,9 @@ private fun SwapSuccessScreenContent(state: SwapSuccessStateHolder, padding: Pad
)
SpacerH16()
InputRowBestRate(
imageUrl = state.selectedProvider.imageLarge,
title = TextReference.Str(state.selectedProvider.name),
titleExtra = TextReference.Str(state.selectedProvider.type.name),
imageUrl = state.providerIcon,
title = state.providerName,
titleExtra = state.providerType,
subtitle = state.rate,
modifier = Modifier
.clip(TangemTheme.shapes.roundedCornersXMedium)
@ -153,13 +152,9 @@ private val state = SwapSuccessStateHolder(
timestamp = 0L,
txUrl = "https://www.google.com/#q=nam",
fee = TextReference.Str("1 000 DAI ~ 1 000 MATIC"),
selectedProvider = SwapProvider(
providerId = "1inch",
rateTypes = listOf(),
name = "1inch",
type = ExchangeProviderType.DEX,
imageLarge = "",
),
providerName = TextReference.Str("1inch"),
providerType = TextReference.Str(ExchangeProviderType.DEX.name),
providerIcon = "",
fromTokenAmount = TextReference.Str("1 000 DAI"),
toTokenAmount = TextReference.Str("1 000 MATIC"),
fromTokenFiatAmount = TextReference.Str("1 000 $"),

View file

@ -27,9 +27,7 @@ import com.tangem.feature.swap.presentation.SwapFragment
import com.tangem.feature.swap.router.SwapNavScreen
import com.tangem.feature.swap.router.SwapRouter
import com.tangem.feature.swap.ui.StateBuilder
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.Debouncer
import com.tangem.utils.coroutines.runCatching
import com.tangem.utils.coroutines.*
import com.tangem.utils.isNullOrZero
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
@ -401,7 +399,8 @@ internal class SwapViewModel @Inject constructor(
uiState = stateBuilder.createSuccessState(
uiState = uiState,
txState = it,
dataState = dataState,
fromAmount = dataState.amount?.toBigDecimal() ?: BigDecimal.ZERO,
toAmount = dataState.swapDataModel?.toTokenAmount?.value ?: BigDecimal.ZERO,
txUrl = url,
onSecondaryBtnClick = {
val txHash = it.txAddress