Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-20 21:54:46 +04:00
parent 8b75e37e30
commit a9bca131c3
386 changed files with 1369 additions and 1347 deletions

View file

@ -55,7 +55,6 @@ dependencies {
implementation(deps.kotlin.immutable.collections)
implementation(deps.moshi)
implementation(deps.moshi.kotlin)
implementation(deps.timber)
implementation(deps.firebase.crashlytics)
ksp(deps.moshi.kotlin.codegen)
kaptForObfuscatingVariants(deps.retrofit.response.type.keeper)

View file

@ -5,11 +5,7 @@ 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.P2PEthPoolBroadcastResultConverter
import com.tangem.data.staking.converters.ethpool.P2PEthPoolErrorConverter
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.data.staking.converters.ethpool.*
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.ethpool.P2PEthPoolApi
import com.tangem.datasource.api.ethpool.models.request.P2PEthPoolBroadcastRequest
@ -28,11 +24,11 @@ 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 com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import timber.log.Timber
/**
* P2PEthPool staking repository implementation
@ -71,7 +67,7 @@ internal class DefaultP2PEthPoolRepository(
override suspend fun fetchVaults(network: P2PEthPoolNetwork) {
val vaults = if (stakingFeatureToggles.isEthStakingEnabled) {
getVaults(network).getOrElse { error ->
Timber.e("Error fetching P2PEthPool vaults: $error")
TangemLogger.e("Error fetching P2PEthPool vaults: $error")
emptyList()
}
} else {

View file

@ -47,13 +47,13 @@ import com.tangem.domain.staking.model.stakekit.transaction.StakingTransaction
import com.tangem.domain.staking.repositories.StakeKitRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import timber.log.Timber
@Suppress("LargeClass", "LongParameterList", "TooManyFunctions")
internal class DefaultStakeKitRepository(
@ -91,7 +91,7 @@ internal class DefaultStakeKitRepository(
when (response) {
is ApiResponse.Success -> response.data.data.filter { yield -> yield.isAvailable == true }
is ApiResponse.Error -> {
Timber.e("Error fetching enabled yields: ${response.cause}")
TangemLogger.e("Error fetching enabled yields: ${response.cause}")
emptyList()
}
}
@ -142,7 +142,7 @@ internal class DefaultStakeKitRepository(
network = networkTypeString,
status = actionStatusString,
).getOrThrow().data,
onError = { Timber.e("Error converting staking actions list: $it") },
onError = { TangemLogger.e("Error converting staking actions list: $it") },
)
}
}
@ -348,7 +348,7 @@ internal class DefaultStakeKitRepository(
private suspend fun getEnabledYieldsSync(): List<Yield> {
return YieldConverter.convertListIgnoreErrors(
input = stakingYieldsStore.getSync(),
onError = { Timber.e("Error converting one of the items in enabled yields: $it") },
onError = { TangemLogger.e("Error converting one of the items in enabled yields: $it") },
)
}
@ -356,7 +356,7 @@ internal class DefaultStakeKitRepository(
return stakingYieldsStore.get().map { yields ->
YieldConverter.convertListIgnoreErrors(
input = yields,
onError = { Timber.e("Error converting one of the items in enabled yields: $it") },
onError = { TangemLogger.e("Error converting one of the items in enabled yields: $it") },
)
}
}

View file

@ -1,15 +1,15 @@
package com.tangem.data.staking
import com.tangem.datasource.api.stakekit.StakeKitApi
import com.tangem.datasource.api.stakekit.models.request.*
import com.tangem.datasource.api.stakekit.models.request.SubmitTransactionHashRequestBody
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.StakeKitTransactionHashRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.withContext
import timber.log.Timber
internal class DefaultStakeKitTransactionHashRepository(
private val stakeKitApi: StakeKitApi,
@ -75,7 +75,7 @@ internal class DefaultStakeKitTransactionHashRepository(
append("StakeKit id = ${transaction.transactionId} and\n")
append("transaction hash = ${transaction.transactionHash}")
}
Timber.e(logMessage)
TangemLogger.e(logMessage)
}
}
}

View file

@ -30,11 +30,11 @@ import com.tangem.domain.staking.model.ethpool.P2PEthPoolVault
import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.runSuspendCatching
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
/**
@ -66,10 +66,10 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
) : MultiStakingBalanceFetcher {
override suspend fun invoke(params: MultiStakingBalanceFetcher.Params): Either<Throwable, Unit> {
Timber.i("Start fetching staking balances for params:\n$params")
TangemLogger.i("Start fetching staking balances for params:\n$params")
val stakingIds = params.stakingIds.ifEmpty {
Timber.i("Nothing to fetch, empty stakingIds for ${params.userWalletId}")
TangemLogger.i("Nothing to fetch, empty stakingIds for ${params.userWalletId}")
return Unit.right()
}
@ -84,7 +84,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
stakingIntegrationID is StakingIntegrationID.StakeKit
}
Timber.i(
TangemLogger.i(
"""
Staking IDs to fetch:
- StakeKit: ${stakeKitIds.joinToString()}
@ -104,7 +104,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
}
}
.onLeft { throwable ->
Timber.e(throwable, "Unable to fetch staking balances $params")
TangemLogger.e("Unable to fetch staking balances $params", throwable)
if (stakeKitIds.isNotEmpty()) {
stakeKitBalancesStore.storeError(
@ -137,7 +137,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
val vaults = runSuspendCatching { p2pEthPoolVaultsStore.getSync() }.getOrNull().orEmpty()
if (vaults.isEmpty()) {
Timber.w("No P2PEthPool vaults available for $userWalletId, storing empty balances")
TangemLogger.w("No P2PEthPool vaults available for $userWalletId, storing empty balances")
p2PEthPoolBalancesStore.storeEmpty(userWalletId = userWalletId, stakingIds = stakingIds)
return
}
@ -155,7 +155,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
val addresses = stakingIds.map { it.address }.toSet()
val responses = fetchP2PAccountResponses(vaults = vaults, addresses = addresses)
Timber.i("Successfully fetched ${responses.size} P2PEthPool balances for $userWalletId")
TangemLogger.i("Successfully fetched ${responses.size} P2PEthPool balances for $userWalletId")
if (responses.isNotEmpty()) {
p2PEthPoolBalancesStore.storeActual(userWalletId = userWalletId, values = responses)
@ -167,19 +167,22 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
}
if (missingStakingIds.isNotEmpty()) {
Timber.i("Missing responses for ${missingStakingIds.size} staking IDs: $missingStakingIds")
TangemLogger.i(
"Missing responses for ${missingStakingIds.size} staking IDs:" +
" $missingStakingIds",
)
p2PEthPoolBalancesStore.storeError(
userWalletId = userWalletId,
stakingIds = missingStakingIds.toSet(),
)
}
} else {
Timber.i("No P2PEthPool responses received for $userWalletId")
TangemLogger.i("No P2PEthPool responses received for $userWalletId")
p2PEthPoolBalancesStore.storeError(userWalletId = userWalletId, stakingIds = stakingIds)
}
},
onError = { throwable ->
Timber.e(throwable, "Unable to fetch P2PEthPool balances $userWalletId")
TangemLogger.e("Unable to fetch P2PEthPool balances $userWalletId", throwable)
p2PEthPoolBalancesStore.storeError(userWalletId = userWalletId, stakingIds = stakingIds)
@ -207,7 +210,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
is ApiResponse.Success -> {
val data = response.data
if (data.error != null) {
Timber.w(
TangemLogger.w(
"P2PEthPool API returned error for vault ${vault.vaultAddress}, " +
"address $address: ${data.error ?: "error"}",
)
@ -219,17 +222,17 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
}
}
is ApiResponse.Error -> {
Timber.w(
response.cause,
TangemLogger.w(
"Failed to fetch P2PEthPool balance for vault ${vault.vaultAddress}, " +
"address $address",
response.cause,
)
}
}
}.onFailure { error ->
Timber.w(
error,
TangemLogger.w(
"Failed to fetch P2PEthPool balance for vault ${vault.vaultAddress}, address $address",
error,
)
}
}
@ -245,7 +248,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
if (!isSupportedByWallet) {
val exception = IllegalStateException("Wallet $userWalletId is not supported: $maybeUserWallet")
Timber.e(exception)
TangemLogger.e("Error", exception)
ifNotSupported(exception)
}
@ -263,7 +266,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
val availableStakingIds = groupedStakingIds[true].orEmpty()
val unavailableStakingIds = groupedStakingIds[false].orEmpty()
Timber.i(
TangemLogger.i(
"""
Available staking IDs: ${availableStakingIds.joinToString()}
Unavailable staking IDs: ${unavailableStakingIds.joinToString()}
@ -282,7 +285,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
stakingIds: ${stakingIds.joinToString()}
""".trimIndent(),
)
Timber.i(exception)
TangemLogger.i(exception.toString())
throw exception
}
}
@ -293,7 +296,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
if (yieldsIds.isEmpty()) {
val exception = IllegalStateException("No enabled yields for $userWalletId")
Timber.e(exception)
TangemLogger.e("Error", exception)
throw exception
}
@ -320,7 +323,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
.toSet()
}
Timber.i(
TangemLogger.i(
"Successfully fetched staking balances for $userWalletId:\n${yieldBalances.joinToString("\n")}",
)
stakeKitBalancesStore.storeActual(userWalletId = userWalletId, values = yieldBalances)
@ -337,7 +340,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor(
}
},
onError = { throwable ->
Timber.e(throwable, "Unable to fetch staking balances $userWalletId")
TangemLogger.e("Unable to fetch staking balances $userWalletId", throwable)
stakeKitBalancesStore.storeError(userWalletId = userWalletId, stakingIds = stakingIds)

View file

@ -10,13 +10,13 @@ import com.tangem.domain.staking.multi.MultiStakingBalanceSupplier
import com.tangem.domain.staking.single.SingleStakingBalanceProducer
import com.tangem.domain.staking.single.SingleStakingBalanceProducer.Companion.selectStakingBalance
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import timber.log.Timber
/**
* Default implementation of [SingleStakingBalanceProducer]
@ -39,7 +39,7 @@ internal class DefaultSingleStakingBalanceProducer @AssistedInject constructor(
override val fallback: Option<StakingBalance> = StakingBalance.Error(stakingId = params.stakingId).some()
override fun produce(): Flow<StakingBalance> {
Timber.i("Producing staking balance for params:\n$params")
TangemLogger.i("Producing staking balance for params:\n$params")
return multiStakingBalanceSupplier(
params = MultiStakingBalanceProducer.Params(userWalletId = params.userWalletId),

View file

@ -9,10 +9,10 @@ import com.tangem.domain.staking.StakingIdFactory
import com.tangem.domain.staking.utils.StakingCleaner
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.runSuspendCatching
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.withContext
import timber.log.Timber
/**
* Default implementation of [StakingCleaner].
@ -32,7 +32,7 @@ internal class DefaultStakingCleaner(
override suspend fun invoke(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
if (currencies.isEmpty()) {
Timber.d("No currencies to clear for wallet: $userWalletId")
TangemLogger.d("No currencies to clear for wallet: $userWalletId")
return
}
@ -41,7 +41,7 @@ internal class DefaultStakingCleaner(
}
if (stakingIds.isEmpty()) {
Timber.d("All currencies have no stakingIds to clear for wallet: $userWalletId")
TangemLogger.d("All currencies have no stakingIds to clear for wallet: $userWalletId")
return
}
@ -50,7 +50,7 @@ internal class DefaultStakingCleaner(
override suspend fun invoke(userWalletId: UserWalletId, stakingIds: Set<StakingID>) {
if (stakingIds.isEmpty()) {
Timber.d("No stakingIds to clear for wallet: $userWalletId")
TangemLogger.d("No stakingIds to clear for wallet: $userWalletId")
return
}
@ -66,13 +66,13 @@ internal class DefaultStakingCleaner(
runSuspendCatching {
stakeKitBalancesStore.clear(userWalletId, stakingIds)
}
.onFailure { Timber.e(it, "Failed to clear StakeKit balance statuses for wallet: $userWalletId") }
.onFailure { TangemLogger.e("Failed to clear StakeKit balance statuses for wallet: $userWalletId", it) }
}
private suspend fun clearP2PEthPoolBalancesStore(userWalletId: UserWalletId, stakingIds: Set<StakingID>) {
runSuspendCatching {
p2pEthPoolBalancesStore.clear(userWalletId, stakingIds)
}
.onFailure { Timber.e(it, "Failed to clear P2PEthPool balance statuses for wallet: $userWalletId") }
.onFailure { TangemLogger.e("Failed to clear P2PEthPool balance statuses for wallet: $userWalletId", it) }
}
}