Updated on 2026-08-14

This commit is contained in:
Tangem 2025-03-03 16:45:50 +04:00
parent ca286232ba
commit a10b94fa45
6 changed files with 75 additions and 16 deletions

View file

@ -4,6 +4,7 @@ import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.domain.managetokens.*
import com.tangem.domain.managetokens.repository.CustomTokensRepository
import com.tangem.domain.managetokens.repository.ManageTokensRepository
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
@ -65,6 +66,7 @@ internal object ManageTokensDomainModule {
currenciesRepository: CurrenciesRepository,
networksRepository: NetworksRepository,
derivationsRepository: DerivationsRepository,
stakingRepository: StakingRepository,
): SaveManagedTokensUseCase {
return SaveManagedTokensUseCase(
customTokensRepository = customTokensRepository,
@ -72,6 +74,7 @@ internal object ManageTokensDomainModule {
currenciesRepository = currenciesRepository,
networksRepository = networksRepository,
derivationsRepository = derivationsRepository,
stakingRepository = stakingRepository,
)
}

View file

@ -72,21 +72,35 @@ internal class DefaultStakingBalanceStore(
override suspend fun store(userWalletId: UserWalletId, items: Set<YieldBalanceWrapperDTO>) {
coroutineScope {
launch {
updateRuntimeStore(userWalletId = userWalletId) {
YieldBalanceConverter(isCached = false).convertSet(input = items)
val newBalances = YieldBalanceConverter(isCached = false).convertSet(input = items)
runtimeStore.update(default = emptyMap()) { saved ->
saved.toMutableMap().apply {
this[userWalletId] = saved[userWalletId]
?.addOrReplace(newBalances) { old, new ->
old.integrationId == new.integrationId && old.address == new.address
}
?: newBalances
}
}
}
launch { storeInPersistenceStore(userWalletId = userWalletId, items = items) }
}
}
override suspend fun refresh(userWalletId: UserWalletId) {
override suspend fun refresh(userWalletId: UserWalletId, addressWithIntegrationIdMap: Map<String, String>) {
updateRuntimeStore(userWalletId = userWalletId) { saved ->
saved.mapTo(hashSetOf()) {
when (it) {
is YieldBalance.Data -> it.copy(source = StatusSource.CACHE)
is YieldBalance.Empty -> it.copy(source = StatusSource.CACHE)
is YieldBalance.Error -> it
saved.mapTo(hashSetOf()) { balance ->
val refreshIntegrationId = addressWithIntegrationIdMap[balance.address]
if (balance.integrationId == refreshIntegrationId) {
when (balance) {
is YieldBalance.Data -> balance.copy(source = StatusSource.CACHE)
is YieldBalance.Empty -> balance.copy(source = StatusSource.CACHE)
is YieldBalance.Error -> balance
}
} else {
balance
}
}
}
@ -114,11 +128,13 @@ internal class DefaultStakingBalanceStore(
) {
val newBalance = YieldBalanceConverter(isCached = false).convert(value = item)
val balances = getSyncOrNull(userWalletId)
?.addOrReplace(newBalance) { it.integrationId == integrationId && it.address == address }
?: setOf(newBalance)
updateRuntimeStore(userWalletId = userWalletId) { balances }
runtimeStore.update(default = emptyMap()) { saved ->
saved.toMutableMap().apply {
this[userWalletId] = saved[userWalletId]
?.addOrReplace(newBalance) { it.integrationId == integrationId && it.address == address }
?: setOf(newBalance)
}
}
}
private suspend fun updateRuntimeStore(
@ -135,7 +151,11 @@ internal class DefaultStakingBalanceStore(
private suspend fun storeInPersistenceStore(userWalletId: UserWalletId, items: Set<YieldBalanceWrapperDTO>) {
persistenceStore.updateData { current ->
current.toMutableMap().apply {
this[userWalletId.stringValue] = items
this[userWalletId.stringValue] = current[userWalletId.stringValue]
?.addOrReplace(items = items) { old, new ->
old.integrationId == new.integrationId && old.addresses.address == new.addresses.address
}
?: items
}
}
}
@ -159,6 +179,8 @@ internal class DefaultStakingBalanceStore(
cachedBalances: Set<YieldBalance>,
runtimeBalances: Set<YieldBalance>,
): Set<YieldBalance> {
if (runtimeBalances.isEmpty()) return cachedBalances
return runtimeBalances
.map { runtime ->
runtime.takeIf { runtime !is YieldBalance.Error }

View file

@ -27,5 +27,5 @@ interface StakingBalanceStore {
/** Store [item] by [userWalletId], [integrationId] and [address] */
suspend fun store(userWalletId: UserWalletId, integrationId: String, address: String, item: YieldBalanceWrapperDTO)
suspend fun refresh(userWalletId: UserWalletId)
suspend fun refresh(userWalletId: UserWalletId, addressWithIntegrationIdMap: Map<String, String>)
}

View file

@ -403,13 +403,31 @@ internal class DefaultStakingRepository(
?: YieldBalance.Error(integrationId, address)
}
@Suppress("LongMethod")
override suspend fun fetchMultiYieldBalance(
userWalletId: UserWalletId,
cryptoCurrencies: List<CryptoCurrency>,
refresh: Boolean,
) = withContext(dispatchers.io) {
if (refresh) {
stakingBalanceStore.refresh(userWalletId = userWalletId)
stakingBalanceStore.refresh(
userWalletId = userWalletId,
addressWithIntegrationIdMap = cryptoCurrencies
.mapNotNull { currency ->
val addresses = walletManagersFacade.getAddresses(userWalletId, currency.network)
val integrationId = integrationIdMap[getIntegrationKey(currency.id)]
if (integrationId != null) {
addresses to integrationId
} else {
null
}
}
.flatMap { (addresses, integrationId) ->
addresses.map { address -> integrationId to address.value }
}
.toMap(),
)
}
cacheRegistry.invokeOnExpire(

View file

@ -15,6 +15,7 @@ dependencies {
api(projects.domain.core)
implementation(projects.domain.wallets.models)
implementation(projects.domain.tokens.models)
implementation(projects.domain.staking)
implementation(projects.domain.tokens)
implementation(projects.domain.card)
implementation(projects.domain.legacy)

View file

@ -5,6 +5,7 @@ import arrow.core.flatten
import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
import com.tangem.domain.managetokens.repository.CustomTokensRepository
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.repository.CurrenciesRepository
@ -18,6 +19,7 @@ class SaveManagedTokensUseCase(
private val currenciesRepository: CurrenciesRepository,
private val networksRepository: NetworksRepository,
private val derivationsRepository: DerivationsRepository,
private val stakingRepository: StakingRepository,
) {
suspend operator fun invoke(
@ -50,6 +52,8 @@ class SaveManagedTokensUseCase(
existingCurrencies = existingCurrencies,
currenciesToAdd = addingCurrencies,
)
refreshUpdatedYieldBalances(userWalletId, existingCurrencies)
}
private suspend fun removeCurrenciesFromWalletManager(
@ -90,6 +94,17 @@ class SaveManagedTokensUseCase(
)
}
private suspend fun refreshUpdatedYieldBalances(
userWalletId: UserWalletId,
existingCurrencies: List<CryptoCurrency>,
) {
stakingRepository.fetchMultiYieldBalance(
userWalletId = userWalletId,
cryptoCurrencies = existingCurrencies,
refresh = true,
)
}
/**
* Determines if the [existingCurrencies] list contains a coin that corresponds
* to the given [network].