Updated on 2026-08-14

This commit is contained in:
Tangem 2026-06-16 19:08:38 +05:00
parent f0898f2873
commit 2e8d0bc03b
9 changed files with 132 additions and 82 deletions

View file

@ -120,12 +120,14 @@ internal class PreviewEmptyExpressTransactionsComponent : ExpressTransactionsCom
toAmountSymbol = toSymbol,
toCurrencyIcon = CurrencyIconState.Empty(),
toAddress = "",
toAmountDecimals = 2,
fromAmount = TextReference.Str(fromAmount),
fromAmountValue = fromAmount.toBigDecimal(),
fromFiatAmount = null,
fromAmountSymbol = fromSymbol,
fromCurrencyIcon = CurrencyIconState.Empty(),
fromAddress = "",
fromAmountDecimals = 2,
),
providerName = "Preview Provider",
providerImageUrl = "",

View file

@ -61,9 +61,7 @@ internal class TokenDetailsOnrampTransactionStateConverter(
),
timestampAgoFormatted = mapFormattedDate(value.timestamp),
activeStatus = value.status.toActiveStatusText(cryptoCurrency.name),
toAmount = stringReference(
value.toAmount.format { crypto(cryptoCurrency) },
),
toAmount = stringReference(value.toAmount.format { crypto(cryptoCurrency) }),
toAmountValue = value.toAmount,
toFiatAmount = stringReference(
statusValue?.fiatRate?.multiply(value.toAmount).format {
@ -73,6 +71,7 @@ internal class TokenDetailsOnrampTransactionStateConverter(
)
},
),
toAmountDecimals = cryptoCurrency.decimals,
toAmountSymbol = cryptoCurrency.symbol,
toCurrencyIcon = iconStateConverter.convert(cryptoCurrency),
toAddress = statusValue?.networkAddress?.defaultAddress?.value.orEmpty(),
@ -91,6 +90,7 @@ internal class TokenDetailsOnrampTransactionStateConverter(
url = value.fromCurrency.image,
fallbackResId = R.drawable.ic_currency_24,
),
fromAmountDecimals = value.fromCurrency.precision,
fromAddress = null,
iconState = value.status.toIconState(),
onGoToProviderClick = { url ->

View file

@ -59,7 +59,7 @@ internal class TokenDetailsSwapTransactionsStateConverter(
fun convert(
savedTransactions: List<SavedSwapTransactionListModel>,
accountStatuses: Map<Account, CryptoCurrencyStatus>,
accountStatuses: Map<Account, List<CryptoCurrencyStatus>>,
): PersistentList<ExchangeUM> {
val result = mutableListOf<ExchangeUM>()
@ -67,29 +67,18 @@ internal class TokenDetailsSwapTransactionsStateConverter(
.forEach { swapTransaction ->
val toCryptoCurrency = swapTransaction.toCryptoCurrency
val fromCryptoCurrency = swapTransaction.fromCryptoCurrency
val toCryptoCurrencyRawId = swapTransaction.toCryptoCurrency.id.rawCurrencyId
val fromCryptoCurrencyRawId = swapTransaction.fromCryptoCurrency.id.rawCurrencyId
var fromCryptoCurrencyStatus: CryptoCurrencyStatus? = null
var toCryptoCurrencyStatus: CryptoCurrencyStatus? = null
val (fromCryptoCurrencyStatus, toCryptoCurrencyStatus) = extractCryptoCurrencyStatuses(
swapTransaction = swapTransaction,
accountStatuses = accountStatuses,
)
swapTransaction.transactions.forEach { transaction ->
val toAmount = transaction.toCryptoAmount
val fromAmount = transaction.fromCryptoAmount
var toFiatAmount: BigDecimal? = null
var fromFiatAmount: BigDecimal? = null
accountStatuses.forEach { (account, cryptoCurrencyStatus) ->
if (cryptoCurrencyStatus.currency.id.rawCurrencyId == fromCryptoCurrencyRawId &&
account.userWalletId.stringValue == swapTransaction.fromUserWalletId
) {
fromFiatAmount = cryptoCurrencyStatus.value.fiatRate?.multiply(fromAmount)
fromCryptoCurrencyStatus = cryptoCurrencyStatus
}
if (cryptoCurrencyStatus.currency.id.rawCurrencyId == toCryptoCurrencyRawId &&
account.userWalletId.stringValue == swapTransaction.toUserWalletId
) {
toFiatAmount = cryptoCurrencyStatus.value.fiatRate?.multiply(toAmount)
toCryptoCurrencyStatus = cryptoCurrencyStatus
}
}
val toFiatAmount = toCryptoCurrencyStatus?.value?.fiatRate?.multiply(toAmount)
val fromFiatAmount = fromCryptoCurrencyStatus?.value?.fiatRate?.multiply(fromAmount)
val statusModel = transaction.status
val notification = getNotification(
status = statusModel?.status,
@ -153,6 +142,34 @@ internal class TokenDetailsSwapTransactionsStateConverter(
)
}
private fun extractCryptoCurrencyStatuses(
swapTransaction: SavedSwapTransactionListModel,
accountStatuses: Map<Account, List<CryptoCurrencyStatus>>,
): Pair<CryptoCurrencyStatus?, CryptoCurrencyStatus?> {
val toCryptoCurrencyId = swapTransaction.toCryptoCurrency.id
val fromCryptoCurrencyId = swapTransaction.fromCryptoCurrency.id
var fromCryptoCurrencyStatus: CryptoCurrencyStatus? = null
var toCryptoCurrencyStatus: CryptoCurrencyStatus? = null
accountStatuses.forEach { (account, cryptoCurrencyStatuses) ->
cryptoCurrencyStatuses.forEach { cryptoCurrencyStatus ->
if (cryptoCurrencyStatus.currency.id == fromCryptoCurrencyId &&
account.userWalletId.stringValue == swapTransaction.fromUserWalletId
) {
fromCryptoCurrencyStatus = cryptoCurrencyStatus
}
if (cryptoCurrencyStatus.currency.id == toCryptoCurrencyId &&
account.userWalletId.stringValue == swapTransaction.toUserWalletId
) {
toCryptoCurrencyStatus = cryptoCurrencyStatus
}
}
}
return fromCryptoCurrencyStatus to toCryptoCurrencyStatus
}
@Suppress("LongParameterList")
private fun createStateInfo(
transaction: SavedSwapTransactionModel,
@ -182,12 +199,14 @@ internal class TokenDetailsSwapTransactionsStateConverter(
toFiatAmount = getFiatAmount(toFiatAmount),
toCurrencyIcon = iconStateConverter.convert(toCryptoCurrency),
toAmountSymbol = toCryptoCurrency.symbol,
toAmountDecimals = toCryptoCurrency.decimals,
toAddress = toStatusValue?.networkAddress?.defaultAddress?.value.orEmpty(),
fromAmount = getCryptoAmount(transaction.fromCryptoAmount, fromCryptoCurrency),
fromAmountValue = transaction.fromCryptoAmount,
fromFiatAmount = getFiatAmount(fromFiatAmount),
fromCurrencyIcon = iconStateConverter.convert(fromCryptoCurrency),
fromAmountSymbol = fromCryptoCurrency.symbol,
fromAmountDecimals = fromCryptoCurrency.decimals,
fromAddress = fromStatusValue?.networkAddress?.defaultAddress?.value.orEmpty(),
onClick = { clickIntents.onExpressTransactionClick(transaction.txId) },
onGoToProviderClick = { url ->

View file

@ -67,13 +67,12 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
).conflate()
.map { savedTransactions ->
val accountStatuses = savedTransactions
?.flatMap { swapTransaction ->
setOf(
?.flatMapTo(mutableSetOf()) { swapTransaction ->
listOf(
swapTransaction.fromAccount to swapTransaction.fromCryptoCurrency,
swapTransaction.toAccount to swapTransaction.toCryptoCurrency,
)
}
?.toMap()
?.getStatuses()
.orEmpty()
@ -199,7 +198,7 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
private fun getExchangeStatusState(
savedTransactions: List<SavedSwapTransactionListModel>?,
accountStatuses: Map<Account, CryptoCurrencyStatus>,
accountStatuses: Map<Account, List<CryptoCurrencyStatus>>,
): PersistentList<ExchangeUM> {
if (savedTransactions == null) {
return persistentListOf()
@ -231,7 +230,7 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
}
}
private suspend fun Map<Account?, CryptoCurrency>.getStatuses(): Map<Account, CryptoCurrencyStatus> {
private suspend fun Set<Pair<Account?, CryptoCurrency>>.getStatuses(): Map<Account, List<CryptoCurrencyStatus>> {
return mapNotNull { (account, cryptoCurrency) ->
when (account) {
is Account.CryptoPortfolio -> {
@ -248,7 +247,10 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
).getOrNull()
else -> null
}
}.toMap()
}.groupBy(
keySelector = { (account, _) -> account },
valueTransform = { (_, status) -> status },
)
}
@AssistedFactory

View file

@ -54,12 +54,14 @@ class ExpressStatusBottomSheetStateProvider : PreviewParameterProvider<ExpressSt
toAmountSymbol = "BTC",
toCurrencyIcon = CurrencyIconState.Empty(),
toAddress = "0x",
toAmountDecimals = 2,
fromAmount = TextReference.Str("5000 USDT"),
fromAmountValue = "5000".toBigDecimal(),
fromFiatAmount = TextReference.Str("$5000"),
fromAmountSymbol = "USDT",
fromCurrencyIcon = CurrencyIconState.Empty(),
fromAddress = "0x",
fromAmountDecimals = 2,
),
provider = SwapProvider(
providerId = "1",

View file

@ -46,6 +46,8 @@ import com.tangem.core.ui.ds.image.TangemIcon
import com.tangem.core.ui.ds.image.TangemIconUM
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreviewRedesign
@ -53,7 +55,6 @@ import com.tangem.core.ui.res.TangemThemeRedesign
import com.tangem.core.ui.utils.toPx
import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM
import com.tangem.features.tokendetails.impl.R
import com.tangem.utils.extensions.stripZeroPlainString
import kotlinx.coroutines.launch
import java.io.File
import java.math.BigDecimal
@ -128,55 +129,7 @@ private fun ExpressShareImageContent(
.matchParentSize()
.background(TangemColorPalette.Black),
) {
Column(
modifier = Modifier.padding(
start = 40.dp,
end = 40.dp,
top = 40.dp,
bottom = 20.dp,
),
) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.img_tangem_logo_90_24),
contentDescription = null,
tint = TangemColorPalette.White,
)
SpacerH(36.dp)
ExpressShareImageAmount(
prefix = stringResourceSafe(R.string.common_send),
amountValue = state.info.fromAmountValue,
currencyIconState = state.info.fromCurrencyIcon,
currencySymbol = state.info.fromAmountSymbol,
)
ExpressShareImageAddress(
prefix = stringResourceSafe(R.string.common_from),
address = state.info.fromAddress,
)
SpacerH(24.dp)
ExpressShareImageSeparator()
SpacerH(24.dp)
ExpressShareImageAmount(
prefix = stringResourceSafe(R.string.common_receive),
amountValue = state.info.toAmountValue,
currencyIconState = state.info.toCurrencyIcon,
currencySymbol = state.info.toAmountSymbol,
)
ExpressShareImageAddress(
prefix = stringResourceSafe(R.string.common_to),
address = state.info.toAddress,
)
SpacerH(24.dp)
ExpressShareImageProvider(state)
Text(
text = stringResourceSafe(R.string.express_transaction_id, state.info.txExternalId.orEmpty()),
style = TangemTheme.typography2.bodySemibold16,
color = TangemTheme.colors3.text.staticDark.secondary,
)
}
ExpressShareInnerContent(state = state)
Image(
painter = painterResource(R.drawable.img_share_express_background),
contentDescription = null,
@ -188,10 +141,71 @@ private fun ExpressShareImageContent(
}
}
@Composable
private fun ExpressShareInnerContent(state: ExpressTransactionStateUM) {
Column(
modifier = Modifier.padding(
start = 40.dp,
end = 40.dp,
top = 40.dp,
bottom = 20.dp,
),
) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.img_tangem_logo_90_24),
contentDescription = null,
tint = TangemColorPalette.White,
)
SpacerH(36.dp)
ExpressShareImageAmount(
prefix = stringResourceSafe(R.string.common_send),
amount = state.info.fromAmountValue,
decimals = state.info.fromAmountDecimals,
currencyIconState = state.info.fromCurrencyIcon,
currencySymbol = state.info.fromAmountSymbol,
)
ExpressShareImageAddress(
prefix = stringResourceSafe(R.string.common_from),
address = state.info.fromAddress,
)
SpacerH(24.dp)
ExpressShareImageSeparator()
SpacerH(24.dp)
ExpressShareImageAmount(
prefix = stringResourceSafe(R.string.common_receive),
amount = state.info.toAmountValue,
decimals = state.info.toAmountDecimals,
currencyIconState = state.info.toCurrencyIcon,
currencySymbol = state.info.toAmountSymbol,
)
ExpressShareImageAddress(
prefix = stringResourceSafe(R.string.common_to),
address = state.info.toAddress,
)
SpacerH(24.dp)
ExpressShareImageProvider(state)
if (state.info.txExternalId != null) {
Text(
text = stringResourceSafe(
R.string.express_transaction_id,
state.info.txExternalId.orEmpty(),
),
style = TangemTheme.typography2.bodySemibold16,
color = TangemTheme.colors3.text.staticDark.secondary,
)
}
}
}
@Composable
private fun ExpressShareImageAmount(
prefix: String,
amountValue: BigDecimal,
amount: BigDecimal,
decimals: Int,
currencyIconState: CurrencyIconState,
currencySymbol: String,
) {
@ -205,7 +219,12 @@ private fun ExpressShareImageAmount(
style = TangemTheme.typography2.bodySemibold16,
)
Text(
text = amountValue.stripZeroPlainString(),
text = amount.format {
crypto(
symbol = "",
decimals = decimals,
)
},
color = TangemTheme.colors3.text.staticDark.primary,
style = TangemTheme.typography2.bodySemibold16,
)

View file

@ -73,6 +73,7 @@ internal class SingleWalletOnrampTransactionConverter(
},
),
toAmountSymbol = currency.symbol,
toAmountDecimals = currency.decimals,
toCurrencyIcon = iconStateConverter.convert(currency),
toAddress = status.networkAddress?.defaultAddress?.value.orEmpty(),
fromAmount = stringReference(
@ -86,6 +87,7 @@ internal class SingleWalletOnrampTransactionConverter(
fromAmountValue = value.fromAmount,
fromFiatAmount = null,
fromAmountSymbol = value.fromCurrency.code,
fromAmountDecimals = value.fromCurrency.precision,
fromCurrencyIcon = CurrencyIconState.FiatIcon(
url = value.fromCurrency.image,
fallbackResId = R.drawable.ic_currency_24,