Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-12 14:18:29 +03:00
commit d44fcb3218
61 changed files with 1333 additions and 232 deletions

View file

@ -24,7 +24,7 @@ internal class SdkTransactionHistoryItemConverter(
SdkTransactionHistoryItem.TransactionStatus.Failed -> TxInfo.TransactionStatus.Failed
SdkTransactionHistoryItem.TransactionStatus.Unconfirmed -> TxInfo.TransactionStatus.Unconfirmed
},
type = typeConverter.convert(value.type),
type = typeConverter.convert(value.type to value.destinationType.toDomain()),
amount = requireNotNull(value.amount.value) { "Transaction amount value must not be null" },
)

View file

@ -1,21 +1,27 @@
package com.tangem.data.walletmanager.utils
import com.tangem.blockchain.transactionhistory.models.TransactionHistoryItem.TransactionType
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyEnterCallData
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyExitCallData
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyInitTokenCallData
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyReactivateTokenCallData
import com.tangem.domain.models.network.TxInfo
import com.tangem.domain.walletmanager.model.SmartContractMethod
import com.tangem.utils.converter.Converter
internal class SdkTransactionTypeConverter(
private val smartContractMethods: Map<String, SmartContractMethod>,
) : Converter<TransactionType, TxInfo.TransactionType> {
) : Converter<Pair<TransactionType, TxInfo.DestinationType>, TxInfo.TransactionType> {
override fun convert(value: TransactionType): TxInfo.TransactionType {
return when (value) {
override fun convert(value: Pair<TransactionType, TxInfo.DestinationType>): TxInfo.TransactionType {
val (type, destination) = value
return when (type) {
is TransactionType.ContractMethod -> {
getTransactionType(methodName = smartContractMethods[value.id]?.name)
getTransactionType(methodName = smartContractMethods[type.id]?.name, type.callData, destination)
}
is TransactionType.ContractMethodName -> {
getTransactionType(methodName = value.name)
getTransactionType(methodName = type.name, type.callData, destination)
}
is TransactionType.Transfer -> {
TxInfo.TransactionType.Transfer
@ -27,7 +33,7 @@ internal class SdkTransactionTypeConverter(
TxInfo.TransactionType.Staking.Unstake
}
is TransactionType.TronStakingTransactionType.VoteWitnessContract -> {
TxInfo.TransactionType.Staking.Vote(value.validatorAddress)
TxInfo.TransactionType.Staking.Vote(type.validatorAddress)
}
is TransactionType.TronStakingTransactionType.WithdrawBalanceContract -> {
TxInfo.TransactionType.Staking.ClaimRewards
@ -38,7 +44,12 @@ internal class SdkTransactionTypeConverter(
}
}
private fun getTransactionType(methodName: String?): TxInfo.TransactionType {
@Suppress("CyclomaticComplexMethod")
private fun getTransactionType(
methodName: String?,
callData: String?,
destination: TxInfo.DestinationType,
): TxInfo.TransactionType {
return when (methodName) {
"transfer" -> TxInfo.TransactionType.Transfer
"approve" -> TxInfo.TransactionType.Approve
@ -59,11 +70,33 @@ internal class SdkTransactionTypeConverter(
"withdrawRewardsPOL",
-> TxInfo.TransactionType.Staking.ClaimRewards
"redelegate" -> TxInfo.TransactionType.Staking.Restake
"supplyEnter" -> TxInfo.TransactionType.YieldSupply.Enter
"supplyExit" -> TxInfo.TransactionType.YieldSupply.Exit
"yieldSend" -> TxInfo.TransactionType.YieldSupply.Send
"enterProtocolByOwner" -> callData?.let { data ->
TxInfo.TransactionType.YieldSupply.Enter(
EthereumYieldSupplyEnterCallData.decode(data)?.tokenContractAddress.orEmpty(),
)
}
"withdrawAndDeactivate" -> callData?.let { data ->
TxInfo.TransactionType.YieldSupply.Exit(
EthereumYieldSupplyExitCallData.decode(data)?.tokenContractAddress.orEmpty(),
)
}
"deployYieldModule" -> TxInfo.TransactionType.YieldSupply.DeployContract(
(destination as? TxInfo.DestinationType.Single)?.addressType?.address.orEmpty(),
)
"initYieldToken" -> callData?.let { data ->
TxInfo.TransactionType.YieldSupply.InitializeToken(
EthereumYieldSupplyInitTokenCallData.decode(data)?.tokenContractAddress.orEmpty(),
)
}
"reactivateToken" -> callData?.let { data ->
TxInfo.TransactionType.YieldSupply.ReactivateToken(
EthereumYieldSupplyReactivateTokenCallData.decode(data)?.tokenContractAddress.orEmpty(),
)
}
"supplyTopUp" -> TxInfo.TransactionType.YieldSupply.Topup
null -> TxInfo.TransactionType.UnknownOperation
else -> TxInfo.TransactionType.Operation(name = methodName.replaceFirstChar { it.titlecase() })
}
} ?: TxInfo.TransactionType.Operation(name = methodName?.replaceFirstChar { it.titlecase() }.orEmpty())
}
}

View file

@ -45,7 +45,7 @@ internal class TransactionDataToTxHistoryItemConverter(
TransactionStatus.Confirmed -> TxInfo.TransactionStatus.Confirmed
TransactionStatus.Unconfirmed -> TxInfo.TransactionStatus.Unconfirmed
},
type = getTransactionType(value.extras),
type = getTransactionType(value),
amount = amount,
)
}
@ -99,16 +99,25 @@ internal class TransactionDataToTxHistoryItemConverter(
)
}
private fun getTransactionType(extras: TransactionExtras?): TxInfo.TransactionType {
return when (extras) {
private fun getTransactionType(transactionData: TransactionData.Uncompiled?): TxInfo.TransactionType {
return when (val extras = transactionData?.extras) {
is EthereumTransactionExtras -> {
when (extras.callData) {
is EthereumYieldSupplyDeployCallData,
is EthereumYieldSupplyReactivateTokenCallData,
is EthereumYieldSupplyInitTokenCallData,
is EthereumYieldSupplyEnterCallData,
-> TxInfo.TransactionType.YieldSupply.Enter
is EthereumYieldSupplyExitCallData -> TxInfo.TransactionType.YieldSupply.Exit
when (val callData = extras.callData) {
is EthereumYieldSupplyDeployCallData -> TxInfo.TransactionType.YieldSupply.DeployContract(
transactionData.destinationAddress,
)
is EthereumYieldSupplyReactivateTokenCallData -> TxInfo.TransactionType.YieldSupply.ReactivateToken(
callData.tokenContractAddress,
)
is EthereumYieldSupplyInitTokenCallData -> TxInfo.TransactionType.YieldSupply.InitializeToken(
callData.tokenContractAddress,
)
is EthereumYieldSupplyEnterCallData -> TxInfo.TransactionType.YieldSupply.Enter(
callData.tokenContractAddress,
)
is EthereumYieldSupplyExitCallData -> TxInfo.TransactionType.YieldSupply.Exit(
callData.tokenContractAddress,
)
is ApprovalERC20TokenCallData -> TxInfo.TransactionType.Approve
else -> TxInfo.TransactionType.Transfer
}

View file

@ -19,6 +19,10 @@ dependencies {
/** Tangem SDKs */
implementation(tangemDeps.blockchain)
// region AndroidX libraries
implementation(deps.androidx.datastore)
// endregion
/** Core */
implementation(projects.core.datasource)
implementation(projects.core.utils)

View file

@ -12,6 +12,10 @@ import com.tangem.data.yield.supply.converters.YieldTokenChartConverter
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.tangemTech.YieldSupplyApi
import com.tangem.datasource.api.tangemTech.models.YieldSupplyChangeTokenStatusBody
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.get
import com.tangem.datasource.local.preferences.utils.store
import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
@ -35,6 +39,7 @@ internal class DefaultYieldSupplyRepository(
private val walletManagersFacade: WalletManagersFacade,
private val dispatchers: CoroutineDispatcherProvider,
private val analyticsExceptionHandler: AnalyticsExceptionHandler,
private val appPreferencesStore: AppPreferencesStore,
) : YieldSupplyRepository {
private val statusMap: MutableMap<String, YieldSupplyEnterStatus> = ConcurrentHashMap()
@ -174,6 +179,14 @@ internal class DefaultYieldSupplyRepository(
null
}
override fun getShouldShowYieldPromoBanner(): Flow<Boolean> {
return appPreferencesStore.get(PreferencesKeys.YIELD_SUPPLY_SHOULD_SHOW_MAIN_PROMO_KEY, true)
}
override suspend fun setShouldShowYieldPromoBanner(shouldShow: Boolean) {
appPreferencesStore.store(PreferencesKeys.YIELD_SUPPLY_SHOULD_SHOW_MAIN_PROMO_KEY, shouldShow)
}
private fun Set<TxInfo>.hasYieldEnterTransactions(yieldAddress: String) = any {
it.type == TxInfo.TransactionType.YieldSupply.Enter ||
it.type == TxInfo.TransactionType.Approve &&

View file

@ -5,6 +5,7 @@ import com.tangem.data.yield.supply.DefaultYieldSupplyRepository
import com.tangem.data.yield.supply.DefaultYieldSupplyErrorResolver
import com.tangem.data.yield.supply.DefaultYieldSupplyTransactionRepository
import com.tangem.datasource.api.tangemTech.YieldSupplyApi
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.yield.supply.YieldSupplyRepository
@ -41,6 +42,7 @@ internal object YieldSupplyDataModule {
walletManagersFacade: WalletManagersFacade,
dispatchers: CoroutineDispatcherProvider,
analyticsExceptionHandler: AnalyticsExceptionHandler,
appPreferencesStore: AppPreferencesStore,
): YieldSupplyRepository {
return DefaultYieldSupplyRepository(
yieldSupplyApi = yieldSupplyApi,
@ -48,6 +50,7 @@ internal object YieldSupplyDataModule {
dispatchers = dispatchers,
walletManagersFacade = walletManagersFacade,
analyticsExceptionHandler = analyticsExceptionHandler,
appPreferencesStore = appPreferencesStore,
)
}