Updated on 2026-08-14

This commit is contained in:
Tangem 2024-10-25 17:49:53 +03:00
parent dab5fb51b6
commit 967d5520a1
37 changed files with 452 additions and 408 deletions

View file

@ -0,0 +1,30 @@
package com.tangem.data.staking
import com.tangem.datasource.local.token.StakingActionsStore
import com.tangem.domain.staking.model.stakekit.action.StakingAction
import com.tangem.domain.staking.repositories.StakingActionRepository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
internal class DefaultStakingActionRepository(
private val stakingActionsStore: StakingActionsStore,
private val dispatchers: CoroutineDispatcherProvider,
) : StakingActionRepository {
override suspend fun store(
userWalletId: UserWalletId,
cryptoCurrencyId: CryptoCurrency.ID,
actions: List<StakingAction>,
) {
withContext(dispatchers.io) {
stakingActionsStore.store(userWalletId, cryptoCurrencyId, actions)
}
}
override fun get(userWalletId: UserWalletId, cryptoCurrencyId: CryptoCurrency.ID): Flow<List<StakingAction>> {
return stakingActionsStore.get(userWalletId, cryptoCurrencyId)
}
}

View file

@ -1,32 +0,0 @@
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 pendingTransactionsMap = ConcurrentHashMap<UserWalletId, CopyOnWriteArrayList<PendingTransaction>>()
override fun saveTransaction(userWalletId: UserWalletId, transaction: PendingTransaction) {
val transactions = pendingTransactionsMap.computeIfAbsent(userWalletId) { CopyOnWriteArrayList() }
transactions.add(transaction)
}
override fun removeTransactions(userWalletId: UserWalletId, transactions: Set<PendingTransaction>) {
pendingTransactionsMap[userWalletId]?.removeAll(transactions)
}
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

@ -25,19 +25,19 @@ import com.tangem.data.staking.converters.transaction.StakingTransactionTypeConv
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.stakekit.StakeKitApi
import com.tangem.datasource.api.stakekit.models.request.*
import com.tangem.datasource.api.stakekit.models.response.model.NetworkTypeDTO
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
import com.tangem.datasource.api.stakekit.models.response.model.action.StakingActionStatusDTO
import com.tangem.datasource.api.stakekit.models.response.model.transaction.tron.TronStakeKitTransaction
import com.tangem.datasource.local.token.StakingBalanceStore
import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.domain.staking.model.StakingApproval
import com.tangem.domain.staking.model.StakingAvailability
import com.tangem.domain.staking.model.StakingEntryInfo
import com.tangem.domain.staking.model.stakekit.NetworkType
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.staking.model.stakekit.YieldBalance
import com.tangem.domain.staking.model.stakekit.YieldBalanceList
import com.tangem.domain.staking.model.stakekit.*
import com.tangem.domain.staking.model.stakekit.action.StakingAction
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.domain.staking.model.stakekit.action.StakingActionStatus
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
import com.tangem.domain.staking.model.stakekit.transaction.ActionParams
import com.tangem.domain.staking.model.stakekit.transaction.StakingGasEstimate
@ -102,6 +102,8 @@ internal class DefaultStakingRepository(
private val yieldBalanceListConverter = YieldBalanceListConverter(yieldBalanceConverter)
private val tronStakeKitTransactionAdapter by lazy { moshi.adapter(TronStakeKitTransaction::class.java) }
private val networkTypeAdapter by lazy { moshi.adapter(NetworkTypeDTO::class.java) }
private val stakingActionStatusAdapter by lazy { moshi.adapter(StakingActionStatusDTO::class.java) }
override fun getIntegrationKey(cryptoCurrencyId: CryptoCurrency.ID): String = with(cryptoCurrencyId) {
rawNetworkId.plus(rawCurrencyId)
@ -140,6 +142,40 @@ internal class DefaultStakingRepository(
}
}
override suspend fun getActions(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
networkType: NetworkType,
stakingActionStatus: StakingActionStatus,
): List<StakingAction> {
return withContext(dispatchers.io) {
val address = walletManagersFacade.getDefaultAddress(userWalletId, cryptoCurrency.network).orEmpty()
val networkTypeDto = networkTypeConverter.convertBack(networkType)
val networkTypeString = networkTypeDto.extractJsonName()
val actionStatusDTO = actionStatusConverter.convertBack(stakingActionStatus)
val actionStatusString = actionStatusDTO.extractJsonName()
enterActionResponseConverter.convertListIgnoreErrors(
input = stakeKitApi.getActions(
walletAddress = address,
network = networkTypeString,
status = actionStatusString,
).getOrThrow().data,
onError = { Timber.e("Error converting staking actions list: $it") },
)
}
}
private fun NetworkTypeDTO.extractJsonName(): String {
return networkTypeAdapter.toJson(this).replace("\"", "")
}
private fun StakingActionStatusDTO.extractJsonName(): String {
return stakingActionStatusAdapter.toJson(this).replace("\"", "")
}
override suspend fun getEntryInfo(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): StakingEntryInfo {
return withContext(dispatchers.io) {
val yield = getYield(cryptoCurrencyId, symbol)

View file

@ -1,23 +0,0 @@
package com.tangem.data.staking
import com.tangem.domain.staking.model.PendingTransaction
import com.tangem.domain.staking.model.stakekit.BalanceItem
import com.tangem.utils.converter.Converter
import org.joda.time.DateTime
internal object PendingTransactionItemConverter : Converter<PendingTransaction, BalanceItem?> {
override fun convert(value: PendingTransaction): BalanceItem? {
return BalanceItem(
groupId = value.groupId ?: return null,
token = value.token,
type = value.type,
amount = value.amount,
rawCurrencyId = value.rawCurrencyId,
validatorAddress = value.validator?.address,
date = DateTime.now(),
pendingActions = emptyList(),
isPending = true,
)
}
}

View file

@ -2,9 +2,10 @@ package com.tangem.data.staking.converters.action
import com.tangem.datasource.api.stakekit.models.response.model.action.StakingActionStatusDTO
import com.tangem.domain.staking.model.stakekit.action.StakingActionStatus
import com.tangem.utils.converter.Converter
import com.tangem.utils.converter.TwoWayConverter
class ActionStatusConverter : TwoWayConverter<StakingActionStatusDTO, StakingActionStatus> {
class ActionStatusConverter : Converter<StakingActionStatusDTO, StakingActionStatus> {
override fun convert(value: StakingActionStatusDTO): StakingActionStatus {
return when (value) {
StakingActionStatusDTO.CANCELED -> StakingActionStatus.CANCELED
@ -16,4 +17,16 @@ class ActionStatusConverter : Converter<StakingActionStatusDTO, StakingActionSta
else -> StakingActionStatus.UNKNOWN
}
}
override fun convertBack(value: StakingActionStatus): StakingActionStatusDTO {
return when (value) {
StakingActionStatus.CANCELED -> StakingActionStatusDTO.CANCELED
StakingActionStatus.CREATED -> StakingActionStatusDTO.CREATED
StakingActionStatus.WAITING_FOR_NEXT -> StakingActionStatusDTO.WAITING_FOR_NEXT
StakingActionStatus.PROCESSING -> StakingActionStatusDTO.PROCESSING
StakingActionStatus.FAILED -> StakingActionStatusDTO.FAILED
StakingActionStatus.SUCCESS -> StakingActionStatusDTO.SUCCESS
else -> StakingActionStatusDTO.UNKNOWN
}
}
}

View file

@ -1,7 +1,7 @@
package com.tangem.data.staking.converters.action
import com.tangem.data.staking.converters.transaction.StakingTransactionConverter
import com.tangem.datasource.api.stakekit.models.response.EnterActionResponse
import com.tangem.datasource.api.stakekit.models.response.ActionDTO
import com.tangem.domain.staking.model.stakekit.action.StakingAction
import com.tangem.utils.converter.Converter
@ -9,9 +9,9 @@ class EnterActionResponseConverter(
private val actionStatusConverter: ActionStatusConverter,
private val stakingActionTypeConverter: StakingActionTypeConverter,
private val transactionConverter: StakingTransactionConverter,
) : Converter<EnterActionResponse, StakingAction> {
) : Converter<ActionDTO, StakingAction> {
override fun convert(value: EnterActionResponse): StakingAction {
override fun convert(value: ActionDTO): StakingAction {
return StakingAction(
id = value.id,
integrationId = value.integrationId,

View file

@ -2,8 +2,8 @@ package com.tangem.data.staking.di
import com.squareup.moshi.Moshi
import com.tangem.data.common.cache.CacheRegistry
import com.tangem.data.staking.*
import com.tangem.data.staking.DefaultStakingErrorResolver
import com.tangem.data.staking.DefaultStakingPendingTransactionRepository
import com.tangem.data.staking.DefaultStakingRepository
import com.tangem.data.staking.DefaultStakingTransactionHashRepository
import com.tangem.data.staking.converters.error.StakeKitErrorConverter
@ -11,12 +11,10 @@ import com.tangem.datasource.api.stakekit.StakeKitApi
import com.tangem.datasource.api.stakekit.models.response.model.error.StakeKitErrorResponse
import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.token.StakingActionsStore
import com.tangem.datasource.local.token.StakingBalanceStore
import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
import com.tangem.domain.staking.repositories.*
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
@ -73,8 +71,14 @@ internal object StakingDataModule {
@Provides
@Singleton
fun provideStakingPendingTransactionRepository(): StakingPendingTransactionRepository {
return DefaultStakingPendingTransactionRepository()
fun provideStakingActionRepository(
stakingActionsStore: StakingActionsStore,
dispatchers: CoroutineDispatcherProvider,
): StakingActionRepository {
return DefaultStakingActionRepository(
stakingActionsStore = stakingActionsStore,
dispatchers = dispatchers,
)
}
@Provides