Updated on 2026-08-14

This commit is contained in:
Tangem 2024-06-27 20:32:12 +03:00
parent eec5a60676
commit 20dc8c9d90
19 changed files with 436 additions and 89 deletions

View file

@ -2,27 +2,47 @@ package com.tangem.data.staking
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.toCoinId
import com.tangem.data.common.cache.CacheRegistry
import com.tangem.data.staking.converters.*
import com.tangem.data.staking.converters.StakingNetworkTypeConverter
import com.tangem.data.staking.converters.TokenConverter
import com.tangem.data.staking.converters.YieldConverter
import com.tangem.data.staking.converters.action.ActionStatusConverter
import com.tangem.data.staking.converters.action.EnterActionResponseConverter
import com.tangem.data.staking.converters.action.StakingActionTypeConverter
import com.tangem.data.staking.converters.transaction.GasEstimateConverter
import com.tangem.data.staking.converters.transaction.StakingTransactionConverter
import com.tangem.data.staking.converters.transaction.StakingTransactionStatusConverter
import com.tangem.data.staking.converters.transaction.StakingTransactionTypeConverter
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.stakekit.StakeKitApi
import com.tangem.datasource.api.stakekit.models.request.Address
import com.tangem.datasource.api.stakekit.models.request.ConstructTransactionRequestBody
import com.tangem.datasource.api.stakekit.models.request.EnterActionRequestBody
import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.domain.staking.model.StakingAvailability
import com.tangem.domain.staking.model.StakingEntryInfo
import com.tangem.domain.staking.model.Token
import com.tangem.domain.staking.model.Yield
import com.tangem.domain.staking.model.action.EnterAction
import com.tangem.domain.staking.model.transaction.StakingTransaction
import com.tangem.data.common.cache.CacheRegistry
import com.tangem.data.staking.converters.*
import com.tangem.datasource.api.stakekit.models.request.YieldBalanceRequestBody
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
import com.tangem.datasource.local.token.StakingBalanceStore
import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.domain.staking.model.*
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyAddress
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.toFormattedString
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.cancellable
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.math.BigDecimal
internal class DefaultStakingRepository(
private val stakeKitApi: StakeKitApi,
@ -33,13 +53,31 @@ internal class DefaultStakingRepository(
) : StakingRepository {
private val stakingNetworkTypeConverter = StakingNetworkTypeConverter()
private val networkTypeConverter = StakingNetworkTypeConverter()
private val transactionStatusConverter = StakingTransactionStatusConverter()
private val transactionTypeConverter = StakingTransactionTypeConverter()
private val actionStatusConverter = ActionStatusConverter()
private val stakingActionTypeConverter = StakingActionTypeConverter()
private val tokenConverter = TokenConverter(
stakingNetworkTypeConverter = stakingNetworkTypeConverter,
)
private val yieldConverter = YieldConverter(
tokenConverter = tokenConverter,
)
private val gasEstimateConverter = GasEstimateConverter(
tokenConverter = tokenConverter,
)
private val transactionConverter = StakingTransactionConverter(
networkTypeConverter = networkTypeConverter,
transactionStatusConverter = transactionStatusConverter,
transactionTypeConverter = transactionTypeConverter,
gasEstimateConverter = gasEstimateConverter,
)
private val enterActionResponseConverter = EnterActionResponseConverter(
actionStatusConverter = actionStatusConverter,
stakingActionTypeConverter = stakingActionTypeConverter,
transactionConverter = transactionConverter,
)
private val yieldBalanceConverter = YieldBalanceConverter()
@ -108,6 +146,40 @@ internal class DefaultStakingRepository(
}
}
override suspend fun createEnterAction(
integrationId: String,
amount: BigDecimal,
address: String,
validatorAddress: String,
token: Token,
): EnterAction {
return withContext(dispatchers.io) {
val body = EnterActionRequestBody(
integrationId = integrationId,
addresses = Address(address),
args = EnterActionRequestBody.EnterActionRequestBodyArgs(
amount = amount.toFormattedString(token.decimals),
inputToken = tokenConverter.convertBack(token),
validatorAddress = validatorAddress,
),
)
val response = stakeKitApi.createEnterAction(body)
enterActionResponseConverter.convert(response.getOrThrow())
}
}
override suspend fun constructTransaction(transactionId: String): StakingTransaction {
return withContext(dispatchers.io) {
val transactionResponse = stakeKitApi.constructTransaction(
transactionId = transactionId,
body = ConstructTransactionRequestBody(),
)
transactionConverter.convert(transactionResponse.getOrThrow())
}
}
override suspend fun fetchSingleYieldBalance(
userWalletId: UserWalletId,
address: String,

View file

@ -2,10 +2,10 @@ package com.tangem.data.staking.converters
import com.tangem.datasource.api.stakekit.models.response.model.NetworkTypeDTO
import com.tangem.domain.staking.model.NetworkType
import com.tangem.utils.converter.Converter
import com.tangem.utils.converter.TwoWayConverter
@Suppress("CyclomaticComplexMethod", "LongMethod")
class StakingNetworkTypeConverter : Converter<NetworkTypeDTO, NetworkType> {
class StakingNetworkTypeConverter : TwoWayConverter<NetworkTypeDTO, NetworkType> {
override fun convert(value: NetworkTypeDTO): NetworkType {
return when (value) {
@ -78,4 +78,76 @@ class StakingNetworkTypeConverter : Converter<NetworkTypeDTO, NetworkType> {
else -> NetworkType.UNKNOWN
}
}
override fun convertBack(value: NetworkType): NetworkTypeDTO {
return when (value) {
NetworkType.AVALANCHE_C -> NetworkTypeDTO.AVALANCHE_C
NetworkType.AVALANCHE_ATOMIC -> NetworkTypeDTO.AVALANCHE_ATOMIC
NetworkType.AVALANCHE_P -> NetworkTypeDTO.AVALANCHE_P
NetworkType.ARBITRUM -> NetworkTypeDTO.ARBITRUM
NetworkType.BINANCE -> NetworkTypeDTO.BINANCE
NetworkType.CELO -> NetworkTypeDTO.CELO
NetworkType.ETHEREUM -> NetworkTypeDTO.ETHEREUM
NetworkType.ETHEREUM_GOERLI -> NetworkTypeDTO.ETHEREUM_GOERLI
NetworkType.ETHEREUM_HOLESKY -> NetworkTypeDTO.ETHEREUM_HOLESKY
NetworkType.FANTOM -> NetworkTypeDTO.FANTOM
NetworkType.HARMONY -> NetworkTypeDTO.HARMONY
NetworkType.OPTIMISM -> NetworkTypeDTO.OPTIMISM
NetworkType.POLYGON -> NetworkTypeDTO.POLYGON
NetworkType.GNOSIS -> NetworkTypeDTO.GNOSIS
NetworkType.MOONRIVER -> NetworkTypeDTO.MOONRIVER
NetworkType.OKC -> NetworkTypeDTO.OKC
NetworkType.ZKSYNC -> NetworkTypeDTO.ZKSYNC
NetworkType.VICTION -> NetworkTypeDTO.VICTION
NetworkType.AGORIC -> NetworkTypeDTO.AGORIC
NetworkType.AKASH -> NetworkTypeDTO.AKASH
NetworkType.AXELAR -> NetworkTypeDTO.AXELAR
NetworkType.BAND_PROTOCOL -> NetworkTypeDTO.BAND_PROTOCOL
NetworkType.BITSONG -> NetworkTypeDTO.BITSONG
NetworkType.CANTO -> NetworkTypeDTO.CANTO
NetworkType.CHIHUAHUA -> NetworkTypeDTO.CHIHUAHUA
NetworkType.COMDEX -> NetworkTypeDTO.COMDEX
NetworkType.COREUM -> NetworkTypeDTO.COREUM
NetworkType.COSMOS -> NetworkTypeDTO.COSMOS
NetworkType.CRESCENT -> NetworkTypeDTO.CRESCENT
NetworkType.CRONOS -> NetworkTypeDTO.CRONOS
NetworkType.CUDOS -> NetworkTypeDTO.CUDOS
NetworkType.DESMOS -> NetworkTypeDTO.DESMOS
NetworkType.DYDX -> NetworkTypeDTO.DYDX
NetworkType.EVMOS -> NetworkTypeDTO.EVMOS
NetworkType.FETCH_AI -> NetworkTypeDTO.FETCH_AI
NetworkType.GRAVITY_BRIDGE -> NetworkTypeDTO.GRAVITY_BRIDGE
NetworkType.INJECTIVE -> NetworkTypeDTO.INJECTIVE
NetworkType.IRISNET -> NetworkTypeDTO.IRISNET
NetworkType.JUNO -> NetworkTypeDTO.JUNO
NetworkType.KAVA -> NetworkTypeDTO.KAVA
NetworkType.KI_NETWORK -> NetworkTypeDTO.KI_NETWORK
NetworkType.MARS_PROTOCOL -> NetworkTypeDTO.MARS_PROTOCOL
NetworkType.NYM -> NetworkTypeDTO.NYM
NetworkType.OKEX_CHAIN -> NetworkTypeDTO.OKEX_CHAIN
NetworkType.ONOMY -> NetworkTypeDTO.ONOMY
NetworkType.OSMOSIS -> NetworkTypeDTO.OSMOSIS
NetworkType.PERSISTENCE -> NetworkTypeDTO.PERSISTENCE
NetworkType.QUICKSILVER -> NetworkTypeDTO.QUICKSILVER
NetworkType.REGEN -> NetworkTypeDTO.REGEN
NetworkType.SECRET -> NetworkTypeDTO.SECRET
NetworkType.SENTINEL -> NetworkTypeDTO.SENTINEL
NetworkType.SOMMELIER -> NetworkTypeDTO.SOMMELIER
NetworkType.STAFI -> NetworkTypeDTO.STAFI
NetworkType.STARGAZE -> NetworkTypeDTO.STARGAZE
NetworkType.STRIDE -> NetworkTypeDTO.STRIDE
NetworkType.TERITORI -> NetworkTypeDTO.TERITORI
NetworkType.TGRADE -> NetworkTypeDTO.TGRADE
NetworkType.UMEE -> NetworkTypeDTO.UMEE
NetworkType.POLKADOT -> NetworkTypeDTO.POLKADOT
NetworkType.KUSAMA -> NetworkTypeDTO.KUSAMA
NetworkType.WESTEND -> NetworkTypeDTO.WESTEND
NetworkType.BINANCEBEACON -> NetworkTypeDTO.BINANCEBEACON
NetworkType.NEAR -> NetworkTypeDTO.NEAR
NetworkType.SOLANA -> NetworkTypeDTO.SOLANA
NetworkType.TEZOS -> NetworkTypeDTO.TEZOS
NetworkType.TRON -> NetworkTypeDTO.TRON
else -> NetworkTypeDTO.UNKNOWN
}
}
}

View file

@ -2,11 +2,11 @@ package com.tangem.data.staking.converters
import com.tangem.datasource.api.stakekit.models.response.model.TokenDTO
import com.tangem.domain.staking.model.Token
import com.tangem.utils.converter.Converter
import com.tangem.utils.converter.TwoWayConverter
class TokenConverter(
private val stakingNetworkTypeConverter: StakingNetworkTypeConverter,
) : Converter<TokenDTO, Token> {
) : TwoWayConverter<TokenDTO, Token> {
override fun convert(value: TokenDTO): Token {
return Token(
@ -20,4 +20,17 @@ class TokenConverter(
isPoints = value.isPoints,
)
}
override fun convertBack(value: Token): TokenDTO {
return TokenDTO(
name = value.name,
network = stakingNetworkTypeConverter.convertBack(value.network),
symbol = value.symbol,
decimals = value.decimals,
address = value.address,
coinGeckoId = value.coinGeckoId,
logoURI = value.logoURI,
isPoints = value.isPoints,
)
}
}

View file

@ -20,7 +20,10 @@ class YieldConverter(
rewardRate = value.rewardRate,
rewardType = convertRewardType(value.rewardType),
metadata = convertMetadata(value.metadata),
validators = value.validators.map { convertValidator(it) },
validators = value.validators
.filter { it.preferred }
.map { convertValidator(it) }
.sortedByDescending { it.apr },
isAvailable = value.isAvailable,
)
}