Transaction code cleanup (#1793)
* Transaction code cleanup * Code cleanup * Code cleanup
This commit is contained in:
parent
2c37d086f0
commit
79f756b580
|
@ -2,16 +2,10 @@ package co.electriccoin.zcash.ui.common.mapper
|
|||
|
||||
import cash.z.ecc.android.sdk.model.TransactionPool
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionData
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVE_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SENDING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SEND_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SENT
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDING_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.ReceiveTransaction
|
||||
import co.electriccoin.zcash.ui.common.repository.SendTransaction
|
||||
import co.electriccoin.zcash.ui.common.repository.ShieldTransaction
|
||||
import co.electriccoin.zcash.ui.common.repository.Transaction
|
||||
import co.electriccoin.zcash.ui.common.usecase.ListTransactionData
|
||||
import co.electriccoin.zcash.ui.design.util.StringResource
|
||||
import co.electriccoin.zcash.ui.design.util.StringResourceColor
|
||||
|
@ -22,80 +16,72 @@ import co.electriccoin.zcash.ui.screen.transactionhistory.TransactionState
|
|||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneId
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.temporal.ChronoUnit
|
||||
|
||||
class TransactionHistoryMapper {
|
||||
fun createTransactionState(
|
||||
transaction: ListTransactionData,
|
||||
data: ListTransactionData,
|
||||
restoreTimestamp: Instant,
|
||||
onTransactionClick: (TransactionData) -> Unit
|
||||
onTransactionClick: (Transaction) -> Unit
|
||||
): TransactionState {
|
||||
val transactionDate =
|
||||
transaction.data.overview.blockTimeEpochSeconds
|
||||
?.let { blockTimeEpochSeconds ->
|
||||
Instant.ofEpochSecond(blockTimeEpochSeconds).atZone(ZoneId.systemDefault())
|
||||
}
|
||||
|
||||
return TransactionState(
|
||||
key = transaction.data.overview.txId.txIdString(),
|
||||
icon = getIcon(transaction),
|
||||
title = getTitle(transaction),
|
||||
subtitle = getSubtitle(transactionDate),
|
||||
isShielded = isShielded(transaction),
|
||||
value = getValue(transaction),
|
||||
onClick = { onTransactionClick(transaction.data) },
|
||||
isUnread = isUnread(transaction, transactionDate, restoreTimestamp)
|
||||
key = data.transaction.id.txIdString(),
|
||||
icon = getIcon(data),
|
||||
title = getTitle(data),
|
||||
subtitle = getSubtitle(data),
|
||||
isShielded = isShielded(data),
|
||||
value = getValue(data),
|
||||
onClick = { onTransactionClick(data.transaction) },
|
||||
isUnread = isUnread(data, restoreTimestamp)
|
||||
)
|
||||
}
|
||||
|
||||
private fun isUnread(
|
||||
transaction: ListTransactionData,
|
||||
transactionDateTime: ZonedDateTime?,
|
||||
data: ListTransactionData,
|
||||
restoreTimestamp: Instant,
|
||||
): Boolean {
|
||||
val hasMemo = transaction.data.overview.memoCount > 0
|
||||
val transactionDateTime = data.transaction.timestamp?.atZone(ZoneId.systemDefault())
|
||||
val hasMemo = data.transaction.memoCount > 0
|
||||
val transactionDate = transactionDateTime?.toLocalDate() ?: LocalDate.now()
|
||||
val restoreDate = restoreTimestamp.atZone(ZoneId.systemDefault()).toLocalDate()
|
||||
|
||||
return if (hasMemo && transactionDate < restoreDate) {
|
||||
false
|
||||
} else {
|
||||
val transactionMetadata = transaction.metadata
|
||||
val transactionMetadata = data.metadata
|
||||
hasMemo && (transactionMetadata == null || transactionMetadata.isRead.not())
|
||||
}
|
||||
}
|
||||
|
||||
private fun getIcon(transaction: ListTransactionData) =
|
||||
when (transaction.data.state) {
|
||||
SENT -> R.drawable.ic_transaction_sent
|
||||
SENDING -> R.drawable.ic_transaction_send_pending
|
||||
SEND_FAILED -> R.drawable.ic_transaction_send_failed
|
||||
|
||||
RECEIVED -> R.drawable.ic_transaction_received
|
||||
RECEIVING -> R.drawable.ic_transaction_receive_pending
|
||||
RECEIVE_FAILED -> R.drawable.ic_transaction_receive_pending
|
||||
|
||||
SHIELDED -> R.drawable.ic_transaction_shielded
|
||||
SHIELDING -> R.drawable.ic_transaction_shield_pending
|
||||
SHIELDING_FAILED -> R.drawable.ic_transaction_shield_failed
|
||||
private fun getIcon(data: ListTransactionData) =
|
||||
when (data.transaction) {
|
||||
is SendTransaction.Success -> R.drawable.ic_transaction_sent
|
||||
is SendTransaction.Pending -> R.drawable.ic_transaction_send_pending
|
||||
is SendTransaction.Failed -> R.drawable.ic_transaction_send_failed
|
||||
is ReceiveTransaction.Success -> R.drawable.ic_transaction_received
|
||||
is ReceiveTransaction.Pending -> R.drawable.ic_transaction_receive_pending
|
||||
is ReceiveTransaction.Failed -> R.drawable.ic_transaction_receive_pending
|
||||
is ShieldTransaction.Success -> R.drawable.ic_transaction_shielded
|
||||
is ShieldTransaction.Pending -> R.drawable.ic_transaction_shield_pending
|
||||
is ShieldTransaction.Failed -> R.drawable.ic_transaction_shield_failed
|
||||
}
|
||||
|
||||
private fun getTitle(transaction: ListTransactionData) =
|
||||
when (transaction.data.state) {
|
||||
SENT -> stringRes(R.string.transaction_history_sent)
|
||||
SENDING -> stringRes(R.string.transaction_history_sending)
|
||||
SEND_FAILED -> stringRes(R.string.transaction_history_sending_failed)
|
||||
RECEIVED -> stringRes(R.string.transaction_history_received)
|
||||
RECEIVING -> stringRes(R.string.transaction_history_receiving)
|
||||
RECEIVE_FAILED -> stringRes(R.string.transaction_history_receiving_failed)
|
||||
SHIELDED -> stringRes(R.string.transaction_history_shielded)
|
||||
SHIELDING -> stringRes(R.string.transaction_history_shielding)
|
||||
SHIELDING_FAILED -> stringRes(R.string.transaction_history_shielding_failed)
|
||||
private fun getTitle(data: ListTransactionData) =
|
||||
when (data.transaction) {
|
||||
is SendTransaction.Success -> stringRes(R.string.transaction_history_sent)
|
||||
is SendTransaction.Pending -> stringRes(R.string.transaction_history_sending)
|
||||
is SendTransaction.Failed -> stringRes(R.string.transaction_history_sending_failed)
|
||||
is ReceiveTransaction.Success -> stringRes(R.string.transaction_history_received)
|
||||
is ReceiveTransaction.Pending -> stringRes(R.string.transaction_history_receiving)
|
||||
is ReceiveTransaction.Failed -> stringRes(R.string.transaction_history_receiving_failed)
|
||||
is ShieldTransaction.Success -> stringRes(R.string.transaction_history_shielded)
|
||||
is ShieldTransaction.Pending -> stringRes(R.string.transaction_history_shielding)
|
||||
is ShieldTransaction.Failed -> stringRes(R.string.transaction_history_shielding_failed)
|
||||
}
|
||||
|
||||
private fun getSubtitle(transactionDate: ZonedDateTime?): StringResource? {
|
||||
if (transactionDate == null) return null
|
||||
private fun getSubtitle(data: ListTransactionData): StringResource? {
|
||||
val timestamp = data.transaction.timestamp ?: return null
|
||||
val transactionDate = timestamp.atZone(ZoneId.systemDefault())
|
||||
val daysBetween = ChronoUnit.DAYS.between(transactionDate.toLocalDate(), LocalDate.now())
|
||||
return when {
|
||||
LocalDate.now() == transactionDate.toLocalDate() ->
|
||||
|
@ -111,71 +97,72 @@ class TransactionHistoryMapper {
|
|||
}
|
||||
}
|
||||
|
||||
private fun isShielded(transaction: ListTransactionData) =
|
||||
transaction.data.transactionOutputs
|
||||
private fun isShielded(data: ListTransactionData) =
|
||||
data.transaction
|
||||
.transactionOutputs
|
||||
.none { output -> output.pool == TransactionPool.TRANSPARENT } &&
|
||||
!transaction.data.overview.isShielding
|
||||
data.transaction !is ShieldTransaction
|
||||
|
||||
private fun getValue(transaction: ListTransactionData) =
|
||||
when (transaction.data.state) {
|
||||
SENT,
|
||||
SENDING ->
|
||||
private fun getValue(data: ListTransactionData) =
|
||||
when (data.transaction) {
|
||||
is SendTransaction.Success,
|
||||
is SendTransaction.Pending ->
|
||||
StyledStringResource(
|
||||
stringRes(
|
||||
R.string.transaction_history_minus,
|
||||
stringRes(transaction.data.overview.netValue)
|
||||
stringRes(data.transaction.amount)
|
||||
)
|
||||
)
|
||||
|
||||
SEND_FAILED ->
|
||||
is SendTransaction.Failed ->
|
||||
StyledStringResource(
|
||||
stringRes(
|
||||
R.string.transaction_history_minus,
|
||||
stringRes(transaction.data.overview.netValue)
|
||||
stringRes(data.transaction.amount)
|
||||
),
|
||||
StringResourceColor.NEGATIVE
|
||||
)
|
||||
|
||||
RECEIVED ->
|
||||
is ReceiveTransaction.Success ->
|
||||
StyledStringResource(
|
||||
stringRes(
|
||||
R.string.transaction_history_plus,
|
||||
stringRes(transaction.data.overview.netValue)
|
||||
stringRes(data.transaction.amount)
|
||||
),
|
||||
StringResourceColor.POSITIVE
|
||||
)
|
||||
|
||||
RECEIVING ->
|
||||
is ReceiveTransaction.Pending ->
|
||||
StyledStringResource(
|
||||
stringRes(
|
||||
R.string.transaction_history_plus,
|
||||
stringRes(transaction.data.overview.netValue)
|
||||
stringRes(data.transaction.amount)
|
||||
),
|
||||
)
|
||||
|
||||
RECEIVE_FAILED ->
|
||||
is ReceiveTransaction.Failed ->
|
||||
StyledStringResource(
|
||||
stringRes(
|
||||
R.string.transaction_history_plus,
|
||||
stringRes(transaction.data.overview.netValue)
|
||||
stringRes(data.transaction.amount)
|
||||
),
|
||||
StringResourceColor.NEGATIVE
|
||||
)
|
||||
|
||||
SHIELDED,
|
||||
SHIELDING ->
|
||||
is ShieldTransaction.Success,
|
||||
is ShieldTransaction.Pending ->
|
||||
StyledStringResource(
|
||||
stringRes(
|
||||
R.string.transaction_history_plus,
|
||||
stringRes(transaction.data.overview.totalSpent)
|
||||
stringRes(data.transaction.amount)
|
||||
)
|
||||
)
|
||||
|
||||
SHIELDING_FAILED ->
|
||||
is ShieldTransaction.Failed ->
|
||||
StyledStringResource(
|
||||
stringRes(
|
||||
R.string.transaction_history_plus,
|
||||
stringRes(transaction.data.overview.totalSpent)
|
||||
stringRes(data.transaction.amount)
|
||||
),
|
||||
StringResourceColor.NEGATIVE
|
||||
)
|
||||
|
|
|
@ -3,17 +3,12 @@ package co.electriccoin.zcash.ui.common.repository
|
|||
import cash.z.ecc.android.sdk.model.TransactionId
|
||||
import cash.z.ecc.android.sdk.model.TransactionOutput
|
||||
import cash.z.ecc.android.sdk.model.TransactionOverview
|
||||
import cash.z.ecc.android.sdk.model.TransactionState.Confirmed
|
||||
import cash.z.ecc.android.sdk.model.TransactionState.Expired
|
||||
import cash.z.ecc.android.sdk.model.TransactionState.Pending
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import co.electriccoin.zcash.ui.common.datasource.AccountDataSource
|
||||
import co.electriccoin.zcash.ui.common.provider.SynchronizerProvider
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVE_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SENDING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SEND_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SENT
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDING_FAILED
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
|
@ -38,22 +33,22 @@ import kotlinx.coroutines.flow.stateIn
|
|||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.Instant
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
interface TransactionRepository {
|
||||
val currentTransactions: Flow<List<TransactionData>?>
|
||||
val currentTransactions: Flow<List<Transaction>?>
|
||||
|
||||
suspend fun getMemos(transactionData: TransactionData): List<String>
|
||||
suspend fun getMemos(transaction: Transaction): List<String>
|
||||
|
||||
suspend fun getRecipients(transactionData: TransactionData): String?
|
||||
suspend fun getRecipients(transaction: Transaction): String?
|
||||
|
||||
fun observeTransaction(txId: String): Flow<TransactionData?>
|
||||
fun observeTransaction(txId: String): Flow<Transaction?>
|
||||
|
||||
fun observeTransactionsByMemo(memo: String): Flow<List<TransactionId>?>
|
||||
|
||||
suspend fun getTransactions(): List<TransactionData>
|
||||
suspend fun getTransactions(): List<Transaction>
|
||||
}
|
||||
|
||||
class TransactionRepositoryImpl(
|
||||
|
@ -63,7 +58,7 @@ class TransactionRepositoryImpl(
|
|||
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override val currentTransactions: Flow<List<TransactionData>?> =
|
||||
override val currentTransactions: Flow<List<Transaction>?> =
|
||||
combine(
|
||||
synchronizerProvider.synchronizer,
|
||||
accountDataSource.selectedAccount.map { it?.sdkAccount }
|
||||
|
@ -73,20 +68,141 @@ class TransactionRepositoryImpl(
|
|||
if (synchronizer == null || account == null) {
|
||||
flowOf(null)
|
||||
} else {
|
||||
channelFlow<List<TransactionData>?> {
|
||||
channelFlow<List<Transaction>?> {
|
||||
send(null)
|
||||
|
||||
launch {
|
||||
synchronizer.getTransactions(account.accountUuid)
|
||||
synchronizer
|
||||
.getTransactions(account.accountUuid)
|
||||
.mapLatest { transactions ->
|
||||
transactions.map { transaction ->
|
||||
TransactionData(
|
||||
overview = transaction,
|
||||
transactionOutputs = synchronizer.getTransactionOutputs(transaction),
|
||||
state = transaction.getExtendedState()
|
||||
)
|
||||
when (transaction.transactionState) {
|
||||
Expired ->
|
||||
when {
|
||||
transaction.isShielding ->
|
||||
ShieldTransaction.Failed(
|
||||
timestamp = createTimestamp(transaction) ?: Instant.now(),
|
||||
transactionOutputs =
|
||||
synchronizer.getTransactionOutputs
|
||||
(transaction),
|
||||
amount = transaction.totalSpent,
|
||||
id = transaction.txId,
|
||||
memoCount = transaction.memoCount,
|
||||
fee = transaction.netValue,
|
||||
overview = transaction
|
||||
)
|
||||
|
||||
transaction.isSentTransaction ->
|
||||
SendTransaction.Failed(
|
||||
timestamp = createTimestamp(transaction) ?: Instant.now(),
|
||||
transactionOutputs =
|
||||
synchronizer.getTransactionOutputs
|
||||
(transaction),
|
||||
amount = transaction.netValue,
|
||||
id = transaction.txId,
|
||||
memoCount = transaction.memoCount,
|
||||
fee = transaction.feePaid,
|
||||
overview = transaction
|
||||
)
|
||||
|
||||
else ->
|
||||
ReceiveTransaction.Failed(
|
||||
timestamp = createTimestamp(transaction) ?: Instant.now(),
|
||||
transactionOutputs =
|
||||
synchronizer.getTransactionOutputs(transaction),
|
||||
amount = transaction.netValue,
|
||||
id = transaction.txId,
|
||||
memoCount = transaction.memoCount,
|
||||
overview = transaction
|
||||
)
|
||||
}
|
||||
|
||||
Confirmed ->
|
||||
when {
|
||||
transaction.isShielding ->
|
||||
ShieldTransaction.Success(
|
||||
timestamp = createTimestamp(transaction) ?: Instant.now(),
|
||||
transactionOutputs =
|
||||
synchronizer.getTransactionOutputs
|
||||
(transaction),
|
||||
amount = transaction.totalSpent,
|
||||
id = transaction.txId,
|
||||
memoCount = transaction.memoCount,
|
||||
fee = transaction.netValue,
|
||||
overview = transaction
|
||||
)
|
||||
|
||||
transaction.isSentTransaction ->
|
||||
SendTransaction.Success(
|
||||
timestamp = createTimestamp(transaction) ?: Instant.now(),
|
||||
transactionOutputs =
|
||||
synchronizer.getTransactionOutputs
|
||||
(transaction),
|
||||
amount = transaction.netValue,
|
||||
id = transaction.txId,
|
||||
memoCount = transaction.memoCount,
|
||||
fee = transaction.feePaid,
|
||||
overview = transaction
|
||||
)
|
||||
|
||||
else ->
|
||||
ReceiveTransaction.Success(
|
||||
timestamp = createTimestamp(transaction) ?: Instant.now(),
|
||||
transactionOutputs =
|
||||
synchronizer.getTransactionOutputs
|
||||
(transaction),
|
||||
amount = transaction.netValue,
|
||||
id = transaction.txId,
|
||||
memoCount = transaction.memoCount,
|
||||
overview = transaction
|
||||
)
|
||||
}
|
||||
|
||||
Pending ->
|
||||
when {
|
||||
transaction.isShielding ->
|
||||
ShieldTransaction.Pending(
|
||||
timestamp = createTimestamp(transaction),
|
||||
transactionOutputs =
|
||||
synchronizer.getTransactionOutputs
|
||||
(transaction),
|
||||
amount = transaction.totalSpent,
|
||||
id = transaction.txId,
|
||||
memoCount = transaction.memoCount,
|
||||
fee = transaction.netValue,
|
||||
overview = transaction
|
||||
)
|
||||
|
||||
transaction.isSentTransaction ->
|
||||
SendTransaction.Pending(
|
||||
timestamp = createTimestamp(transaction),
|
||||
transactionOutputs =
|
||||
synchronizer.getTransactionOutputs
|
||||
(transaction),
|
||||
amount = transaction.netValue,
|
||||
id = transaction.txId,
|
||||
memoCount = transaction.memoCount,
|
||||
fee = transaction.feePaid,
|
||||
overview = transaction
|
||||
)
|
||||
|
||||
else ->
|
||||
ReceiveTransaction.Pending(
|
||||
timestamp = createTimestamp(transaction),
|
||||
transactionOutputs =
|
||||
synchronizer.getTransactionOutputs
|
||||
(transaction),
|
||||
amount = transaction.netValue,
|
||||
id = transaction.txId,
|
||||
memoCount = transaction.memoCount,
|
||||
overview = transaction
|
||||
)
|
||||
}
|
||||
|
||||
else -> error("Unexpected transaction stat")
|
||||
}
|
||||
}.sortedByDescending { transaction ->
|
||||
transaction.overview.blockTimeEpochSeconds ?: ZonedDateTime.now().toEpochSecond()
|
||||
transaction.timestamp ?: Instant.now()
|
||||
}
|
||||
}
|
||||
.collect {
|
||||
|
@ -105,19 +221,23 @@ class TransactionRepositoryImpl(
|
|||
initialValue = null
|
||||
)
|
||||
|
||||
override suspend fun getMemos(transactionData: TransactionData): List<String> =
|
||||
private fun createTimestamp(transaction: TransactionOverview): Instant? {
|
||||
return transaction.blockTimeEpochSeconds?.let { Instant.ofEpochSecond(it) }
|
||||
}
|
||||
|
||||
override suspend fun getMemos(transaction: Transaction): List<String> =
|
||||
withContext(Dispatchers.IO) {
|
||||
synchronizerProvider.getSynchronizer().getMemos(transactionData.overview)
|
||||
synchronizerProvider.getSynchronizer().getMemos(transaction.overview)
|
||||
.mapNotNull { memo -> memo.takeIf { it.isNotEmpty() } }
|
||||
.toList()
|
||||
}
|
||||
|
||||
override suspend fun getRecipients(transactionData: TransactionData): String? =
|
||||
override suspend fun getRecipients(transaction: Transaction): String? =
|
||||
withContext(Dispatchers.IO) {
|
||||
if (transactionData.overview.isSentTransaction) {
|
||||
if (transaction is SendTransaction) {
|
||||
synchronizerProvider
|
||||
.getSynchronizer()
|
||||
.getRecipients(transactionData.overview)
|
||||
.getRecipients(transaction.overview)
|
||||
.firstOrNull()
|
||||
?.addressValue
|
||||
} else {
|
||||
|
@ -125,10 +245,10 @@ class TransactionRepositoryImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override fun observeTransaction(txId: String): Flow<TransactionData?> =
|
||||
override fun observeTransaction(txId: String): Flow<Transaction?> =
|
||||
currentTransactions
|
||||
.map { transactions ->
|
||||
transactions?.find { it.overview.txId.txIdString() == txId }
|
||||
transactions?.find { it.id.txIdString() == txId }
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
@ -140,52 +260,111 @@ class TransactionRepositoryImpl(
|
|||
}
|
||||
.distinctUntilChanged()
|
||||
|
||||
override suspend fun getTransactions(): List<TransactionData> {
|
||||
return currentTransactions.filterNotNull().first()
|
||||
}
|
||||
override suspend fun getTransactions(): List<Transaction> = currentTransactions.filterNotNull().first()
|
||||
}
|
||||
|
||||
data class TransactionData(
|
||||
val overview: TransactionOverview,
|
||||
val transactionOutputs: List<TransactionOutput>,
|
||||
val state: TransactionExtendedState,
|
||||
)
|
||||
|
||||
enum class TransactionExtendedState {
|
||||
SENT,
|
||||
SENDING,
|
||||
SEND_FAILED,
|
||||
RECEIVED,
|
||||
RECEIVING,
|
||||
RECEIVE_FAILED,
|
||||
SHIELDED,
|
||||
SHIELDING,
|
||||
SHIELDING_FAILED
|
||||
sealed interface Transaction {
|
||||
val id: TransactionId
|
||||
val amount: Zatoshi
|
||||
val memoCount: Int
|
||||
val timestamp: Instant?
|
||||
val transactionOutputs: List<TransactionOutput>
|
||||
val overview: TransactionOverview
|
||||
val fee: Zatoshi?
|
||||
}
|
||||
|
||||
private fun TransactionOverview.getExtendedState(): TransactionExtendedState {
|
||||
return when (transactionState) {
|
||||
cash.z.ecc.android.sdk.model.TransactionState.Expired ->
|
||||
when {
|
||||
isShielding -> SHIELDING_FAILED
|
||||
isSentTransaction -> SEND_FAILED
|
||||
else -> RECEIVE_FAILED
|
||||
}
|
||||
sealed interface SendTransaction : Transaction {
|
||||
data class Success(
|
||||
override val id: TransactionId,
|
||||
override val amount: Zatoshi,
|
||||
override val timestamp: Instant,
|
||||
override val memoCount: Int,
|
||||
override val fee: Zatoshi?,
|
||||
override val transactionOutputs: List<TransactionOutput>,
|
||||
override val overview: TransactionOverview,
|
||||
) : SendTransaction
|
||||
|
||||
cash.z.ecc.android.sdk.model.TransactionState.Confirmed ->
|
||||
when {
|
||||
isShielding -> SHIELDED
|
||||
isSentTransaction -> SENT
|
||||
else -> RECEIVED
|
||||
}
|
||||
data class Pending(
|
||||
override val id: TransactionId,
|
||||
override val amount: Zatoshi,
|
||||
override val timestamp: Instant?,
|
||||
override val memoCount: Int,
|
||||
override val fee: Zatoshi?,
|
||||
override val transactionOutputs: List<TransactionOutput>,
|
||||
override val overview: TransactionOverview,
|
||||
) : SendTransaction
|
||||
|
||||
cash.z.ecc.android.sdk.model.TransactionState.Pending ->
|
||||
when {
|
||||
isShielding -> SHIELDING
|
||||
isSentTransaction -> SENDING
|
||||
else -> RECEIVING
|
||||
}
|
||||
|
||||
else -> error("Unexpected transaction state found while calculating its extended state.")
|
||||
}
|
||||
data class Failed(
|
||||
override val id: TransactionId,
|
||||
override val amount: Zatoshi,
|
||||
override val timestamp: Instant,
|
||||
override val memoCount: Int,
|
||||
override val fee: Zatoshi?,
|
||||
override val transactionOutputs: List<TransactionOutput>,
|
||||
override val overview: TransactionOverview,
|
||||
) : SendTransaction
|
||||
}
|
||||
|
||||
sealed interface ReceiveTransaction : Transaction {
|
||||
override val fee: Zatoshi?
|
||||
get() = null
|
||||
|
||||
data class Success(
|
||||
override val id: TransactionId,
|
||||
override val amount: Zatoshi,
|
||||
override val timestamp: Instant,
|
||||
override val memoCount: Int,
|
||||
override val transactionOutputs: List<TransactionOutput>,
|
||||
override val overview: TransactionOverview,
|
||||
) : ReceiveTransaction
|
||||
|
||||
data class Pending(
|
||||
override val id: TransactionId,
|
||||
override val amount: Zatoshi,
|
||||
override val timestamp: Instant?,
|
||||
override val memoCount: Int,
|
||||
override val transactionOutputs: List<TransactionOutput>,
|
||||
override val overview: TransactionOverview,
|
||||
) : ReceiveTransaction
|
||||
|
||||
data class Failed(
|
||||
override val id: TransactionId,
|
||||
override val amount: Zatoshi,
|
||||
override val timestamp: Instant,
|
||||
override val memoCount: Int,
|
||||
override val transactionOutputs: List<TransactionOutput>,
|
||||
override val overview: TransactionOverview,
|
||||
) : ReceiveTransaction
|
||||
}
|
||||
|
||||
sealed interface ShieldTransaction : Transaction {
|
||||
data class Success(
|
||||
override val id: TransactionId,
|
||||
override val amount: Zatoshi,
|
||||
override val timestamp: Instant,
|
||||
override val memoCount: Int,
|
||||
override val fee: Zatoshi?,
|
||||
override val transactionOutputs: List<TransactionOutput>,
|
||||
override val overview: TransactionOverview,
|
||||
) : ShieldTransaction
|
||||
|
||||
data class Pending(
|
||||
override val id: TransactionId,
|
||||
override val amount: Zatoshi,
|
||||
override val timestamp: Instant?,
|
||||
override val memoCount: Int,
|
||||
override val fee: Zatoshi?,
|
||||
override val transactionOutputs: List<TransactionOutput>,
|
||||
override val overview: TransactionOverview,
|
||||
) : ShieldTransaction
|
||||
|
||||
data class Failed(
|
||||
override val id: TransactionId,
|
||||
override val amount: Zatoshi,
|
||||
override val memoCount: Int,
|
||||
override val timestamp: Instant,
|
||||
override val transactionOutputs: List<TransactionOutput>,
|
||||
override val fee: Zatoshi?,
|
||||
override val overview: TransactionOverview,
|
||||
) : ShieldTransaction
|
||||
}
|
||||
|
|
|
@ -8,15 +8,9 @@ import co.electriccoin.zcash.ui.common.datasource.AccountDataSource
|
|||
import co.electriccoin.zcash.ui.common.model.KeystoneAccount
|
||||
import co.electriccoin.zcash.ui.common.model.ZashiAccount
|
||||
import co.electriccoin.zcash.ui.common.provider.GetVersionInfoProvider
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVE_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SENDING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SEND_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SENT
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDING_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.ReceiveTransaction
|
||||
import co.electriccoin.zcash.ui.common.repository.SendTransaction
|
||||
import co.electriccoin.zcash.ui.common.repository.ShieldTransaction
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionRepository
|
||||
import co.electriccoin.zcash.ui.design.util.getString
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
|
@ -25,7 +19,6 @@ import co.electriccoin.zcash.ui.util.FileShareUtil.ZASHI_INTERNAL_DATA_MIME_TYPE
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.time.Instant
|
||||
import java.time.Year
|
||||
import java.time.ZoneId
|
||||
import java.time.ZoneOffset
|
||||
|
@ -122,12 +115,7 @@ class ExportTaxUseCase(
|
|||
.mapNotNull { transaction ->
|
||||
val previousYear = Year.now().minusYears(1)
|
||||
|
||||
val date =
|
||||
transaction.overview.blockTimeEpochSeconds
|
||||
?.let {
|
||||
Instant.ofEpochSecond(it).atZone(ZoneId.of("UTC"))
|
||||
} ?: return@mapNotNull null
|
||||
|
||||
val date = transaction.timestamp?.atZone(ZoneId.of("UTC")) ?: return@mapNotNull null
|
||||
if (date.year != previousYear.value) return@mapNotNull null
|
||||
|
||||
val dateString =
|
||||
|
@ -139,16 +127,16 @@ class ExportTaxUseCase(
|
|||
formatter.format(date)
|
||||
} ?: return@mapNotNull null
|
||||
|
||||
when (transaction.state) {
|
||||
SENT,
|
||||
SENDING -> {
|
||||
val fee = transaction.overview.feePaid
|
||||
when (transaction) {
|
||||
is SendTransaction.Success,
|
||||
is SendTransaction.Pending -> {
|
||||
val fee = transaction.fee
|
||||
|
||||
val sentQuantity =
|
||||
if (fee != null) {
|
||||
stringRes(transaction.overview.netValue - fee)
|
||||
stringRes(transaction.amount - fee)
|
||||
} else {
|
||||
stringRes(transaction.overview.netValue)
|
||||
stringRes(transaction.amount)
|
||||
}
|
||||
|
||||
CsvEntry(
|
||||
|
@ -163,12 +151,12 @@ class ExportTaxUseCase(
|
|||
)
|
||||
}
|
||||
|
||||
SEND_FAILED -> null
|
||||
RECEIVED,
|
||||
RECEIVING -> {
|
||||
is SendTransaction.Failed -> null
|
||||
is ReceiveTransaction.Success,
|
||||
is ReceiveTransaction.Pending -> {
|
||||
CsvEntry(
|
||||
date = dateString,
|
||||
receivedQuantity = stringRes(transaction.overview.netValue).getString(context),
|
||||
receivedQuantity = stringRes(transaction.amount).getString(context),
|
||||
receivedCurrency = ZEC_SYMBOL,
|
||||
sentQuantity = "",
|
||||
sentCurrency = "",
|
||||
|
@ -178,10 +166,10 @@ class ExportTaxUseCase(
|
|||
)
|
||||
}
|
||||
|
||||
RECEIVE_FAILED -> null
|
||||
SHIELDED,
|
||||
SHIELDING,
|
||||
SHIELDING_FAILED -> null
|
||||
is ReceiveTransaction.Failed -> null
|
||||
is ShieldTransaction.Success,
|
||||
is ShieldTransaction.Pending,
|
||||
is ShieldTransaction.Failed -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@ import co.electriccoin.zcash.ui.common.datasource.RestoreTimestampDataSource
|
|||
import co.electriccoin.zcash.ui.common.model.AddressBookContact
|
||||
import co.electriccoin.zcash.ui.common.repository.AddressBookRepository
|
||||
import co.electriccoin.zcash.ui.common.repository.MetadataRepository
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionData
|
||||
import co.electriccoin.zcash.ui.common.repository.SendTransaction
|
||||
import co.electriccoin.zcash.ui.common.repository.ShieldTransaction
|
||||
import co.electriccoin.zcash.ui.common.repository.Transaction
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionFilter
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionFilterRepository
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionMetadata
|
||||
|
@ -57,7 +59,7 @@ class GetCurrentFilteredTransactionsUseCase(
|
|||
|
||||
if (recipient == null) {
|
||||
metadataRepository.observeTransactionMetadataByTxId(
|
||||
transaction.overview.txId.txIdString()
|
||||
transaction.id.txIdString()
|
||||
).map {
|
||||
FilterTransactionData(
|
||||
transaction = transaction,
|
||||
|
@ -70,7 +72,7 @@ class GetCurrentFilteredTransactionsUseCase(
|
|||
combine(
|
||||
addressBookRepository.observeContactByAddress(recipient),
|
||||
metadataRepository.observeTransactionMetadataByTxId(
|
||||
txId = transaction.overview.txId.txIdString(),
|
||||
txId = transaction.id.txIdString(),
|
||||
)
|
||||
) { contact, transactionMetadata ->
|
||||
FilterTransactionData(
|
||||
|
@ -148,7 +150,7 @@ class GetCurrentFilteredTransactionsUseCase(
|
|||
}
|
||||
?.map { transaction ->
|
||||
ListTransactionData(
|
||||
data = transaction.transaction,
|
||||
transaction = transaction.transaction,
|
||||
metadata = transaction.transactionMetadata
|
||||
)
|
||||
}
|
||||
|
@ -167,7 +169,7 @@ class GetCurrentFilteredTransactionsUseCase(
|
|||
): Boolean {
|
||||
val memoPass =
|
||||
if (filters.contains(TransactionFilter.MEMOS)) {
|
||||
transaction.transaction.overview.memoCount > 0
|
||||
transaction.transaction.memoCount > 0
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
@ -201,12 +203,11 @@ class GetCurrentFilteredTransactionsUseCase(
|
|||
return if (filters.contains(TransactionFilter.SENT) || filters.contains(TransactionFilter.RECEIVED)) {
|
||||
when {
|
||||
filters.contains(TransactionFilter.SENT) &&
|
||||
transaction.transaction.overview.isSentTransaction &&
|
||||
!transaction.transaction.overview.isShielding -> true
|
||||
transaction.transaction is SendTransaction -> true
|
||||
|
||||
filters.contains(TransactionFilter.RECEIVED) &&
|
||||
!transaction.transaction.overview.isSentTransaction &&
|
||||
!transaction.transaction.overview.isShielding -> true
|
||||
transaction.transaction !is SendTransaction &&
|
||||
transaction.transaction !is ShieldTransaction -> true
|
||||
|
||||
else -> false
|
||||
}
|
||||
|
@ -220,12 +221,10 @@ class GetCurrentFilteredTransactionsUseCase(
|
|||
restoreTimestamp: Instant,
|
||||
): Boolean {
|
||||
val transactionDate =
|
||||
transaction.transaction.overview.blockTimeEpochSeconds
|
||||
?.let { blockTimeEpochSeconds ->
|
||||
Instant.ofEpochSecond(blockTimeEpochSeconds).atZone(ZoneId.systemDefault()).toLocalDate()
|
||||
} ?: LocalDate.now()
|
||||
transaction.transaction.timestamp?.atZone(ZoneId.systemDefault())?.toLocalDate()
|
||||
?: LocalDate.now()
|
||||
|
||||
val hasMemo = transaction.transaction.overview.memoCount > 0
|
||||
val hasMemo = transaction.transaction.memoCount > 0
|
||||
val restoreDate = restoreTimestamp.atZone(ZoneId.systemDefault()).toLocalDate()
|
||||
|
||||
return if (hasMemo && transactionDate < restoreDate) {
|
||||
|
@ -261,7 +260,7 @@ class GetCurrentFilteredTransactionsUseCase(
|
|||
transaction: FilterTransactionData,
|
||||
fulltextFilter: String
|
||||
): Boolean {
|
||||
val text = stringRes(transaction.transaction.overview.netValue).getString(context)
|
||||
val text = stringRes(transaction.transaction.amount).getString(context)
|
||||
return text.contains(fulltextFilter, ignoreCase = true)
|
||||
}
|
||||
|
||||
|
@ -282,11 +281,11 @@ class GetCurrentFilteredTransactionsUseCase(
|
|||
private fun hasMemoInFilteredIds(
|
||||
memoTxIds: List<TransactionId>?,
|
||||
transaction: FilterTransactionData
|
||||
) = memoTxIds?.contains(transaction.transaction.overview.txId) ?: false
|
||||
) = memoTxIds?.contains(transaction.transaction.id) ?: false
|
||||
}
|
||||
|
||||
private data class FilterTransactionData(
|
||||
val transaction: TransactionData,
|
||||
val transaction: Transaction,
|
||||
val contact: AddressBookContact?,
|
||||
val recipientAddress: String?,
|
||||
val transactionMetadata: TransactionMetadata?
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package co.electriccoin.zcash.ui.common.usecase
|
||||
|
||||
import co.electriccoin.zcash.ui.common.repository.MetadataRepository
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionData
|
||||
import co.electriccoin.zcash.ui.common.repository.Transaction
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionMetadata
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionRepository
|
||||
import co.electriccoin.zcash.ui.util.combineToFlow
|
||||
|
@ -25,10 +25,10 @@ class GetCurrentTransactionsUseCase(
|
|||
} else {
|
||||
transactions
|
||||
.map {
|
||||
metadataRepository.observeTransactionMetadataByTxId(it.overview.txId.txIdString())
|
||||
metadataRepository.observeTransactionMetadataByTxId(it.id.txIdString())
|
||||
.mapLatest { metadata ->
|
||||
ListTransactionData(
|
||||
data = it,
|
||||
transaction = it,
|
||||
metadata = metadata
|
||||
)
|
||||
}
|
||||
|
@ -39,6 +39,6 @@ class GetCurrentTransactionsUseCase(
|
|||
}
|
||||
|
||||
data class ListTransactionData(
|
||||
val data: TransactionData,
|
||||
val transaction: Transaction,
|
||||
val metadata: TransactionMetadata?
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ import co.electriccoin.zcash.ui.common.model.AddressBookContact
|
|||
import co.electriccoin.zcash.ui.common.provider.SynchronizerProvider
|
||||
import co.electriccoin.zcash.ui.common.repository.AddressBookRepository
|
||||
import co.electriccoin.zcash.ui.common.repository.MetadataRepository
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionData
|
||||
import co.electriccoin.zcash.ui.common.repository.Transaction
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionMetadata
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -82,7 +82,7 @@ class GetTransactionDetailByIdUseCase(
|
|||
}
|
||||
|
||||
data class DetailedTransactionData(
|
||||
val transaction: TransactionData,
|
||||
val transaction: Transaction,
|
||||
val memos: List<String>?,
|
||||
val contact: AddressBookContact?,
|
||||
val recipientAddress: WalletAddress?,
|
||||
|
|
|
@ -236,13 +236,8 @@ internal fun WrapSend(
|
|||
)
|
||||
)
|
||||
|
||||
val fee = it.transaction.overview.feePaid
|
||||
val value =
|
||||
if (fee == null) {
|
||||
it.transaction.overview.netValue
|
||||
} else {
|
||||
it.transaction.overview.netValue - fee
|
||||
}
|
||||
val fee = it.transaction.fee
|
||||
val value = if (fee == null) it.transaction.amount else it.transaction.amount - fee
|
||||
|
||||
setAmountState(
|
||||
AmountState.newFromZec(
|
||||
|
|
|
@ -7,15 +7,9 @@ import cash.z.ecc.android.sdk.model.WalletAddress
|
|||
import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVE_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.RECEIVING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SENDING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SEND_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SENT
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDED
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDING
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionExtendedState.SHIELDING_FAILED
|
||||
import co.electriccoin.zcash.ui.common.repository.ReceiveTransaction
|
||||
import co.electriccoin.zcash.ui.common.repository.SendTransaction
|
||||
import co.electriccoin.zcash.ui.common.repository.ShieldTransaction
|
||||
import co.electriccoin.zcash.ui.common.usecase.CopyToClipboardUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.DetailedTransactionData
|
||||
import co.electriccoin.zcash.ui.common.usecase.FlipTransactionBookmarkUseCase
|
||||
|
@ -49,7 +43,6 @@ import kotlinx.coroutines.flow.mapLatest
|
|||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
|
@ -110,7 +103,7 @@ class TransactionDetailViewModel(
|
|||
viewModelScope.launch {
|
||||
withContext(Dispatchers.Default) {
|
||||
val transaction = transaction.filterNotNull().first()
|
||||
if (transaction.transaction.overview.memoCount > 0) {
|
||||
if (transaction.transaction.memoCount > 0) {
|
||||
markTxMemoAsRead(transactionDetail.transactionId)
|
||||
}
|
||||
}
|
||||
|
@ -122,10 +115,10 @@ class TransactionDetailViewModel(
|
|||
}
|
||||
|
||||
private fun createTransactionInfoState(transaction: DetailedTransactionData): TransactionDetailInfoState {
|
||||
return when (transaction.transaction.state) {
|
||||
SENT,
|
||||
SENDING,
|
||||
SEND_FAILED -> {
|
||||
return when (transaction.transaction) {
|
||||
is SendTransaction.Success,
|
||||
is SendTransaction.Pending,
|
||||
is SendTransaction.Failed -> {
|
||||
if (transaction.recipientAddress is WalletAddress.Transparent) {
|
||||
SendTransparentState(
|
||||
contact = transaction.contact?.let { stringRes(it.name) },
|
||||
|
@ -133,11 +126,11 @@ class TransactionDetailViewModel(
|
|||
addressAbbreviated = createAbbreviatedAddressStringRes(transaction),
|
||||
transactionId =
|
||||
stringResByTransactionId(
|
||||
value = transaction.transaction.overview.txId.txIdString(),
|
||||
value = transaction.transaction.id.txIdString(),
|
||||
abbreviated = true
|
||||
),
|
||||
onTransactionIdClick = {
|
||||
onCopyToClipboard(transaction.transaction.overview.txId.txIdString())
|
||||
onCopyToClipboard(transaction.transaction.id.txIdString())
|
||||
},
|
||||
onTransactionAddressClick = { onCopyToClipboard(transaction.recipientAddress.address) },
|
||||
fee = createFeeStringRes(transaction),
|
||||
|
@ -151,11 +144,11 @@ class TransactionDetailViewModel(
|
|||
addressAbbreviated = createAbbreviatedAddressStringRes(transaction),
|
||||
transactionId =
|
||||
stringResByTransactionId(
|
||||
value = transaction.transaction.overview.txId.txIdString(),
|
||||
value = transaction.transaction.id.txIdString(),
|
||||
abbreviated = true
|
||||
),
|
||||
onTransactionIdClick = {
|
||||
onCopyToClipboard(transaction.transaction.overview.txId.txIdString())
|
||||
onCopyToClipboard(transaction.transaction.id.txIdString())
|
||||
},
|
||||
onTransactionAddressClick = {
|
||||
onCopyToClipboard(transaction.recipientAddress?.address.orEmpty())
|
||||
|
@ -177,18 +170,18 @@ class TransactionDetailViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
RECEIVED,
|
||||
RECEIVING,
|
||||
RECEIVE_FAILED -> {
|
||||
is ReceiveTransaction.Success,
|
||||
is ReceiveTransaction.Pending,
|
||||
is ReceiveTransaction.Failed -> {
|
||||
if (transaction.transaction.transactionOutputs.all { it.pool == TransactionPool.TRANSPARENT }) {
|
||||
ReceiveTransparentState(
|
||||
transactionId =
|
||||
stringResByTransactionId(
|
||||
value = transaction.transaction.overview.txId.txIdString(),
|
||||
value = transaction.transaction.id.txIdString(),
|
||||
abbreviated = true
|
||||
),
|
||||
onTransactionIdClick = {
|
||||
onCopyToClipboard(transaction.transaction.overview.txId.txIdString())
|
||||
onCopyToClipboard(transaction.transaction.id.txIdString())
|
||||
},
|
||||
completedTimestamp = createTimestampStringRes(transaction),
|
||||
note = transaction.metadata?.note?.let { stringRes(it) }
|
||||
|
@ -197,11 +190,11 @@ class TransactionDetailViewModel(
|
|||
ReceiveShieldedState(
|
||||
transactionId =
|
||||
stringResByTransactionId(
|
||||
value = transaction.transaction.overview.txId.txIdString(),
|
||||
value = transaction.transaction.id.txIdString(),
|
||||
abbreviated = true
|
||||
),
|
||||
onTransactionIdClick = {
|
||||
onCopyToClipboard(transaction.transaction.overview.txId.txIdString())
|
||||
onCopyToClipboard(transaction.transaction.id.txIdString())
|
||||
},
|
||||
completedTimestamp = createTimestampStringRes(transaction),
|
||||
memo =
|
||||
|
@ -219,17 +212,17 @@ class TransactionDetailViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
SHIELDED,
|
||||
SHIELDING,
|
||||
SHIELDING_FAILED -> {
|
||||
is ShieldTransaction.Success,
|
||||
is ShieldTransaction.Pending,
|
||||
is ShieldTransaction.Failed -> {
|
||||
ShieldingState(
|
||||
transactionId =
|
||||
stringResByTransactionId(
|
||||
value = transaction.transaction.overview.txId.txIdString(),
|
||||
value = transaction.transaction.id.txIdString(),
|
||||
abbreviated = true
|
||||
),
|
||||
onTransactionIdClick = {
|
||||
onCopyToClipboard(transaction.transaction.overview.txId.txIdString())
|
||||
onCopyToClipboard(transaction.transaction.id.txIdString())
|
||||
},
|
||||
completedTimestamp = createTimestampStringRes(transaction),
|
||||
fee = createFeeStringRes(transaction),
|
||||
|
@ -239,19 +232,10 @@ class TransactionDetailViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun createFeeStringRes(transaction: DetailedTransactionData): StringResource {
|
||||
private fun createFeeStringRes(data: DetailedTransactionData): StringResource {
|
||||
val feePaid =
|
||||
when (transaction.transaction.state) {
|
||||
SENT,
|
||||
SENDING,
|
||||
SEND_FAILED,
|
||||
RECEIVED,
|
||||
RECEIVING,
|
||||
RECEIVE_FAILED -> transaction.transaction.overview.feePaid
|
||||
SHIELDED,
|
||||
SHIELDING,
|
||||
SHIELDING_FAILED -> transaction.transaction.overview.netValue
|
||||
} ?: return stringRes(R.string.transaction_detail_fee_minimal)
|
||||
data.transaction.fee.takeIf { data.transaction !is ReceiveTransaction }
|
||||
?: return stringRes(R.string.transaction_detail_fee_minimal)
|
||||
|
||||
return if (feePaid.value < MIN_FEE_THRESHOLD) {
|
||||
stringRes(R.string.transaction_detail_fee_minimal)
|
||||
|
@ -272,11 +256,8 @@ class TransactionDetailViewModel(
|
|||
abbreviated = true
|
||||
)
|
||||
|
||||
private fun createTimestampStringRes(transaction: DetailedTransactionData) =
|
||||
transaction.transaction.overview.blockTimeEpochSeconds
|
||||
?.let { blockTimeEpochSeconds ->
|
||||
Instant.ofEpochSecond(blockTimeEpochSeconds)
|
||||
}
|
||||
private fun createTimestampStringRes(data: DetailedTransactionData) =
|
||||
data.transaction.timestamp
|
||||
?.atZone(ZoneId.systemDefault())
|
||||
?.let {
|
||||
stringResByDateTime(
|
||||
|
@ -292,27 +273,27 @@ class TransactionDetailViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
private fun createPrimaryButtonState(transaction: DetailedTransactionData) =
|
||||
if (transaction.contact == null) {
|
||||
when (transaction.transaction.state) {
|
||||
SENT,
|
||||
SENDING,
|
||||
SEND_FAILED ->
|
||||
private fun createPrimaryButtonState(data: DetailedTransactionData) =
|
||||
if (data.contact == null) {
|
||||
when (data.transaction) {
|
||||
is SendTransaction.Success,
|
||||
is SendTransaction.Pending,
|
||||
is SendTransaction.Failed ->
|
||||
ButtonState(
|
||||
text = stringRes(R.string.transaction_detail_save_address),
|
||||
onClick = { onSaveAddressClick(transaction) }
|
||||
onClick = { onSaveAddressClick(data) }
|
||||
)
|
||||
|
||||
else -> null
|
||||
}
|
||||
} else {
|
||||
when (transaction.transaction.state) {
|
||||
SENT,
|
||||
SENDING,
|
||||
SEND_FAILED ->
|
||||
when (data.transaction) {
|
||||
is ReceiveTransaction.Success,
|
||||
is ReceiveTransaction.Pending,
|
||||
is ReceiveTransaction.Failed ->
|
||||
ButtonState(
|
||||
text = stringRes(R.string.transaction_detail_send_again),
|
||||
onClick = { onSendAgainClick(transaction) }
|
||||
onClick = { onSendAgainClick(data) }
|
||||
)
|
||||
|
||||
else -> null
|
||||
|
@ -329,32 +310,22 @@ class TransactionDetailViewModel(
|
|||
sendTransactionAgain(transaction)
|
||||
}
|
||||
|
||||
private fun createTransactionHeaderState(transaction: DetailedTransactionData) =
|
||||
private fun createTransactionHeaderState(data: DetailedTransactionData) =
|
||||
TransactionDetailHeaderState(
|
||||
title =
|
||||
when (transaction.transaction.state) {
|
||||
SENT -> stringRes(R.string.transaction_detail_sent)
|
||||
SENDING -> stringRes(R.string.transaction_detail_sending)
|
||||
SEND_FAILED -> stringRes(R.string.transaction_detail_send_failed)
|
||||
RECEIVED -> stringRes(R.string.transaction_detail_received)
|
||||
RECEIVING -> stringRes(R.string.transaction_detail_receiving)
|
||||
RECEIVE_FAILED -> stringRes(R.string.transaction_detail_receive_failed)
|
||||
SHIELDED -> stringRes(R.string.transaction_detail_shielded)
|
||||
SHIELDING -> stringRes(R.string.transaction_detail_shielding)
|
||||
SHIELDING_FAILED -> stringRes(R.string.transaction_detail_shielding_failed)
|
||||
when (data.transaction) {
|
||||
is SendTransaction.Success -> stringRes(R.string.transaction_detail_sent)
|
||||
is SendTransaction.Pending -> stringRes(R.string.transaction_detail_sending)
|
||||
is SendTransaction.Failed -> stringRes(R.string.transaction_detail_send_failed)
|
||||
is ReceiveTransaction.Success -> stringRes(R.string.transaction_detail_received)
|
||||
is ReceiveTransaction.Pending -> stringRes(R.string.transaction_detail_receiving)
|
||||
is ReceiveTransaction.Failed -> stringRes(R.string.transaction_detail_receive_failed)
|
||||
is ShieldTransaction.Success -> stringRes(R.string.transaction_detail_shielded)
|
||||
is ShieldTransaction.Pending -> stringRes(R.string.transaction_detail_shielding)
|
||||
is ShieldTransaction.Failed -> stringRes(R.string.transaction_detail_shielding_failed)
|
||||
},
|
||||
amount =
|
||||
when (transaction.transaction.state) {
|
||||
SENT,
|
||||
SENDING,
|
||||
SEND_FAILED,
|
||||
RECEIVED,
|
||||
RECEIVING,
|
||||
RECEIVE_FAILED -> stringRes(transaction.transaction.overview.netValue)
|
||||
SHIELDED,
|
||||
SHIELDING,
|
||||
SHIELDING_FAILED -> stringRes(transaction.transaction.overview.totalSpent)
|
||||
}
|
||||
stringRes(data.transaction.amount)
|
||||
)
|
||||
|
||||
private fun onBack() {
|
||||
|
|
|
@ -7,7 +7,7 @@ import co.electriccoin.zcash.ui.NavigationRouter
|
|||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.datasource.RestoreTimestampDataSource
|
||||
import co.electriccoin.zcash.ui.common.mapper.TransactionHistoryMapper
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionData
|
||||
import co.electriccoin.zcash.ui.common.repository.Transaction
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionFilterRepository
|
||||
import co.electriccoin.zcash.ui.common.usecase.ApplyTransactionFulltextFiltersUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetCurrentFilteredTransactionsUseCase
|
||||
|
@ -109,12 +109,7 @@ class TransactionHistoryViewModel(
|
|||
transactions
|
||||
.groupBy {
|
||||
val other =
|
||||
it.data.overview.blockTimeEpochSeconds?.let { sec ->
|
||||
Instant
|
||||
.ofEpochSecond(sec)
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDate()
|
||||
} ?: now
|
||||
it.transaction.timestamp?.atZone(ZoneId.systemDefault())?.toLocalDate() ?: now
|
||||
when {
|
||||
now == other ->
|
||||
stringRes(R.string.transaction_history_today) to "today"
|
||||
|
@ -146,7 +141,7 @@ class TransactionHistoryViewModel(
|
|||
TransactionHistoryItem.Transaction(
|
||||
state =
|
||||
transactionHistoryMapper.createTransactionState(
|
||||
transaction = transaction,
|
||||
data = transaction,
|
||||
onTransactionClick = ::onTransactionClick,
|
||||
restoreTimestamp = restoreTimestamp
|
||||
)
|
||||
|
@ -215,8 +210,8 @@ class TransactionHistoryViewModel(
|
|||
navigationRouter.back()
|
||||
}
|
||||
|
||||
private fun onTransactionClick(transactionData: TransactionData) {
|
||||
navigationRouter.forward(TransactionDetail(transactionData.overview.txId.txIdString()))
|
||||
private fun onTransactionClick(transaction: Transaction) {
|
||||
navigationRouter.forward(TransactionDetail(transaction.id.txIdString()))
|
||||
}
|
||||
|
||||
private fun onTransactionFiltersClicked() = navigationRouter.forward(TransactionFilters)
|
||||
|
|
|
@ -9,7 +9,7 @@ import co.electriccoin.zcash.ui.R
|
|||
import co.electriccoin.zcash.ui.common.datasource.RestoreTimestampDataSource
|
||||
import co.electriccoin.zcash.ui.common.mapper.TransactionHistoryMapper
|
||||
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||
import co.electriccoin.zcash.ui.common.repository.TransactionData
|
||||
import co.electriccoin.zcash.ui.common.repository.Transaction
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetCurrentTransactionsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletRestoringStateUseCase
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
|
@ -67,7 +67,7 @@ class TransactionHistoryWidgetViewModel(
|
|||
.take(MAX_TRANSACTION_COUNT)
|
||||
.map { transaction ->
|
||||
transactionHistoryMapper.createTransactionState(
|
||||
transaction = transaction,
|
||||
data = transaction,
|
||||
restoreTimestamp = restoreTimestampDataSource.getOrCreate(),
|
||||
onTransactionClick = ::onTransactionClick,
|
||||
)
|
||||
|
@ -81,8 +81,8 @@ class TransactionHistoryWidgetViewModel(
|
|||
TransactionHistoryWidgetState.Loading
|
||||
)
|
||||
|
||||
private fun onTransactionClick(transactionData: TransactionData) {
|
||||
navigationRouter.forward(TransactionDetail(transactionData.overview.txId.txIdString()))
|
||||
private fun onTransactionClick(transaction: Transaction) {
|
||||
navigationRouter.forward(TransactionDetail(transaction.id.txIdString()))
|
||||
}
|
||||
|
||||
private fun onSeeAllTransactionsClick() {
|
||||
|
|
Loading…
Reference in New Issue