Updated on 2026-08-14
This commit is contained in:
parent
721ab042e0
commit
7d599256d1
27 changed files with 366 additions and 454 deletions
|
|
@ -2,21 +2,32 @@ package com.tangem.data.staking
|
|||
|
||||
import arrow.core.Either
|
||||
import arrow.core.getOrElse
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.raise.ensure
|
||||
import com.tangem.data.staking.converters.ethpool.*
|
||||
import com.tangem.data.staking.converters.ethpool.P2PEthPoolBroadcastResultConverter
|
||||
import com.tangem.data.staking.converters.ethpool.P2PEthPoolErrorConverter
|
||||
import com.tangem.data.staking.converters.ethpool.P2PEthPoolRewardConverter
|
||||
import com.tangem.data.staking.converters.ethpool.P2PEthPoolStakingAccountConverter
|
||||
import com.tangem.data.staking.converters.ethpool.P2PEthPoolUnsignedTxConverter
|
||||
import com.tangem.data.staking.converters.ethpool.P2PEthPoolVaultConverter
|
||||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.ethpool.P2PEthPoolApi
|
||||
import com.tangem.datasource.api.ethpool.models.request.P2PEthPoolBroadcastRequest
|
||||
import com.tangem.datasource.api.ethpool.models.request.P2PEthPoolDepositRequest
|
||||
import com.tangem.datasource.api.ethpool.models.request.P2PEthPoolUnstakeRequest
|
||||
import com.tangem.datasource.api.ethpool.models.request.P2PEthPoolWithdrawRequest
|
||||
import com.tangem.datasource.api.ethpool.models.request.P2PEthPoolTransactionRequest
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolResponse
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolTransactionResponse
|
||||
import com.tangem.datasource.local.token.P2PEthPoolVaultsStore
|
||||
import com.tangem.domain.models.staking.P2PEthPoolStakingAccount
|
||||
import com.tangem.domain.staking.model.StakingAvailability
|
||||
import com.tangem.domain.staking.model.StakingOption
|
||||
import com.tangem.domain.staking.model.ethpool.*
|
||||
import com.tangem.domain.staking.repositories.P2PEthPoolRepository
|
||||
import com.tangem.domain.staking.model.ethpool.P2PEthPoolBroadcastResult
|
||||
import com.tangem.domain.staking.model.ethpool.P2PEthPoolNetwork
|
||||
import com.tangem.domain.staking.model.ethpool.P2PEthPoolReward
|
||||
import com.tangem.domain.staking.model.ethpool.P2PEthPoolUnsignedTx
|
||||
import com.tangem.domain.staking.model.ethpool.P2PEthPoolVault
|
||||
import com.tangem.domain.staking.model.stakekit.StakingError
|
||||
import com.tangem.domain.staking.repositories.P2PEthPoolRepository
|
||||
import com.tangem.domain.staking.toggles.StakingFeatureToggles
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -36,11 +47,30 @@ internal class DefaultP2PEthPoolRepository(
|
|||
) : P2PEthPoolRepository {
|
||||
|
||||
private val vaultConverter = P2PEthPoolVaultConverter
|
||||
private val accountInfoConverter = P2PEthPoolAccountConverter
|
||||
private val accountConverter = P2PEthPoolStakingAccountConverter
|
||||
private val rewardConverter = P2PEthPoolRewardConverter
|
||||
private val broadcastResultConverter = P2PEthPoolBroadcastResultConverter
|
||||
private val errorConverter = P2PEthPoolErrorConverter
|
||||
|
||||
/**
|
||||
* Handles P2PEthPool API response with error checking and result extraction.
|
||||
* Reduces duplication across all API call methods.
|
||||
*/
|
||||
private inline fun <T, R> Raise<StakingError>.handleApiResponse(
|
||||
response: ApiResponse<P2PEthPoolResponse<T>>,
|
||||
transform: (T) -> R,
|
||||
): R = when (response) {
|
||||
is ApiResponse.Success -> {
|
||||
val data = response.data
|
||||
ensure(data.error == null) {
|
||||
errorConverter.convertFromErrorDetails(requireNotNull(data.error))
|
||||
}
|
||||
val result = requireNotNull(data.result) { "Result is null in successful response" }
|
||||
transform(result)
|
||||
}
|
||||
is ApiResponse.Error -> raise(StakingError.UnknownError(response.cause))
|
||||
}
|
||||
|
||||
override suspend fun fetchVaults(network: P2PEthPoolNetwork) {
|
||||
val vaults = if (stakingFeatureToggles.isEthStakingEnabled) {
|
||||
getVaults(network).getOrElse { error ->
|
||||
|
|
@ -56,16 +86,8 @@ internal class DefaultP2PEthPoolRepository(
|
|||
|
||||
override suspend fun getVaults(network: P2PEthPoolNetwork): Either<StakingError, List<P2PEthPoolVault>> = either {
|
||||
withContext(dispatchers.io) {
|
||||
when (val response = p2pEthPoolApi.getVaults(network.value)) {
|
||||
is ApiResponse.Success -> {
|
||||
val data = response.data
|
||||
ensure(data.error == null) {
|
||||
errorConverter.convertFromErrorDetails(requireNotNull(data.error))
|
||||
}
|
||||
val result = requireNotNull(data.result) { "Result is null in successful response" }
|
||||
result.vaults.map { vaultConverter.convert(it) }
|
||||
}
|
||||
is ApiResponse.Error -> raise(StakingError.UnknownError(response.cause))
|
||||
handleApiResponse(p2pEthPoolApi.getVaults(network.value)) { result ->
|
||||
result.vaults.map { vaultConverter.convert(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -75,81 +97,60 @@ internal class DefaultP2PEthPoolRepository(
|
|||
delegatorAddress: String,
|
||||
vaultAddress: String,
|
||||
amount: String,
|
||||
): Either<StakingError, P2PEthPoolUnsignedTx> = either {
|
||||
withContext(dispatchers.io) {
|
||||
val requestBody = P2PEthPoolDepositRequest(
|
||||
delegatorAddress = delegatorAddress,
|
||||
vaultAddress = vaultAddress,
|
||||
amount = amount.toDoubleOrNull() ?: raise(StakingError.InvalidAmount("Invalid amount format: $amount")),
|
||||
)
|
||||
val response = p2pEthPoolApi.createDepositTransaction(network.value, requestBody)
|
||||
when (response) {
|
||||
is ApiResponse.Success -> {
|
||||
val data = response.data
|
||||
ensure(data.error == null) {
|
||||
errorConverter.convertFromErrorDetails(requireNotNull(data.error))
|
||||
}
|
||||
val result = requireNotNull(data.result) { "Result is null in successful response" }
|
||||
P2PEthPoolUnsignedTxConverter.convert(result.unsignedTransaction)
|
||||
}
|
||||
is ApiResponse.Error -> raise(StakingError.UnknownError(response.cause))
|
||||
}
|
||||
}
|
||||
}
|
||||
): Either<StakingError, P2PEthPoolUnsignedTx> = createStakingTransaction(
|
||||
network = network,
|
||||
delegatorAddress = delegatorAddress,
|
||||
vaultAddress = vaultAddress,
|
||||
amount = amount,
|
||||
apiCall = p2pEthPoolApi::createDepositTransaction,
|
||||
)
|
||||
|
||||
override suspend fun createUnstakeTransaction(
|
||||
network: P2PEthPoolNetwork,
|
||||
stakerPublicKey: String,
|
||||
stakeTransactionHash: String,
|
||||
): Either<StakingError, P2PEthPoolUnsignedTx> = either {
|
||||
withContext(dispatchers.io) {
|
||||
val requestBody = P2PEthPoolUnstakeRequest(
|
||||
stakerPublicKey = stakerPublicKey,
|
||||
stakeTransactionHash = stakeTransactionHash,
|
||||
)
|
||||
val response = p2pEthPoolApi.createUnstakeTransaction(network.value, requestBody)
|
||||
when (response) {
|
||||
is ApiResponse.Success -> {
|
||||
val data = response.data
|
||||
ensure(data.error == null) {
|
||||
errorConverter.convertFromErrorDetails(requireNotNull(data.error))
|
||||
}
|
||||
val result = requireNotNull(data.result) { "Result is null in successful response" }
|
||||
// Note: API returns only hex string for unstake, not full transaction structure
|
||||
P2PEthPoolUnsignedTx(
|
||||
serializeTx = result.unstakeTransactionHex,
|
||||
to = "", // Will be parsed from hex by wallet
|
||||
data = result.unstakeTransactionHex,
|
||||
value = java.math.BigDecimal.ZERO,
|
||||
nonce = 0,
|
||||
chainId = network.chainId,
|
||||
gasLimit = java.math.BigDecimal.ZERO,
|
||||
maxFeePerGas = java.math.BigDecimal.ZERO,
|
||||
maxPriorityFeePerGas = java.math.BigDecimal.ZERO,
|
||||
)
|
||||
}
|
||||
is ApiResponse.Error -> raise(StakingError.UnknownError(response.cause))
|
||||
}
|
||||
}
|
||||
}
|
||||
delegatorAddress: String,
|
||||
vaultAddress: String,
|
||||
amount: String,
|
||||
): Either<StakingError, P2PEthPoolUnsignedTx> = createStakingTransaction(
|
||||
network = network,
|
||||
delegatorAddress = delegatorAddress,
|
||||
vaultAddress = vaultAddress,
|
||||
amount = amount,
|
||||
apiCall = p2pEthPoolApi::createUnstakeTransaction,
|
||||
)
|
||||
|
||||
override suspend fun createWithdrawTransaction(
|
||||
network: P2PEthPoolNetwork,
|
||||
stakerAddress: String,
|
||||
delegatorAddress: String,
|
||||
vaultAddress: String,
|
||||
amount: String,
|
||||
): Either<StakingError, P2PEthPoolUnsignedTx> = createStakingTransaction(
|
||||
network = network,
|
||||
delegatorAddress = delegatorAddress,
|
||||
vaultAddress = vaultAddress,
|
||||
amount = amount,
|
||||
apiCall = p2pEthPoolApi::createWithdrawTransaction,
|
||||
)
|
||||
|
||||
private suspend fun createStakingTransaction(
|
||||
network: P2PEthPoolNetwork,
|
||||
delegatorAddress: String,
|
||||
vaultAddress: String,
|
||||
amount: String,
|
||||
apiCall:
|
||||
suspend (
|
||||
String,
|
||||
P2PEthPoolTransactionRequest,
|
||||
) -> ApiResponse<P2PEthPoolResponse<P2PEthPoolTransactionResponse>>,
|
||||
): Either<StakingError, P2PEthPoolUnsignedTx> = either {
|
||||
withContext(dispatchers.io) {
|
||||
val requestBody = P2PEthPoolWithdrawRequest(stakerAddress = stakerAddress)
|
||||
val response = p2pEthPoolApi.createWithdrawTransaction(network.value, requestBody)
|
||||
when (response) {
|
||||
is ApiResponse.Success -> {
|
||||
val data = response.data
|
||||
ensure(data.error == null) {
|
||||
errorConverter.convertFromErrorDetails(requireNotNull(data.error))
|
||||
}
|
||||
val result = requireNotNull(data.result) { "Result is null in successful response" }
|
||||
P2PEthPoolUnsignedTxConverter.convert(result.unsignedTransaction)
|
||||
}
|
||||
is ApiResponse.Error -> raise(StakingError.UnknownError(response.cause))
|
||||
val requestBody = P2PEthPoolTransactionRequest(
|
||||
delegatorAddress = delegatorAddress,
|
||||
vaultAddress = vaultAddress,
|
||||
amount = amount.toBigDecimalOrNull()
|
||||
?: raise(StakingError.InvalidAmount("Invalid amount format: $amount")),
|
||||
)
|
||||
handleApiResponse(apiCall(network.value, requestBody)) { result ->
|
||||
P2PEthPoolUnsignedTxConverter.convert(result.unsignedTransaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -160,17 +161,8 @@ internal class DefaultP2PEthPoolRepository(
|
|||
): Either<StakingError, P2PEthPoolBroadcastResult> = either {
|
||||
withContext(dispatchers.io) {
|
||||
val requestBody = P2PEthPoolBroadcastRequest(signedTransaction = signedTransaction)
|
||||
val response = p2pEthPoolApi.broadcastTransaction(network.value, requestBody)
|
||||
when (response) {
|
||||
is ApiResponse.Success -> {
|
||||
val data = response.data
|
||||
ensure(data.error == null) {
|
||||
errorConverter.convertFromErrorDetails(requireNotNull(data.error))
|
||||
}
|
||||
val result = requireNotNull(data.result) { "Result is null in successful response" }
|
||||
broadcastResultConverter.convert(result)
|
||||
}
|
||||
is ApiResponse.Error -> raise(StakingError.UnknownError(response.cause))
|
||||
handleApiResponse(p2pEthPoolApi.broadcastTransaction(network.value, requestBody)) { result ->
|
||||
broadcastResultConverter.convert(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -179,19 +171,12 @@ internal class DefaultP2PEthPoolRepository(
|
|||
network: P2PEthPoolNetwork,
|
||||
delegatorAddress: String,
|
||||
vaultAddress: String,
|
||||
): Either<StakingError, P2PEthPoolAccount> = either {
|
||||
): Either<StakingError, P2PEthPoolStakingAccount> = either {
|
||||
withContext(dispatchers.io) {
|
||||
val response = p2pEthPoolApi.getAccountInfo(network.value, delegatorAddress, vaultAddress)
|
||||
when (response) {
|
||||
is ApiResponse.Success -> {
|
||||
val data = response.data
|
||||
ensure(data.error == null) {
|
||||
errorConverter.convertFromErrorDetails(requireNotNull(data.error))
|
||||
}
|
||||
val result = requireNotNull(data.result) { "Result is null in successful response" }
|
||||
accountInfoConverter.convert(result)
|
||||
}
|
||||
is ApiResponse.Error -> raise(StakingError.UnknownError(response.cause))
|
||||
handleApiResponse(
|
||||
p2pEthPoolApi.getAccountInfo(network.value, delegatorAddress, vaultAddress),
|
||||
) { result ->
|
||||
accountConverter.convert(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -203,22 +188,15 @@ internal class DefaultP2PEthPoolRepository(
|
|||
period: Int?,
|
||||
): Either<StakingError, List<P2PEthPoolReward>> = either {
|
||||
withContext(dispatchers.io) {
|
||||
val response = p2pEthPoolApi.getRewards(
|
||||
network = network.value,
|
||||
delegatorAddress = delegatorAddress,
|
||||
vaultAddress = vaultAddress,
|
||||
period = period,
|
||||
)
|
||||
when (response) {
|
||||
is ApiResponse.Success -> {
|
||||
val data = response.data
|
||||
ensure(data.error == null) {
|
||||
errorConverter.convertFromErrorDetails(requireNotNull(data.error))
|
||||
}
|
||||
val result = requireNotNull(data.result) { "Result is null in successful response" }
|
||||
result.rewards.map { rewardConverter.convert(it) }
|
||||
}
|
||||
is ApiResponse.Error -> raise(StakingError.UnknownError(response.cause))
|
||||
handleApiResponse(
|
||||
p2pEthPoolApi.getRewards(
|
||||
network = network.value,
|
||||
delegatorAddress = delegatorAddress,
|
||||
vaultAddress = vaultAddress,
|
||||
period = period,
|
||||
),
|
||||
) { result ->
|
||||
result.rewards.map { rewardConverter.convert(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,17 +4,20 @@ import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolAccountRespon
|
|||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolExitQueueDTO
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolExitRequestDTO
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolStakeDTO
|
||||
import com.tangem.domain.staking.model.ethpool.*
|
||||
import com.tangem.domain.models.staking.P2PEthPoolExitQueue
|
||||
import com.tangem.domain.models.staking.P2PEthPoolExitRequest
|
||||
import com.tangem.domain.models.staking.P2PEthPoolStake
|
||||
import com.tangem.domain.models.staking.P2PEthPoolStakingAccount
|
||||
import com.tangem.utils.converter.Converter
|
||||
import org.joda.time.Instant
|
||||
import kotlinx.datetime.Instant
|
||||
|
||||
/**
|
||||
* Converter from P2PEthPool Account Info Response to Domain model
|
||||
* Converts P2PEthPool Account API response to domain [P2PEthPoolStakingAccount].
|
||||
*/
|
||||
internal object P2PEthPoolAccountConverter : Converter<P2PEthPoolAccountResponse, P2PEthPoolAccount> {
|
||||
internal object P2PEthPoolStakingAccountConverter : Converter<P2PEthPoolAccountResponse, P2PEthPoolStakingAccount> {
|
||||
|
||||
override fun convert(value: P2PEthPoolAccountResponse): P2PEthPoolAccount {
|
||||
return P2PEthPoolAccount(
|
||||
override fun convert(value: P2PEthPoolAccountResponse): P2PEthPoolStakingAccount {
|
||||
return P2PEthPoolStakingAccount(
|
||||
delegatorAddress = value.delegatorAddress,
|
||||
vaultAddress = value.vaultAddress,
|
||||
stake = convertStake(value.stake),
|
||||
|
|
@ -24,26 +27,26 @@ internal object P2PEthPoolAccountConverter : Converter<P2PEthPoolAccountResponse
|
|||
)
|
||||
}
|
||||
|
||||
private fun convertStake(dto: P2PEthPoolStakeDTO): P2PEthPoolStake {
|
||||
fun convertStake(dto: P2PEthPoolStakeDTO): P2PEthPoolStake {
|
||||
return P2PEthPoolStake(
|
||||
assets = dto.assets,
|
||||
totalEarnedAssets = dto.totalEarnedAssets,
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertExitQueue(dto: P2PEthPoolExitQueueDTO): P2PEthPoolExitQueue {
|
||||
fun convertExitQueue(dto: P2PEthPoolExitQueueDTO): P2PEthPoolExitQueue {
|
||||
return P2PEthPoolExitQueue(
|
||||
total = dto.total.toBigDecimal(),
|
||||
total = dto.total,
|
||||
requests = dto.requests.map(::convertExitRequest),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertExitRequest(dto: P2PEthPoolExitRequestDTO): P2PEthPoolExitRequest {
|
||||
fun convertExitRequest(dto: P2PEthPoolExitRequestDTO): P2PEthPoolExitRequest {
|
||||
return P2PEthPoolExitRequest(
|
||||
ticket = dto.ticket,
|
||||
totalAssets = dto.totalAssets.toBigDecimal(),
|
||||
timestamp = Instant.ofEpochSecond(dto.timestamp),
|
||||
withdrawalTimestamp = Instant.ofEpochSecond(dto.withdrawalTimestamp),
|
||||
totalAssets = dto.totalAssets,
|
||||
timestamp = Instant.fromEpochMilliseconds(dto.timestamp),
|
||||
withdrawalTimestamp = dto.withdrawalTimestamp?.let { Instant.fromEpochMilliseconds(it) },
|
||||
isClaimable = dto.isClaimable,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,16 +1,17 @@
|
|||
package com.tangem.data.staking.converters.ethpool
|
||||
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolAccountResponse
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolExitQueueDTO
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolExitRequestDTO
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolStakeDTO
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.staking.*
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
import kotlinx.datetime.Instant
|
||||
import java.math.BigDecimal
|
||||
|
||||
/** Converts P2PEthPool API response to [StakingBalance] */
|
||||
/**
|
||||
* Converts P2PEthPool API response to [StakingBalance].
|
||||
*
|
||||
* Uses [P2PEthPoolStakingAccountConverter] for account conversion to avoid duplication.
|
||||
*/
|
||||
internal object P2PEthPoolStakingBalanceConverter {
|
||||
|
||||
fun convert(response: P2PEthPoolAccountResponse, source: StatusSource): StakingBalance {
|
||||
|
|
@ -19,14 +20,7 @@ internal object P2PEthPoolStakingBalanceConverter {
|
|||
address = response.delegatorAddress,
|
||||
)
|
||||
|
||||
val account = P2PEthPoolStakingAccount(
|
||||
delegatorAddress = response.delegatorAddress,
|
||||
vaultAddress = response.vaultAddress,
|
||||
stake = convertStake(response.stake),
|
||||
availableToUnstake = response.availableToUnstake,
|
||||
availableToWithdraw = response.availableToWithdraw,
|
||||
exitQueue = convertExitQueue(response.exitQueue),
|
||||
)
|
||||
val account = P2PEthPoolStakingAccountConverter.convert(response)
|
||||
|
||||
val hasActivePosition = account.stake.assets > BigDecimal.ZERO ||
|
||||
account.exitQueue.total > BigDecimal.ZERO ||
|
||||
|
|
@ -45,28 +39,4 @@ internal object P2PEthPoolStakingBalanceConverter {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertStake(dto: P2PEthPoolStakeDTO): P2PEthPoolStake {
|
||||
return P2PEthPoolStake(
|
||||
assets = dto.assets,
|
||||
totalEarnedAssets = dto.totalEarnedAssets,
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertExitQueue(dto: P2PEthPoolExitQueueDTO): P2PEthPoolExitQueue {
|
||||
return P2PEthPoolExitQueue(
|
||||
total = dto.total.toBigDecimal(),
|
||||
requests = dto.requests.map(::convertExitRequest),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertExitRequest(dto: P2PEthPoolExitRequestDTO): P2PEthPoolExitRequest {
|
||||
return P2PEthPoolExitRequest(
|
||||
ticket = dto.ticket,
|
||||
totalAssets = dto.totalAssets.toBigDecimal(),
|
||||
timestamp = Instant.fromEpochSeconds(dto.timestamp),
|
||||
withdrawalTimestamp = Instant.fromEpochSeconds(dto.withdrawalTimestamp),
|
||||
isClaimable = dto.isClaimable,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.data.staking.store
|
||||
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Base interface for staking balances stores.
|
||||
*
|
||||
* Defines common read/query operations shared by all staking provider stores.
|
||||
*/
|
||||
interface BaseStakingBalancesStore {
|
||||
|
||||
/** Get flow of staking balances for a wallet */
|
||||
fun get(userWalletId: UserWalletId): Flow<Set<StakingBalance>>
|
||||
|
||||
/** Get a single staking balance synchronously */
|
||||
suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): StakingBalance?
|
||||
|
||||
/** Get all staking balances for a wallet synchronously */
|
||||
suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<StakingBalance>?
|
||||
|
||||
/** Refresh a single staking balance from cache */
|
||||
suspend fun refresh(userWalletId: UserWalletId, stakingId: StakingID)
|
||||
|
||||
/** Refresh multiple staking balances from cache */
|
||||
suspend fun refresh(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
|
||||
/** Store error state for staking balances */
|
||||
suspend fun storeError(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
|
||||
/** Clear staking balances */
|
||||
suspend fun clear(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
}
|
||||
|
|
@ -1,31 +1,19 @@
|
|||
package com.tangem.data.staking.store
|
||||
|
||||
import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolAccountResponse
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Store for P2PEthPool staking balances
|
||||
* Store for P2PEthPool staking balances.
|
||||
*
|
||||
* Extends [BaseStakingBalancesStore] with P2PEthPool-specific storage operations.
|
||||
*/
|
||||
interface P2PEthPoolBalancesStore {
|
||||
|
||||
fun get(userWalletId: UserWalletId): Flow<Set<StakingBalance>>
|
||||
|
||||
suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): StakingBalance?
|
||||
|
||||
suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<StakingBalance>?
|
||||
|
||||
suspend fun refresh(userWalletId: UserWalletId, stakingId: StakingID)
|
||||
|
||||
suspend fun refresh(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
interface P2PEthPoolBalancesStore : BaseStakingBalancesStore {
|
||||
|
||||
/** Store actual P2PEthPool account balances */
|
||||
suspend fun storeActual(userWalletId: UserWalletId, values: Set<P2PEthPoolAccountResponse>)
|
||||
|
||||
/** Store empty state for accounts with no active positions */
|
||||
suspend fun storeEmpty(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
|
||||
suspend fun storeError(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
|
||||
suspend fun clear(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
}
|
||||
|
|
@ -1,27 +1,15 @@
|
|||
package com.tangem.data.staking.store
|
||||
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.domain.models.staking.StakingID
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/** Store of StakeKit [StakingBalance] */
|
||||
interface StakingBalancesStore {
|
||||
|
||||
fun get(userWalletId: UserWalletId): Flow<Set<StakingBalance>>
|
||||
|
||||
suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingId: StakingID): StakingBalance?
|
||||
|
||||
suspend fun getAllSyncOrNull(userWalletId: UserWalletId): Set<StakingBalance>?
|
||||
|
||||
suspend fun refresh(userWalletId: UserWalletId, stakingId: StakingID)
|
||||
|
||||
suspend fun refresh(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
/**
|
||||
* Store for StakeKit staking balances.
|
||||
*
|
||||
* Extends [BaseStakingBalancesStore] with StakeKit-specific storage operations.
|
||||
*/
|
||||
interface StakingBalancesStore : BaseStakingBalancesStore {
|
||||
|
||||
/** Store actual StakeKit yield balances */
|
||||
suspend fun storeActual(userWalletId: UserWalletId, values: Set<YieldBalanceWrapperDTO>)
|
||||
|
||||
suspend fun storeError(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
|
||||
suspend fun clear(userWalletId: UserWalletId, stakingIds: Set<StakingID>)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue