Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-18 16:25:57 +02:00
parent fe6c26624a
commit 5060b5c028
19 changed files with 212 additions and 64 deletions

View file

@ -44,7 +44,7 @@ internal class DefaultP2PEthPoolRepository(
Timber.e("Error fetching P2PEthPool vaults: $error")
emptyList()
}
p2pEthPoolVaultsStore.store(vaults)
p2pEthPoolVaultsStore.store(vaults.filter { !it.isPrivate }) // TODO eth isSmoothingPool?
}
override suspend fun getVaults(network: P2PEthPoolNetwork): Either<StakingError, List<P2PEthPoolVault>> = either {

View file

@ -8,11 +8,12 @@ import com.tangem.domain.models.StatusSource
import com.tangem.domain.models.staking.*
import com.tangem.domain.staking.model.StakingIntegrationID
import kotlinx.datetime.Instant
import java.math.BigDecimal
/** Converts P2PEthPool API response to [StakingBalance.Data.P2PEthPool] */
/** Converts P2PEthPool API response to [StakingBalance] */
internal object P2PEthPoolStakingBalanceConverter {
fun convert(response: P2PEthPoolAccountResponse, source: StatusSource): StakingBalance.Data.P2PEthPool {
fun convert(response: P2PEthPoolAccountResponse, source: StatusSource): StakingBalance {
val stakingId = StakingID(
integrationId = StakingIntegrationID.P2PEthPool.value,
address = response.delegatorAddress,
@ -27,11 +28,22 @@ internal object P2PEthPoolStakingBalanceConverter {
exitQueue = convertExitQueue(response.exitQueue),
)
return StakingBalance.Data.P2PEthPool(
stakingId = stakingId,
source = source,
account = account,
)
val hasActivePosition = account.stake.assets > BigDecimal.ZERO ||
account.exitQueue.total > BigDecimal.ZERO ||
account.availableToWithdraw > BigDecimal.ZERO
return if (hasActivePosition) {
StakingBalance.Data.P2PEthPool(
stakingId = stakingId,
source = source,
account = account,
)
} else {
StakingBalance.Empty(
stakingId = stakingId,
source = source,
)
}
}
private fun convertStake(dto: P2PEthPoolStakeDTO): P2PEthPoolStake {

View file

@ -3,21 +3,26 @@ package com.tangem.data.staking.converters.ethpool
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolVaultDTO
import com.tangem.domain.staking.model.ethpool.P2PEthPoolVault
import com.tangem.utils.converter.Converter
import java.math.BigDecimal
import java.math.RoundingMode
/**
* Converter from P2PEthPool Vault DTO to Domain model
*/
internal object P2PEthPoolVaultConverter : Converter<P2PEthPoolVaultDTO, P2PEthPoolVault> {
private val HUNDRED = BigDecimal(100)
private const val DIVIDE_SCALE = 8
override fun convert(value: P2PEthPoolVaultDTO): P2PEthPoolVault {
return P2PEthPoolVault(
vaultAddress = value.vaultAddress,
displayName = value.displayName,
apy = value.apy.toBigDecimal(),
baseApy = value.baseApy.toBigDecimal(),
capacity = value.capacity.toBigDecimal(),
totalAssets = value.totalAssets.toBigDecimal(),
feePercent = value.feePercent.toBigDecimal(),
apy = value.apy.divide(HUNDRED, DIVIDE_SCALE, RoundingMode.HALF_UP),
baseApy = value.baseApy.divide(HUNDRED, DIVIDE_SCALE, RoundingMode.HALF_UP),
capacity = value.capacity,
totalAssets = value.totalAssets,
feePercent = value.feePercent,
isPrivate = value.isPrivate,
isGenesis = value.isGenesis,
isSmoothingPool = value.isSmoothingPool,

View file

@ -136,8 +136,8 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
val vaults = runSuspendCatching { p2pEthPoolVaultsStore.getSync() }.getOrNull().orEmpty()
if (vaults.isEmpty()) {
Timber.w("No P2PEthPool vaults available for $userWalletId")
p2PEthPoolBalancesStore.storeError(userWalletId = userWalletId, stakingIds = stakingIds)
Timber.w("No P2PEthPool vaults available for $userWalletId, storing empty balances")
p2PEthPoolBalancesStore.storeEmpty(userWalletId = userWalletId, stakingIds = stakingIds)
return
}

View file

@ -90,6 +90,15 @@ internal class DefaultP2PEthPoolBalancesStore(
}
}
override suspend fun storeEmpty(userWalletId: UserWalletId, stakingIds: Set<StakingID>) {
updateInRuntime(
userWalletId = userWalletId,
stakingIds = stakingIds,
ifNotFound = ::createEmptyStakingBalance,
update = { it.copySealed(source = StatusSource.ACTUAL) },
)
}
override suspend fun storeError(userWalletId: UserWalletId, stakingIds: Set<StakingID>) {
updateInRuntime(
userWalletId = userWalletId,
@ -187,5 +196,8 @@ internal class DefaultP2PEthPoolBalancesStore(
}
}
private fun createEmptyStakingBalance(id: StakingID): StakingBalance =
StakingBalance.Empty(stakingId = id, source = StatusSource.ACTUAL)
private fun createErrorStakingBalance(id: StakingID): StakingBalance = StakingBalance.Error(stakingId = id)
}

View file

@ -23,6 +23,8 @@ interface P2PEthPoolBalancesStore {
suspend fun storeActual(userWalletId: UserWalletId, values: Set<P2PEthPoolAccountResponse>)
suspend fun storeEmpty(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
suspend fun storeError(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
suspend fun clear(userWalletId: UserWalletId, stakingIds: Set<StakingID>)

View file

@ -13,7 +13,7 @@ internal fun YieldBalanceWrapperDTO.toDomain(source: StatusSource = StatusSource
internal fun P2PEthPoolAccountResponse.toDomain(
source: StatusSource = StatusSource.CACHE,
): StakingBalance.Data.P2PEthPool {
): StakingBalance {
return P2PEthPoolStakingBalanceConverter.convert(
response = this,
source = source,