Updated on 2026-08-14
This commit is contained in:
parent
81cce1254d
commit
879c8d603b
19 changed files with 566 additions and 415 deletions
|
|
@ -418,20 +418,22 @@ internal object WalletPreviewData {
|
|||
listOf(
|
||||
TxHistoryState.TxHistoryItemState.GroupTitle("Today"),
|
||||
TxHistoryState.TxHistoryItemState.Transaction(
|
||||
TransactionState.Sending(
|
||||
TransactionState.Send(
|
||||
txHash = UUID.randomUUID().toString(),
|
||||
address = TextReference.Str("33BddS...ga2B"),
|
||||
amount = "-0.500913 BTC",
|
||||
timestamp = "8:41",
|
||||
status = TransactionState.Content.Status.Unconfirmed,
|
||||
),
|
||||
),
|
||||
TxHistoryState.TxHistoryItemState.GroupTitle("Yesterday"),
|
||||
TxHistoryState.TxHistoryItemState.Transaction(
|
||||
TransactionState.Sending(
|
||||
TransactionState.Send(
|
||||
txHash = UUID.randomUUID().toString(),
|
||||
address = TextReference.Str("33BddS...ga2B"),
|
||||
amount = "-0.500913 BTC",
|
||||
timestamp = "8:41",
|
||||
status = TransactionState.Content.Status.Confirmed,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -7,17 +7,13 @@ import com.tangem.common.Provider
|
|||
import com.tangem.core.ui.components.transactions.state.TransactionState
|
||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState.TxHistoryItemState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.extensions.isToday
|
||||
import com.tangem.utils.extensions.isYesterday
|
||||
import com.tangem.utils.toBriefAddressFormat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -27,7 +23,6 @@ import kotlinx.coroutines.flow.update
|
|||
import org.joda.time.DateTime
|
||||
import org.joda.time.DateTimeZone
|
||||
import org.joda.time.format.DateTimeFormatterBuilder
|
||||
import java.math.BigDecimal
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
|
|
@ -45,6 +40,10 @@ internal class WalletTxHistoryItemFlowConverter(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
) : Converter<Flow<PagingData<TxHistoryItem>>, TxHistoryState?> {
|
||||
|
||||
private val txHistoryItemConverter by lazy {
|
||||
WalletTxHistoryTransactionStateConverter(symbol = blockchain.currency, decimals = blockchain.decimals())
|
||||
}
|
||||
|
||||
/** Example, 2 Aug, 2023 */
|
||||
private val dateFormatter by lazy {
|
||||
DateTimeFormatterBuilder()
|
||||
|
|
@ -95,68 +94,7 @@ internal class WalletTxHistoryItemFlowConverter(
|
|||
}
|
||||
|
||||
private fun createTransactionState(item: TxHistoryItem): TransactionState {
|
||||
return when (item.type) {
|
||||
TxHistoryItem.TransactionType.Transfer -> {
|
||||
when (val direction = item.direction) {
|
||||
is TxHistoryItem.TransactionDirection.Incoming -> {
|
||||
createIncomingTransferTransaction(item, direction, blockchain)
|
||||
}
|
||||
is TxHistoryItem.TransactionDirection.Outgoing -> {
|
||||
createOutgoingTransferTransaction(item, direction, blockchain)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIncomingTransferTransaction(
|
||||
item: TxHistoryItem,
|
||||
direction: TxHistoryItem.TransactionDirection.Incoming,
|
||||
blockchain: Blockchain,
|
||||
): TransactionState {
|
||||
return when (item.status) {
|
||||
TxHistoryItem.TxStatus.Confirmed -> TransactionState.Receive(
|
||||
txHash = item.txHash,
|
||||
address = direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(blockchain = blockchain),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
)
|
||||
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Receiving(
|
||||
txHash = item.txHash,
|
||||
address = direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(blockchain = blockchain),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createOutgoingTransferTransaction(
|
||||
item: TxHistoryItem,
|
||||
direction: TxHistoryItem.TransactionDirection.Outgoing,
|
||||
blockchain: Blockchain,
|
||||
): TransactionState {
|
||||
return when (item.status) {
|
||||
TxHistoryItem.TxStatus.Confirmed -> TransactionState.Send(
|
||||
txHash = item.txHash,
|
||||
address = direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(blockchain = blockchain),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
)
|
||||
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Sending(
|
||||
txHash = item.txHash,
|
||||
address = direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(blockchain = blockchain),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun BigDecimal.toCryptoCurrencyFormat(blockchain: Blockchain): String {
|
||||
return BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = this,
|
||||
cryptoCurrency = blockchain.currency,
|
||||
decimals = blockchain.decimals(),
|
||||
)
|
||||
return txHistoryItemConverter.convert(value = item)
|
||||
}
|
||||
|
||||
private fun PagingData<TxHistoryItemState>.insertGroupTitle(): PagingData<TxHistoryItemState> {
|
||||
|
|
@ -202,14 +140,6 @@ internal class WalletTxHistoryItemFlowConverter(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get timestamp without formatting.
|
||||
* It's life hack that help us to add transaction's group title to flow.
|
||||
*
|
||||
* @see [convert]
|
||||
*/
|
||||
private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString()
|
||||
|
||||
private fun TxHistoryItemState?.getTimestamp(): Long? {
|
||||
return if (this is TxHistoryItemState.Transaction && this.state is TransactionState.Content) {
|
||||
val txContent = this.state as TransactionState.Content
|
||||
|
|
@ -242,9 +172,4 @@ internal class WalletTxHistoryItemFlowConverter(
|
|||
DateTime(this.toLong(), DateTimeZone.getDefault()),
|
||||
)
|
||||
}
|
||||
|
||||
private fun TxHistoryItem.TransactionDirection.extractAddress(): TextReference = when (val addr = address) {
|
||||
TxHistoryItem.Address.Multiple -> TextReference.Res(R.string.transaction_history_multiple_addresses)
|
||||
is TxHistoryItem.Address.Single -> TextReference.Str(addr.rawAddress.toBriefAddressFormat())
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.factory.txhistory
|
||||
|
||||
import com.tangem.core.ui.components.transactions.state.TransactionState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.toBriefAddressFormat
|
||||
import com.tangem.utils.toFormattedCurrencyString
|
||||
import java.math.BigDecimal
|
||||
|
||||
class WalletTxHistoryTransactionStateConverter(
|
||||
private val symbol: String,
|
||||
private val decimals: Int,
|
||||
) : Converter<TxHistoryItem, TransactionState> {
|
||||
|
||||
override fun convert(value: TxHistoryItem): TransactionState {
|
||||
return createTransactionStateItem(item = value)
|
||||
}
|
||||
|
||||
// TODO: Finalize transaction types [REDACTED_JIRA]
|
||||
private fun createTransactionStateItem(item: TxHistoryItem): TransactionState {
|
||||
return when (val type = item.type) {
|
||||
TxHistoryItem.TransactionType.Transfer -> mapTransfer(item)
|
||||
TxHistoryItem.TransactionType.Approve -> mapApprove(item)
|
||||
TxHistoryItem.TransactionType.Swap -> mapSwap(item)
|
||||
TxHistoryItem.TransactionType.Deposit -> TransactionState.Custom(
|
||||
txHash = item.txHash,
|
||||
address = item.direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
status = item.status.tiUiStatus(),
|
||||
title = TextReference.Str("Deposit"),
|
||||
subtitle = item.direction.extractAddress(),
|
||||
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
|
||||
)
|
||||
TxHistoryItem.TransactionType.Submit -> TransactionState.Custom(
|
||||
txHash = item.txHash,
|
||||
address = item.direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
status = item.status.tiUiStatus(),
|
||||
title = TextReference.Str("Submit"),
|
||||
subtitle = item.direction.extractAddress(),
|
||||
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
|
||||
)
|
||||
TxHistoryItem.TransactionType.Supply -> TransactionState.Custom(
|
||||
txHash = item.txHash,
|
||||
address = item.direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
status = item.status.tiUiStatus(),
|
||||
title = TextReference.Str("Supply"),
|
||||
subtitle = item.direction.extractAddress(),
|
||||
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
|
||||
)
|
||||
TxHistoryItem.TransactionType.Unoswap -> TransactionState.Custom(
|
||||
txHash = item.txHash,
|
||||
address = item.direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
status = item.status.tiUiStatus(),
|
||||
title = TextReference.Str("Unoswap"),
|
||||
subtitle = item.direction.extractAddress(),
|
||||
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
|
||||
)
|
||||
TxHistoryItem.TransactionType.Withdraw -> TransactionState.Custom(
|
||||
txHash = item.txHash,
|
||||
address = item.direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
status = item.status.tiUiStatus(),
|
||||
title = TextReference.Str("Withdraw"),
|
||||
subtitle = item.direction.extractAddress(),
|
||||
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
|
||||
)
|
||||
is TxHistoryItem.TransactionType.Custom -> TransactionState.Custom(
|
||||
txHash = item.txHash,
|
||||
address = item.direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
status = item.status.tiUiStatus(),
|
||||
title = TextReference.Str(type.id),
|
||||
subtitle = item.direction.extractAddress(),
|
||||
isIncoming = item.direction is TxHistoryItem.TransactionDirection.Incoming,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapTransfer(item: TxHistoryItem): TransactionState {
|
||||
return when (item.direction) {
|
||||
is TxHistoryItem.TransactionDirection.Incoming -> TransactionState.Receive(
|
||||
txHash = item.txHash,
|
||||
address = item.direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
status = item.status.tiUiStatus(),
|
||||
)
|
||||
is TxHistoryItem.TransactionDirection.Outgoing -> TransactionState.Send(
|
||||
txHash = item.txHash,
|
||||
address = item.direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
status = item.status.tiUiStatus(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapApprove(item: TxHistoryItem): TransactionState {
|
||||
return TransactionState.Approve(
|
||||
txHash = item.txHash,
|
||||
address = item.direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
status = item.status.tiUiStatus(),
|
||||
)
|
||||
}
|
||||
private fun mapSwap(item: TxHistoryItem): TransactionState {
|
||||
return TransactionState.Swap(
|
||||
txHash = item.txHash,
|
||||
address = item.direction.extractAddress(),
|
||||
amount = item.amount.toCryptoCurrencyFormat(),
|
||||
timestamp = item.getRawTimestamp(),
|
||||
status = item.status.tiUiStatus(),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get timestamp without formatting.
|
||||
* It's life hack that help us to add transaction's group title to flow.
|
||||
*
|
||||
* @see [convert]
|
||||
*/
|
||||
private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString()
|
||||
|
||||
private fun BigDecimal.toCryptoCurrencyFormat(): String {
|
||||
return toFormattedCurrencyString(currency = symbol, decimals = decimals)
|
||||
}
|
||||
|
||||
private fun TxHistoryItem.TransactionDirection.extractAddress(): TextReference = when (val addr = address) {
|
||||
TxHistoryItem.Address.Multiple -> TextReference.Res(R.string.transaction_history_multiple_addresses)
|
||||
is TxHistoryItem.Address.Single -> TextReference.Str(addr.rawAddress.toBriefAddressFormat())
|
||||
}
|
||||
|
||||
private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) {
|
||||
TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed
|
||||
TxHistoryItem.TransactionStatus.Failed -> TransactionState.Content.Status.Failed
|
||||
TxHistoryItem.TransactionStatus.Unconfirmed -> TransactionState.Content.Status.Unconfirmed
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +38,6 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|||
import com.tangem.domain.tokens.model.NetworkGroup
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||
|
|
@ -757,9 +756,9 @@ internal class WalletViewModel @Inject constructor(
|
|||
updateNotifications(index)
|
||||
}
|
||||
|
||||
private fun updateTxHistory(network: Network) {
|
||||
private fun updateTxHistory(currency: CryptoCurrency) {
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val txHistoryItemsCountEither = txHistoryItemsCountUseCase(network)
|
||||
val txHistoryItemsCountEither = txHistoryItemsCountUseCase(currency.network)
|
||||
|
||||
uiState = stateFactory.getLoadingTxHistoryState(
|
||||
itemsCountEither = txHistoryItemsCountEither,
|
||||
|
|
@ -767,9 +766,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
txHistoryItemsCountEither.onRight {
|
||||
uiState = stateFactory.getLoadedTxHistoryState(
|
||||
txHistoryEither = txHistoryItemsUseCase(
|
||||
network,
|
||||
).map {
|
||||
txHistoryEither = txHistoryItemsUseCase(currency = currency).map {
|
||||
it.cachedIn(viewModelScope)
|
||||
},
|
||||
)
|
||||
|
|
@ -786,7 +783,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
maybeCryptoCurrencyStatus.onRight { status ->
|
||||
singleWalletCryptoCurrencyStatus = status
|
||||
updateButtons(userWalletId = userWalletId, currencyStatus = status)
|
||||
updateTxHistory(status.currency.network)
|
||||
updateTxHistory(status.currency)
|
||||
}
|
||||
}
|
||||
.flowOn(dispatchers.io)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue