Updated on 2026-08-14

This commit is contained in:
Tangem 2024-09-30 22:59:14 +03:00
parent f004aaf1f3
commit b051579757
10 changed files with 41 additions and 24 deletions

View file

@ -3,25 +3,30 @@ package com.tangem.data.staking
import com.tangem.domain.staking.model.PendingTransaction
import com.tangem.domain.staking.model.stakekit.BalanceItem
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
import com.tangem.domain.wallets.models.UserWalletId
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArrayList
internal class DefaultStakingPendingTransactionRepository : StakingPendingTransactionRepository {
private val pendingTransactions = CopyOnWriteArrayList<PendingTransaction>()
private val pendingTransactionsMap = ConcurrentHashMap<UserWalletId, CopyOnWriteArrayList<PendingTransaction>>()
override fun saveTransaction(transaction: PendingTransaction) {
pendingTransactions.add(transaction)
override fun saveTransaction(userWalletId: UserWalletId, transaction: PendingTransaction) {
val transactions = pendingTransactionsMap.computeIfAbsent(userWalletId) { CopyOnWriteArrayList() }
transactions.add(transaction)
}
override fun removeTransactions(transactions: Set<PendingTransaction>) {
pendingTransactions.removeAll(transactions)
override fun removeTransactions(userWalletId: UserWalletId, transactions: Set<PendingTransaction>) {
pendingTransactionsMap[userWalletId]?.removeAll(transactions)
}
override fun getTransactionsWithBalanceItems(): List<Pair<PendingTransaction, BalanceItem>> {
return pendingTransactions.mapNotNull { pendingTransaction ->
override fun getTransactionsWithBalanceItems(
userWalletId: UserWalletId,
): List<Pair<PendingTransaction, BalanceItem>> {
return pendingTransactionsMap[userWalletId]?.mapNotNull { pendingTransaction: PendingTransaction ->
PendingTransactionItemConverter.convert(pendingTransaction)?.let { balanceItem ->
pendingTransaction to balanceItem
}
}
} ?: emptyList()
}
}

View file

@ -37,7 +37,7 @@ sealed class YieldBalance {
// need to exclude rewards because their amount may change frequently
return balance.items
.filter { it.type != BalanceType.REWARDS }
.map { it.amount.toString() + it.type.toString() + it.groupId + it.validatorAddress }
.map { it.amount.toString() + it.type.toString() + it.groupId }
.hashCode()
}
}

View file

@ -5,6 +5,7 @@ import com.tangem.domain.staking.model.stakekit.BalanceItem
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
import com.tangem.domain.wallets.models.UserWalletId
/**
* Use case for getting saved staking pending transactions.
@ -14,9 +15,9 @@ class GetStakingPendingTransactionsUseCase(
private val stakingErrorResolver: StakingErrorResolver,
) {
operator fun invoke(): Either<StakingError, List<BalanceItem>> {
operator fun invoke(userWalletId: UserWalletId): Either<StakingError, List<BalanceItem>> {
return Either.catch {
stakingPendingTransactionRepository.getTransactionsWithBalanceItems().map { it.second }
stakingPendingTransactionRepository.getTransactionsWithBalanceItems(userWalletId).map { it.second }
}.mapLeft {
stakingErrorResolver.resolve(it)
}

View file

@ -8,6 +8,7 @@ import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.model.stakekit.YieldBalance
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
import com.tangem.domain.wallets.models.UserWalletId
import java.util.UUID
class InvalidatePendingTransactionsUseCase(
@ -15,15 +16,18 @@ class InvalidatePendingTransactionsUseCase(
private val stakingErrorResolver: StakingErrorResolver,
) {
operator fun invoke(yieldBalance: YieldBalance): Either<StakingError, List<BalanceItem>> {
operator fun invoke(
userWalletId: UserWalletId,
yieldBalance: YieldBalance,
): Either<StakingError, List<BalanceItem>> {
return Either.catch {
if (yieldBalance is YieldBalance.Data) {
val (balancesToDisplay, transactionsToRemove) = mergeRealAndPendingTransactions(
yieldBalance = yieldBalance,
pending = stakingPendingTransactionRepository.getTransactionsWithBalanceItems(),
pending = stakingPendingTransactionRepository.getTransactionsWithBalanceItems(userWalletId),
)
stakingPendingTransactionRepository.removeTransactions(transactionsToRemove.toSet())
stakingPendingTransactionRepository.removeTransactions(userWalletId, transactionsToRemove.toSet())
balancesToDisplay
} else {

View file

@ -5,6 +5,7 @@ import com.tangem.domain.staking.model.PendingTransaction
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
import com.tangem.domain.wallets.models.UserWalletId
/**
* Use case for saving hash that failed to submit during staking confirmation
@ -14,9 +15,12 @@ class SavePendingTransactionUseCase(
private val stakingErrorResolver: StakingErrorResolver,
) {
operator fun invoke(pendingTransaction: PendingTransaction): Either<StakingError, Unit> {
operator fun invoke(userWalletId: UserWalletId, transaction: PendingTransaction): Either<StakingError, Unit> {
return Either.catch {
stakingPendingTransactionRepository.saveTransaction(pendingTransaction)
stakingPendingTransactionRepository.saveTransaction(
userWalletId = userWalletId,
transaction = transaction,
)
}.mapLeft {
stakingErrorResolver.resolve(it)
}

View file

@ -2,12 +2,13 @@ package com.tangem.domain.staking.repositories
import com.tangem.domain.staking.model.PendingTransaction
import com.tangem.domain.staking.model.stakekit.BalanceItem
import com.tangem.domain.wallets.models.UserWalletId
interface StakingPendingTransactionRepository {
fun getTransactionsWithBalanceItems(): List<Pair<PendingTransaction, BalanceItem>>
fun getTransactionsWithBalanceItems(userWalletId: UserWalletId): List<Pair<PendingTransaction, BalanceItem>>
fun saveTransaction(transaction: PendingTransaction)
fun saveTransaction(userWalletId: UserWalletId, transaction: PendingTransaction)
fun removeTransactions(transactions: Set<PendingTransaction>)
fun removeTransactions(userWalletId: UserWalletId, transactions: Set<PendingTransaction>)
}

View file

@ -264,7 +264,7 @@ internal class StakingTransactionSender @AssistedInject constructor(
}.onRight {
Timber.d("Successful hash submission")
if (transaction.type != StakingTransactionType.FREEZE_ENERGY) {
savePendingTransactionUseCase.invoke(pendingTransaction)
savePendingTransactionUseCase.invoke(userWallet.walletId, pendingTransaction)
}
}
}
@ -294,7 +294,8 @@ internal class StakingTransactionSender @AssistedInject constructor(
rawCurrencyId = cryptoCurrencyStatus.currency.id.rawCurrencyId,
validator = (confirmationState.validatorState as? ValidatorState.Content)?.chosenValidator,
balancesId = (cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data)?.getBalancesUniqueId() ?: 0,
balanceItems = (cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data)?.balance?.items ?: emptyList()
balanceItems = (cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data)?.balance?.items
?: emptyList(),
)
}

View file

@ -26,7 +26,8 @@ internal class SetPossiblePendingTransactionTransformer(
rawCurrencyId = balanceState.rawCurrencyId,
validator = balanceState.validator,
balancesId = balancesId,
balanceItems = (cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data)?.balance?.items ?: emptyList()
balanceItems = (cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data)?.balance?.items
?: emptyList(),
),
),
)

View file

@ -137,7 +137,7 @@ internal class StakingViewModel @Inject constructor(
private val balancesToShow: List<BalanceItem>
get() {
return cryptoCurrencyStatus.value.yieldBalance?.let {
invalidatePendingTransactionsUseCase(it).getOrElse { emptyList() }
invalidatePendingTransactionsUseCase(userWallet.walletId, it).getOrElse { emptyList() }
} ?: emptyList()
}

View file

@ -152,7 +152,7 @@ internal class TokenDetailsViewModel @Inject constructor(
private val swapTxJobHolder = JobHolder()
private val selectedAppCurrencyFlow: StateFlow<AppCurrency> = createSelectedAppCurrencyFlow()
private val stakingPendingBalances: List<BalanceItem>
get() = getStakingPendingTransactionsUseCase().getOrElse { emptyList() }
get() = getStakingPendingTransactionsUseCase(userWalletId).getOrElse { emptyList() }
private var cryptoCurrencyStatus: CryptoCurrencyStatus? = null
private var stakingEntryInfo: StakingEntryInfo? = null