Updated on 2026-08-14
This commit is contained in:
parent
a74c3787e7
commit
e49a9befc7
12 changed files with 137 additions and 97 deletions
|
|
@ -583,8 +583,8 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
private fun sendStakingUnsubmittedHashes() {
|
||||
lifecycleScope.launch {
|
||||
sendUnsubmittedHashesUseCase.invoke()
|
||||
.onRight { Timber.d("Submitting hashes succeeded") }
|
||||
.onLeft { Timber.e(it.toString()) }
|
||||
.onRight { Timber.d("Submitting hashes succeeded") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.di.domain
|
|||
import com.tangem.domain.staking.*
|
||||
import com.tangem.domain.staking.repositories.StakingErrorResolver
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -112,11 +113,11 @@ internal object StakingDomainModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideSubmitHashUseCase(
|
||||
stakingRepository: StakingRepository,
|
||||
stakingTransactionHashRepository: StakingTransactionHashRepository,
|
||||
stakingErrorResolver: StakingErrorResolver,
|
||||
): SubmitHashUseCase {
|
||||
return SubmitHashUseCase(
|
||||
stakingRepository = stakingRepository,
|
||||
stakingTransactionHashRepository = stakingTransactionHashRepository,
|
||||
stakingErrorResolver = stakingErrorResolver,
|
||||
)
|
||||
}
|
||||
|
|
@ -124,11 +125,11 @@ internal object StakingDomainModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideSaveUnsubmittedHashUseCase(
|
||||
stakingRepository: StakingRepository,
|
||||
stakingTransactionHashRepository: StakingTransactionHashRepository,
|
||||
stakingErrorResolver: StakingErrorResolver,
|
||||
): SaveUnsubmittedHashUseCase {
|
||||
return SaveUnsubmittedHashUseCase(
|
||||
stakingRepository = stakingRepository,
|
||||
stakingTransactionHashRepository = stakingTransactionHashRepository,
|
||||
stakingErrorResolver = stakingErrorResolver,
|
||||
)
|
||||
}
|
||||
|
|
@ -136,11 +137,11 @@ internal object StakingDomainModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideSendUnsubmittedHashesUseCase(
|
||||
stakingRepository: StakingRepository,
|
||||
stakingTransactionHashRepository: StakingTransactionHashRepository,
|
||||
stakingErrorResolver: StakingErrorResolver,
|
||||
): SendUnsubmittedHashesUseCase {
|
||||
return SendUnsubmittedHashesUseCase(
|
||||
stakingRepository = stakingRepository,
|
||||
stakingTransactionHashRepository = stakingTransactionHashRepository,
|
||||
stakingErrorResolver = stakingErrorResolver,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ dependencies {
|
|||
implementation(deps.kotlin.immutable.collections)
|
||||
implementation(deps.moshi)
|
||||
implementation(deps.moshi.kotlin)
|
||||
implementation(deps.timber)
|
||||
|
||||
implementation(projects.libs.blockchainSdk)
|
||||
implementation(projects.libs.crypto)
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@ import com.tangem.datasource.api.stakekit.StakeKitApi
|
|||
import com.tangem.datasource.api.stakekit.models.request.*
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.transaction.tron.TronStakeKitTransaction
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.datasource.local.preferences.utils.getObjectListSync
|
||||
import com.tangem.datasource.local.token.StakingBalanceStore
|
||||
import com.tangem.datasource.local.token.StakingYieldsStore
|
||||
import com.tangem.domain.core.lce.LceFlow
|
||||
|
|
@ -36,7 +33,10 @@ import com.tangem.domain.core.lce.lceFlow
|
|||
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.UnsubmittedTransactionMetadata
|
||||
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
|
||||
|
|
@ -54,7 +54,6 @@ import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
|
|||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import com.tangem.lib.crypto.BlockchainUtils.isSolana
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -62,7 +61,6 @@ import kotlinx.coroutines.withContext
|
|||
@Suppress("LargeClass", "LongParameterList", "TooManyFunctions")
|
||||
internal class DefaultStakingRepository(
|
||||
private val stakeKitApi: StakeKitApi,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val stakingYieldsStore: StakingYieldsStore,
|
||||
private val stakingBalanceStore: StakingBalanceStore,
|
||||
private val cacheRegistry: CacheRegistry,
|
||||
|
|
@ -464,55 +462,6 @@ internal class DefaultStakingRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun submitHash(transactionId: String, transactionHash: String) {
|
||||
withContext(dispatchers.io) {
|
||||
stakeKitApi.submitTransactionHash(
|
||||
transactionId = transactionId,
|
||||
body = SubmitTransactionHashRequestBody(
|
||||
hash = transactionHash,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun storeUnsubmittedHash(unsubmittedTransactionMetadata: UnsubmittedTransactionMetadata) {
|
||||
withContext(dispatchers.io) {
|
||||
appPreferencesStore.editData { preferences ->
|
||||
val savedTransactions = preferences.getObjectListOrDefault<UnsubmittedTransactionMetadata>(
|
||||
key = PreferencesKeys.UNSUBMITTED_TRANSACTIONS_KEY,
|
||||
default = emptyList(),
|
||||
)
|
||||
|
||||
preferences.setObjectList(
|
||||
key = PreferencesKeys.UNSUBMITTED_TRANSACTIONS_KEY,
|
||||
value = savedTransactions + unsubmittedTransactionMetadata,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun sendUnsubmittedHashes() {
|
||||
withContext(NonCancellable) {
|
||||
val savedTransactions = appPreferencesStore.getObjectListSync<UnsubmittedTransactionMetadata>(
|
||||
key = PreferencesKeys.UNSUBMITTED_TRANSACTIONS_KEY,
|
||||
)
|
||||
|
||||
savedTransactions.forEach {
|
||||
stakeKitApi.submitTransactionHash(
|
||||
transactionId = it.transactionId,
|
||||
body = SubmitTransactionHashRequestBody(hash = it.transactionHash),
|
||||
)
|
||||
}
|
||||
|
||||
appPreferencesStore.editData { mutablePreferences ->
|
||||
mutablePreferences.setObjectList<UnsubmittedTransactionMetadata>(
|
||||
key = PreferencesKeys.UNSUBMITTED_TRANSACTIONS_KEY,
|
||||
value = emptyList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun isAnyTokenStaked(userWalletId: UserWalletId): Boolean {
|
||||
return withContext(dispatchers.io) {
|
||||
stakingBalanceStore.getSyncOrNull(userWalletId)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
package com.tangem.data.staking
|
||||
|
||||
import com.tangem.datasource.api.stakekit.StakeKitApi
|
||||
import com.tangem.datasource.api.stakekit.models.request.*
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.datasource.local.preferences.utils.getObjectListSync
|
||||
import com.tangem.domain.staking.model.UnsubmittedTransactionMetadata
|
||||
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
|
||||
internal class DefaultStakingTransactionHashRepository(
|
||||
private val stakeKitApi: StakeKitApi,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : StakingTransactionHashRepository {
|
||||
|
||||
override suspend fun submitHash(transactionId: String, transactionHash: String) {
|
||||
withContext(dispatchers.io) {
|
||||
stakeKitApi.submitTransactionHash(
|
||||
transactionId = transactionId,
|
||||
body = SubmitTransactionHashRequestBody(
|
||||
hash = transactionHash,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun storeUnsubmittedHash(unsubmittedTransactionMetadata: UnsubmittedTransactionMetadata) {
|
||||
withContext(dispatchers.io) {
|
||||
appPreferencesStore.editData { preferences ->
|
||||
val savedTransactions = preferences.getObjectListOrDefault<UnsubmittedTransactionMetadata>(
|
||||
key = PreferencesKeys.UNSUBMITTED_TRANSACTIONS_KEY,
|
||||
default = emptyList(),
|
||||
)
|
||||
|
||||
preferences.setObjectList(
|
||||
key = PreferencesKeys.UNSUBMITTED_TRANSACTIONS_KEY,
|
||||
value = savedTransactions + unsubmittedTransactionMetadata,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun sendUnsubmittedHashes() {
|
||||
withContext(dispatchers.io) {
|
||||
val savedTransactions = appPreferencesStore.getObjectListSync<UnsubmittedTransactionMetadata>(
|
||||
key = PreferencesKeys.UNSUBMITTED_TRANSACTIONS_KEY,
|
||||
)
|
||||
|
||||
savedTransactions.forEach { transaction ->
|
||||
try {
|
||||
stakeKitApi.submitTransactionHash(
|
||||
transactionId = transaction.transactionId,
|
||||
body = SubmitTransactionHashRequestBody(hash = transaction.transactionHash),
|
||||
)
|
||||
|
||||
appPreferencesStore.editData { mutablePreferences ->
|
||||
val updatedTransactions =
|
||||
mutablePreferences.getObjectListOrDefault<UnsubmittedTransactionMetadata>(
|
||||
key = PreferencesKeys.UNSUBMITTED_TRANSACTIONS_KEY,
|
||||
default = emptyList(),
|
||||
).filterNot { it.transactionId == transaction.transactionId }
|
||||
|
||||
mutablePreferences.setObjectList(
|
||||
key = PreferencesKeys.UNSUBMITTED_TRANSACTIONS_KEY,
|
||||
value = updatedTransactions,
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
val logMessage = buildString {
|
||||
append("Error while submitting transaction with\n")
|
||||
append("StakeKit id = ${transaction.transactionId} and\n")
|
||||
append("transaction hash = ${transaction.transactionHash}")
|
||||
}
|
||||
Timber.e(logMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.squareup.moshi.Moshi
|
|||
import com.tangem.data.common.cache.CacheRegistry
|
||||
import com.tangem.data.staking.DefaultStakingErrorResolver
|
||||
import com.tangem.data.staking.DefaultStakingRepository
|
||||
import com.tangem.data.staking.DefaultStakingTransactionHashRepository
|
||||
import com.tangem.data.staking.converters.error.StakeKitErrorConverter
|
||||
import com.tangem.datasource.api.stakekit.StakeKitApi
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.error.StakeKitErrorResponse
|
||||
|
|
@ -13,6 +14,7 @@ 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.StakingRepository
|
||||
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
|
||||
|
|
@ -31,23 +33,21 @@ internal object StakingDataModule {
|
|||
@Singleton
|
||||
fun provideStakingRepository(
|
||||
stakeKitApi: StakeKitApi,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
stakingTokenStore: StakingYieldsStore,
|
||||
stakingYieldsStore: StakingYieldsStore,
|
||||
stakingBalanceStore: StakingBalanceStore,
|
||||
cacheRegistry: CacheRegistry,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
stakingFeatureToggle: StakingFeatureToggles,
|
||||
cacheRegistry: CacheRegistry,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
getUserWalletUseCase: GetUserWalletUseCase,
|
||||
@NetworkMoshi moshi: Moshi,
|
||||
): StakingRepository {
|
||||
return DefaultStakingRepository(
|
||||
stakeKitApi = stakeKitApi,
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
stakingYieldsStore = stakingTokenStore,
|
||||
stakingYieldsStore = stakingYieldsStore,
|
||||
stakingBalanceStore = stakingBalanceStore,
|
||||
dispatchers = dispatchers,
|
||||
cacheRegistry = cacheRegistry,
|
||||
dispatchers = dispatchers,
|
||||
stakingFeatureToggle = stakingFeatureToggle,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
getUserWalletUseCase = getUserWalletUseCase,
|
||||
|
|
@ -55,6 +55,20 @@ internal object StakingDataModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun StakingTransactionHashRepository(
|
||||
stakeKitApi: StakeKitApi,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): StakingTransactionHashRepository {
|
||||
return DefaultStakingTransactionHashRepository(
|
||||
stakeKitApi = stakeKitApi,
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
internal fun provideStakingErrorResolver(@NetworkMoshi moshi: Moshi): StakingErrorResolver {
|
||||
|
|
|
|||
|
|
@ -4,19 +4,19 @@ import arrow.core.Either
|
|||
import com.tangem.domain.staking.model.stakekit.StakingError
|
||||
import com.tangem.domain.staking.model.UnsubmittedTransactionMetadata
|
||||
import com.tangem.domain.staking.repositories.StakingErrorResolver
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
|
||||
|
||||
/**
|
||||
* Use case for saving hash that failed to submit during staking confirmation
|
||||
*/
|
||||
class SaveUnsubmittedHashUseCase(
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val stakingTransactionHashRepository: StakingTransactionHashRepository,
|
||||
private val stakingErrorResolver: StakingErrorResolver,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(transactionId: String, transactionHash: String): Either<StakingError, Unit> {
|
||||
return Either.catch {
|
||||
stakingRepository.storeUnsubmittedHash(
|
||||
stakingTransactionHashRepository.storeUnsubmittedHash(
|
||||
unsubmittedTransactionMetadata = UnsubmittedTransactionMetadata(
|
||||
transactionId = transactionId,
|
||||
transactionHash = transactionHash,
|
||||
|
|
|
|||
|
|
@ -3,19 +3,19 @@ package com.tangem.domain.staking
|
|||
import arrow.core.Either
|
||||
import com.tangem.domain.staking.model.stakekit.StakingError
|
||||
import com.tangem.domain.staking.repositories.StakingErrorResolver
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
|
||||
|
||||
/**
|
||||
* Use case for commiting hashes that failed to submit during staking confirmation
|
||||
*/
|
||||
class SendUnsubmittedHashesUseCase(
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val stakingTransactionHashRepository: StakingTransactionHashRepository,
|
||||
private val stakingErrorResolver: StakingErrorResolver,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(): Either<StakingError, Unit> {
|
||||
return Either
|
||||
.catch { stakingRepository.sendUnsubmittedHashes() }
|
||||
.catch { stakingTransactionHashRepository.sendUnsubmittedHashes() }
|
||||
.mapLeft { stakingErrorResolver.resolve(it) }
|
||||
}
|
||||
}
|
||||
|
|
@ -3,20 +3,20 @@ package com.tangem.domain.staking
|
|||
import arrow.core.Either
|
||||
import com.tangem.domain.staking.model.stakekit.StakingError
|
||||
import com.tangem.domain.staking.repositories.StakingErrorResolver
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
|
||||
|
||||
/**
|
||||
* Use case for submitting transaction hash to stakekit
|
||||
*/
|
||||
class SubmitHashUseCase(
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val stakingTransactionHashRepository: StakingTransactionHashRepository,
|
||||
private val stakingErrorResolver: StakingErrorResolver,
|
||||
) {
|
||||
|
||||
suspend fun submitHash(transactionId: String, transactionHash: String): Either<StakingError, Unit> {
|
||||
return Either
|
||||
.catch {
|
||||
stakingRepository.submitHash(
|
||||
stakingTransactionHashRepository.submitHash(
|
||||
transactionId = transactionId,
|
||||
transactionHash = transactionHash,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.domain.core.lce.LceFlow
|
|||
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.UnsubmittedTransactionMetadata
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||
import com.tangem.domain.staking.model.stakekit.YieldBalanceList
|
||||
|
|
@ -75,12 +74,6 @@ interface StakingRepository {
|
|||
transactionId: String,
|
||||
): Pair<StakingTransaction, TransactionData.Compiled>
|
||||
|
||||
suspend fun submitHash(transactionId: String, transactionHash: String)
|
||||
|
||||
suspend fun storeUnsubmittedHash(unsubmittedTransactionMetadata: UnsubmittedTransactionMetadata)
|
||||
|
||||
suspend fun sendUnsubmittedHashes()
|
||||
|
||||
/** Returns staking approval */
|
||||
fun getStakingApproval(cryptoCurrency: CryptoCurrency): StakingApproval
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.domain.staking.repositories
|
||||
|
||||
import com.tangem.domain.staking.model.UnsubmittedTransactionMetadata
|
||||
|
||||
interface StakingTransactionHashRepository {
|
||||
|
||||
suspend fun submitHash(transactionId: String, transactionHash: String)
|
||||
|
||||
suspend fun storeUnsubmittedHash(unsubmittedTransactionMetadata: UnsubmittedTransactionMetadata)
|
||||
|
||||
suspend fun sendUnsubmittedHashes()
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ import com.tangem.domain.core.lce.lceFlow
|
|||
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.UnsubmittedTransactionMetadata
|
||||
import com.tangem.domain.staking.model.stakekit.*
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingAction
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionStatus
|
||||
|
|
@ -239,18 +238,6 @@ class MockStakingRepository : StakingRepository {
|
|||
status = TransactionStatus.Unconfirmed,
|
||||
)
|
||||
|
||||
override suspend fun submitHash(transactionId: String, transactionHash: String) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
override suspend fun storeUnsubmittedHash(unsubmittedTransactionMetadata: UnsubmittedTransactionMetadata) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
override suspend fun sendUnsubmittedHashes() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
override fun getStakingApproval(cryptoCurrency: CryptoCurrency): StakingApproval = StakingApproval.Empty
|
||||
|
||||
override suspend fun isAnyTokenStaked(userWalletId: UserWalletId): Boolean = false
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue