Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-08 14:49:51 +05:00
parent 972a287b1d
commit ef6918ce4a
20 changed files with 374 additions and 115 deletions

View file

@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.blockchain.common.Blockchain
import com.tangem.core.ui.components.transactions.state.TxHistoryState
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.TxInfo
import com.tangem.domain.txhistory.models.TxHistoryStateError
import com.tangem.domain.models.wallet.UserWallet
@ -17,6 +18,7 @@ internal class SetTxHistoryCountErrorTransformer(
private val error: TxHistoryStateError,
private val pendingTransactions: Set<TxInfo>,
private val clickIntents: WalletClickIntents,
private val currency: CryptoCurrency,
) : WalletStateTransformer(userWallet.walletId) {
private val txHistoryItemConverter by lazy {
@ -26,6 +28,7 @@ internal class SetTxHistoryCountErrorTransformer(
}
TxHistoryItemStateConverter(
currency = currency,
symbol = blockchain.currency,
decimals = blockchain.decimals(),
clickIntents = clickIntents,

View file

@ -9,6 +9,7 @@ import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.utils.toTimeFormat
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.TxInfo
import com.tangem.domain.models.network.TxInfo.TransactionStatus
import com.tangem.domain.models.network.TxInfo.TransactionType
@ -20,6 +21,7 @@ import com.tangem.utils.converter.Converter
import com.tangem.utils.toBriefAddressFormat
internal class TxHistoryItemStateConverter(
private val currency: CryptoCurrency,
private val symbol: String,
private val decimals: Int,
private val clickIntents: WalletClickIntents,
@ -49,7 +51,9 @@ internal class TxHistoryItemStateConverter(
R.drawable.ic_close_24
} else {
when (type) {
is TransactionType.Approve -> R.drawable.ic_doc_24
is TransactionType.YieldSupply.DeployContract,
is TransactionType.Approve,
-> R.drawable.ic_doc_24
is TransactionType.Staking.Stake,
is TransactionType.Staking.Vote,
is TransactionType.Staking.Restake,
@ -59,11 +63,16 @@ internal class TxHistoryItemStateConverter(
is TransactionType.Staking.Unstake,
is TransactionType.Staking.Withdraw,
-> R.drawable.ic_transaction_history_unstaking_24
is TransactionType.YieldSupply.Enter -> R.drawable.ic_connect_24
is TransactionType.YieldSupply.InitializeToken -> R.drawable.ic_gear_24
is TransactionType.YieldSupply.ReactivateToken -> R.drawable.ic_refresh_24
is TransactionType.YieldSupply.Exit -> R.drawable.ic_disconnect_24
is TransactionType.Operation,
is TransactionType.Swap,
is TransactionType.Transfer,
is TransactionType.YieldSupply,
is TransactionType.UnknownOperation,
TransactionType.YieldSupply.Send,
TransactionType.YieldSupply.Topup,
-> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24
}
}
@ -74,32 +83,81 @@ internal class TxHistoryItemStateConverter(
is TransactionType.Operation -> stringReference(type.name)
is TransactionType.Swap -> resourceReference(R.string.common_swap)
is TransactionType.Transfer -> resourceReference(R.string.common_transfer)
is TransactionType.YieldSupply.Enter -> resourceReference(R.string.yield_module_transaction_enter)
is TransactionType.YieldSupply.Exit -> resourceReference(R.string.yield_module_transaction_exit)
is TransactionType.YieldSupply.Topup -> resourceReference(R.string.yield_module_transaction_topup)
is TransactionType.Staking.Stake -> resourceReference(R.string.common_stake)
is TransactionType.Staking.Unstake -> resourceReference(R.string.common_unstake)
is TransactionType.Staking.Vote -> resourceReference(R.string.staking_vote)
is TransactionType.Staking.ClaimRewards -> resourceReference(R.string.common_claim_rewards)
is TransactionType.Staking.Withdraw -> resourceReference(R.string.staking_withdraw)
is TransactionType.Staking.Restake -> resourceReference(R.string.staking_restake)
is TransactionType.YieldSupply -> when (type) {
is TransactionType.YieldSupply.Enter -> resourceReference(R.string.yield_module_transaction_enter)
is TransactionType.YieldSupply.Exit -> resourceReference(R.string.yield_module_transaction_exit)
TransactionType.YieldSupply.Topup -> resourceReference(R.string.yield_module_transaction_topup)
TransactionType.YieldSupply.Send -> if (isOutgoing) {
resourceReference(R.string.common_transfer)
} else {
resourceReference(R.string.yield_module_transaction_withdraw)
}
is TransactionType.YieldSupply.DeployContract -> resourceReference(
R.string
.yield_module_transaction_deploy_contract,
)
is TransactionType.YieldSupply.InitializeToken -> resourceReference(
R.string
.yield_module_transaction_initialize,
)
is TransactionType.YieldSupply.ReactivateToken -> resourceReference(
R.string
.yield_module_transaction_reactivate,
)
}
is TransactionType.UnknownOperation -> resourceReference(R.string.transaction_history_operation)
}
private fun TxInfo.extractSubtitle(): TextReference {
return when (this.type) {
is TransactionType.YieldSupply.Enter -> {
val amount = amount.format { crypto(symbol = symbol, decimals = decimals) }
resourceReference(R.string.yield_module_transaction_enter_subtitle, wrappedList(amount))
}
is TransactionType.YieldSupply.Topup,
-> {
val amount = amount.format { crypto(symbol = symbol, decimals = decimals) }
resourceReference(R.string.yield_module_transaction_topup_subtitle, wrappedList(amount))
}
is TransactionType.YieldSupply.Exit -> {
val amount = amount.format { crypto(symbol = symbol, decimals = decimals) }
resourceReference(R.string.yield_module_transaction_exit_subtitle, wrappedList(amount))
return when (val type = this.type) {
is TransactionType.YieldSupply -> if (currency is CryptoCurrency.Coin) {
resourceReference(
R.string.transaction_history_transaction_for_address,
wrappedList(type.address?.toBriefAddressFormat().orEmpty()),
)
} else {
when (type) {
is TransactionType.YieldSupply.Enter -> {
val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) }
resourceReference(
R.string.yield_module_transaction_enter_subtitle,
wrappedList(amount),
)
}
TransactionType.YieldSupply.Topup -> {
val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) }
resourceReference(
R.string.yield_module_transaction_topup_subtitle,
wrappedList(amount),
)
}
TransactionType.YieldSupply.Send -> {
if (isOutgoing) {
extractSubtitleByAddressType()
} else {
val amount =
amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) }
resourceReference(
R.string.yield_module_transaction_exit_subtitle,
wrappedList(amount),
)
}
}
is TransactionType.YieldSupply.Exit -> {
val amount = amount.format { crypto(symbol = currency.symbol, decimals = currency.decimals) }
resourceReference(
R.string.yield_module_transaction_exit_subtitle,
wrappedList(amount),
)
}
else -> extractSubtitleByAddressType()
}
}
else -> extractSubtitleByAddressType()
}
@ -147,14 +205,18 @@ internal class TxHistoryItemStateConverter(
@Suppress("ComplexCondition")
private fun TxInfo.getAmount(): String {
if (type is TransactionType.Staking.Vote ||
type == TransactionType.Staking.ClaimRewards ||
type == TransactionType.Staking.Withdraw ||
type == TransactionType.YieldSupply.Enter ||
type == TransactionType.YieldSupply.Exit ||
type == TransactionType.YieldSupply.Topup
) {
return ""
when (type) {
is TransactionType.Staking.Vote,
TransactionType.Staking.ClaimRewards,
TransactionType.Staking.Withdraw,
-> return ""
is TransactionType.YieldSupply -> {
if (currency is CryptoCurrency.Token && type == TransactionType.YieldSupply.Send && !isOutgoing) {
return ""
}
}
else -> Unit
}
val prefix = when {
status == TransactionStatus.Failed -> ""

View file

@ -5,6 +5,7 @@ import androidx.paging.cachedIn
import androidx.paging.map
import arrow.core.Either
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.TxInfo
import com.tangem.domain.models.wallet.UserWallet
@ -58,7 +59,7 @@ internal class TxHistorySubscriber(
refresh = isRefresh,
).map { it.cachedIn(coroutineScope) }
setLoadedTxHistoryState(maybeTxHistoryItems)
setLoadedTxHistoryState(maybeTxHistoryItems, status.currency)
}
}
}
@ -67,18 +68,19 @@ internal class TxHistorySubscriber(
private fun setLoadingTxHistoryState(maybeTxHistoryItemCount: MaybeTxHistoryCount, status: CryptoCurrencyStatus) {
stateHolder.update(
maybeTxHistoryItemCount.fold(
ifLeft = {
ifLeft = { error ->
SetTxHistoryCountErrorTransformer(
userWallet = userWallet,
error = it,
error = error,
pendingTransactions = status.value.pendingTransactions,
currency = status.currency,
clickIntents = clickIntents,
)
},
ifRight = {
ifRight = { txCount ->
SetTxHistoryCountTransformer(
userWalletId = userWallet.walletId,
transactionsCount = it,
transactionsCount = txCount,
clickIntents = clickIntents,
)
},
@ -86,7 +88,7 @@ internal class TxHistorySubscriber(
)
}
private fun setLoadedTxHistoryState(maybeTxHistoryItems: MaybeTxHistoryItems) {
private fun setLoadedTxHistoryState(maybeTxHistoryItems: MaybeTxHistoryItems, currency: CryptoCurrency) {
stateHolder.update(
maybeTxHistoryItems.fold(
ifLeft = {
@ -102,6 +104,7 @@ internal class TxHistorySubscriber(
symbol = blockchain.currency,
decimals = blockchain.decimals(),
clickIntents = clickIntents,
currency = currency,
)
SetTxHistoryItemsTransformer(

View file

@ -5,6 +5,7 @@ import androidx.paging.cachedIn
import androidx.paging.map
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.TxInfo
import com.tangem.domain.models.wallet.UserWallet
@ -51,7 +52,7 @@ internal class TxHistorySubscriberV2(
refresh = isRefresh,
).map { it.cachedIn(coroutineScope) }
setLoadedTxHistoryState(maybeTxHistoryItems)
setLoadedTxHistoryState(maybeTxHistoryItems, currency = status.currency)
}
}
}
@ -60,18 +61,19 @@ internal class TxHistorySubscriberV2(
private fun setLoadingTxHistoryState(maybeTxHistoryItemCount: MaybeTxHistoryCount, status: CryptoCurrencyStatus) {
stateController.update(
maybeTxHistoryItemCount.fold(
ifLeft = {
ifLeft = { error ->
SetTxHistoryCountErrorTransformer(
userWallet = userWallet,
error = it,
error = error,
pendingTransactions = status.value.pendingTransactions,
clickIntents = clickIntents,
currency = status.currency,
)
},
ifRight = {
ifRight = { txCount ->
SetTxHistoryCountTransformer(
userWalletId = userWallet.walletId,
transactionsCount = it,
transactionsCount = txCount,
clickIntents = clickIntents,
)
},
@ -79,7 +81,7 @@ internal class TxHistorySubscriberV2(
)
}
private fun setLoadedTxHistoryState(maybeTxHistoryItems: MaybeTxHistoryItems) {
private fun setLoadedTxHistoryState(maybeTxHistoryItems: MaybeTxHistoryItems, currency: CryptoCurrency) {
stateController.update(
maybeTxHistoryItems.fold(
ifLeft = {
@ -92,6 +94,7 @@ internal class TxHistorySubscriberV2(
ifRight = { itemsFlow ->
val blockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain()
val itemConverter = TxHistoryItemStateConverter(
currency = currency,
symbol = blockchain.currency,
decimals = blockchain.decimals(),
clickIntents = clickIntents,