Updated on 2026-08-14
This commit is contained in:
parent
c1a7434cbf
commit
0fb5081daf
6 changed files with 133 additions and 32 deletions
|
|
@ -1,10 +1,13 @@
|
|||
package com.tangem.data.walletmanager.utils
|
||||
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.ethereum.tokenmethods.ApprovalERC20TokenCallData
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.yieldsupply.providers.ethereum.factory.EthereumYieldSupplyDeployCallData
|
||||
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.blockchainsdk.models.UpdateWalletManagerResult.Address
|
||||
import com.tangem.domain.models.network.TxInfo
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
|
@ -37,25 +40,12 @@ internal class TransactionDataToTxHistoryItemConverter(
|
|||
addressType = TxInfo.AddressType.User(value.destinationAddress),
|
||||
),
|
||||
sourceType = TxInfo.SourceType.Single(value.sourceAddress),
|
||||
interactionAddressType = TxInfo.InteractionAddressType.User(
|
||||
address = if (isOutgoing) value.destinationAddress else value.sourceAddress,
|
||||
),
|
||||
interactionAddressType = getInteractionAddressType(value, isOutgoing),
|
||||
status = when (value.status) {
|
||||
TransactionStatus.Confirmed -> TxInfo.TransactionStatus.Confirmed
|
||||
TransactionStatus.Unconfirmed -> TxInfo.TransactionStatus.Unconfirmed
|
||||
},
|
||||
type = when (val extras = value.extras) {
|
||||
is EthereumTransactionExtras -> {
|
||||
when (extras.callData) {
|
||||
is EthereumYieldSupplyDeployCallData,
|
||||
is EthereumYieldSupplyEnterCallData,
|
||||
-> TxInfo.TransactionType.YieldSupply.Enter
|
||||
is EthereumYieldSupplyExitCallData -> TxInfo.TransactionType.YieldSupply.Exit
|
||||
else -> TxInfo.TransactionType.Transfer
|
||||
}
|
||||
}
|
||||
else -> TxInfo.TransactionType.Transfer
|
||||
},
|
||||
type = getTransactionType(value.extras),
|
||||
amount = amount,
|
||||
)
|
||||
}
|
||||
|
|
@ -89,4 +79,41 @@ internal class TransactionDataToTxHistoryItemConverter(
|
|||
return amountToken.contractAddress.equals(feeToken.contractAddress, ignoreCase = true) &&
|
||||
amountToken.symbol.equals(feeToken.symbol, ignoreCase = true)
|
||||
}
|
||||
|
||||
private fun getInteractionAddressType(
|
||||
value: TransactionData.Uncompiled,
|
||||
isOutgoing: Boolean,
|
||||
): TxInfo.InteractionAddressType = when (val extras = value.extras) {
|
||||
is EthereumTransactionExtras -> {
|
||||
when (val callData = extras.callData) {
|
||||
is ApprovalERC20TokenCallData -> TxInfo.InteractionAddressType.Contract(
|
||||
address = callData.spenderAddress,
|
||||
)
|
||||
else -> TxInfo.InteractionAddressType.User(
|
||||
address = if (isOutgoing) value.destinationAddress else value.sourceAddress,
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> TxInfo.InteractionAddressType.User(
|
||||
address = if (isOutgoing) value.destinationAddress else value.sourceAddress,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getTransactionType(extras: TransactionExtras?): TxInfo.TransactionType {
|
||||
return when (extras) {
|
||||
is EthereumTransactionExtras -> {
|
||||
when (extras.callData) {
|
||||
is EthereumYieldSupplyDeployCallData,
|
||||
is EthereumYieldSupplyReactivateTokenCallData,
|
||||
is EthereumYieldSupplyInitTokenCallData,
|
||||
is EthereumYieldSupplyEnterCallData,
|
||||
-> TxInfo.TransactionType.YieldSupply.Enter
|
||||
is EthereumYieldSupplyExitCallData -> TxInfo.TransactionType.YieldSupply.Exit
|
||||
is ApprovalERC20TokenCallData -> TxInfo.TransactionType.Approve
|
||||
else -> TxInfo.TransactionType.Transfer
|
||||
}
|
||||
}
|
||||
else -> TxInfo.TransactionType.Transfer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@ dependencies {
|
|||
implementation(projects.domain.yieldSupply.models)
|
||||
implementation(projects.domain.walletManager)
|
||||
implementation(projects.domain.legacy)
|
||||
implementation(projects.domain.txhistory.models)
|
||||
|
||||
implementation(projects.libs.blockchainSdk)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import com.tangem.datasource.api.tangemTech.YieldSupplyApi
|
|||
import com.tangem.datasource.api.tangemTech.models.YieldSupplyChangeTokenStatusBody
|
||||
import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.TxInfo
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.yield.supply.YieldSupplyRepository
|
||||
|
|
@ -109,16 +111,21 @@ internal class DefaultYieldSupplyRepository(
|
|||
override suspend fun saveTokenProtocolStatus(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
yieldSupplyEnterStatus: YieldSupplyEnterStatus,
|
||||
yieldSupplyEnterStatus: YieldSupplyEnterStatus?,
|
||||
) {
|
||||
statusMap["${userWalletId}_${cryptoCurrency.id.value}"] = yieldSupplyEnterStatus
|
||||
val key = getTokenProtocolStatusKey(userWalletId, cryptoCurrency)
|
||||
if (yieldSupplyEnterStatus != null) {
|
||||
statusMap[key] = yieldSupplyEnterStatus
|
||||
} else {
|
||||
statusMap.remove(key)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTokenProtocolStatus(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
): YieldSupplyEnterStatus? {
|
||||
return statusMap["${userWalletId}_${cryptoCurrency.id.value}"]
|
||||
return statusMap[getTokenProtocolStatusKey(userWalletId, cryptoCurrency)]
|
||||
}
|
||||
|
||||
private fun List<YieldMarketToken>.enrichNetworkIds(): List<YieldMarketToken> {
|
||||
|
|
@ -127,4 +134,41 @@ internal class DefaultYieldSupplyRepository(
|
|||
token.copy(backendId = chainIdMap[token.chainId])
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getTokenPendingStatus(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
): YieldSupplyEnterStatus? {
|
||||
val cryptoCurrency = cryptoCurrencyStatus.currency
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
blockchain = cryptoCurrency.network.toBlockchain(),
|
||||
derivationPath = cryptoCurrency.network.derivationPath.value,
|
||||
) ?: error("Wallet manager not found")
|
||||
|
||||
val pendingTxs = cryptoCurrencyStatus.value.pendingTransactions
|
||||
|
||||
val yieldAddress = walletManager.calculateYieldModuleAddress()
|
||||
val hasRecentYieldEnterTxs = pendingTxs.hasYieldEnterTransactions(yieldAddress)
|
||||
val hasRecentYieldExitTxs = pendingTxs.hasYieldExitTransactions()
|
||||
|
||||
return when {
|
||||
hasRecentYieldEnterTxs -> YieldSupplyEnterStatus.Enter
|
||||
hasRecentYieldExitTxs -> YieldSupplyEnterStatus.Exit
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun Set<TxInfo>.hasYieldEnterTransactions(yieldAddress: String) = any {
|
||||
it.type == TxInfo.TransactionType.YieldSupply.Enter ||
|
||||
it.type == TxInfo.TransactionType.Approve &&
|
||||
(it.interactionAddressType as? TxInfo.InteractionAddressType.Contract)?.address == yieldAddress
|
||||
}
|
||||
|
||||
private fun Set<TxInfo>.hasYieldExitTransactions() = any {
|
||||
it.type == TxInfo.TransactionType.YieldSupply.Exit
|
||||
}
|
||||
|
||||
private fun getTokenProtocolStatusKey(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): String =
|
||||
"${userWalletId}_${cryptoCurrency.id.value}"
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.domain.yield.supply
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.yield.supply.models.YieldMarketToken
|
||||
import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus
|
||||
|
|
@ -76,7 +77,7 @@ interface YieldSupplyRepository {
|
|||
suspend fun saveTokenProtocolStatus(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
yieldSupplyEnterStatus: YieldSupplyEnterStatus,
|
||||
yieldSupplyEnterStatus: YieldSupplyEnterStatus?,
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
@ -91,4 +92,20 @@ interface YieldSupplyRepository {
|
|||
* @return the last action intent or null if nothing has been recorded
|
||||
*/
|
||||
fun getTokenProtocolStatus(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): YieldSupplyEnterStatus?
|
||||
|
||||
/**
|
||||
* Get the pending status of the yield protocol action for the given wallet and currency, if any.
|
||||
*
|
||||
* Used to determine whether the UI should display an intermediate "processing" state
|
||||
* until the protocol status retrieved from backend reflects the change. The value is
|
||||
* transient (in‑memory only) and is not persisted across app restarts.
|
||||
*
|
||||
* @param userWalletId the wallet to query
|
||||
* @param cryptoCurrencyStatus the currency status to query
|
||||
* @return the pending action intent or null if nothing has been recorded
|
||||
*/
|
||||
suspend fun getTokenPendingStatus(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
): YieldSupplyEnterStatus?
|
||||
}
|
||||
|
|
@ -35,9 +35,9 @@ import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
|
|||
import com.tangem.features.yield.supply.impl.main.model.transformers.YieldSupplyTokenStatusSuccessTransformer
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.DelayedWork
|
||||
import com.tangem.utils.transformer.update
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveIn
|
||||
import com.tangem.utils.transformer.update
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
|
@ -193,42 +193,54 @@ internal class YieldSupplyModel @Inject constructor(
|
|||
}
|
||||
|
||||
@Suppress("MaximumLineLength")
|
||||
private fun onCryptoCurrencyStatusUpdated(cryptoCurrencyStatus: CryptoCurrencyStatus) {
|
||||
private fun onCryptoCurrencyStatusUpdated(cryptoCurrencyStatus: CryptoCurrencyStatus) = modelScope.launch {
|
||||
val yieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus
|
||||
val tokenProtocolStatus = yieldSupplyRepository.getTokenProtocolStatus(
|
||||
userWallet.walletId,
|
||||
cryptoCurrency,
|
||||
)
|
||||
val tokenPendingStatus = yieldSupplyRepository.getTokenPendingStatus(
|
||||
userWallet.walletId,
|
||||
cryptoCurrencyStatus,
|
||||
)
|
||||
|
||||
val isActive = yieldSupplyStatus?.isActive == true
|
||||
val isCryptoCurrencyStatusFromCache = cryptoCurrencyStatus.value.sources.networkSource != StatusSource.ACTUAL
|
||||
val processing = uiState.value is YieldSupplyUM.Processing
|
||||
Timber.d(
|
||||
"currentUiState ${uiState.value.javaClass} \n" +
|
||||
"yieldSupplyStatus $yieldSupplyStatus" +
|
||||
"YIELD " +
|
||||
"yieldSupplyStatus $yieldSupplyStatus " +
|
||||
"tokenProtocolStatus $tokenProtocolStatus " +
|
||||
"tokenPendingStatus $tokenPendingStatus " +
|
||||
"isActive $isActive " +
|
||||
"processing $processing " +
|
||||
"isCryptoCurrencyStatusFromCache $isCryptoCurrencyStatusFromCache",
|
||||
)
|
||||
if (isCryptoCurrencyStatusFromCache && processing) {
|
||||
return
|
||||
return@launch
|
||||
}
|
||||
|
||||
when {
|
||||
!isActive && tokenProtocolStatus == YieldSupplyEnterStatus.Enter -> {
|
||||
uiState.update { YieldSupplyUM.Processing.Enter }
|
||||
fetchCurrencyWithDelay()
|
||||
}
|
||||
isActive && tokenProtocolStatus == YieldSupplyEnterStatus.Exit -> {
|
||||
uiState.update { YieldSupplyUM.Processing.Exit }
|
||||
tokenProtocolStatus != null && tokenPendingStatus != null -> {
|
||||
uiState.update {
|
||||
when (tokenPendingStatus) {
|
||||
YieldSupplyEnterStatus.Enter -> YieldSupplyUM.Processing.Enter
|
||||
YieldSupplyEnterStatus.Exit -> YieldSupplyUM.Processing.Exit
|
||||
}
|
||||
}
|
||||
fetchCurrencyWithDelay()
|
||||
}
|
||||
else -> {
|
||||
yieldSupplyRepository.saveTokenProtocolStatus(
|
||||
userWalletId = userWallet.walletId,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
yieldSupplyEnterStatus = null,
|
||||
)
|
||||
sendInfoAboutProtocolStatus(cryptoCurrencyStatus)
|
||||
if (isActive) {
|
||||
loadActiveState(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
yieldSupplyStatus = requireNotNull(yieldSupplyStatus),
|
||||
yieldSupplyStatus = yieldSupplyStatus,
|
||||
)
|
||||
} else {
|
||||
loadTokenStatus()
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# https://github.com/tangem/tangem-sdk-android/
|
||||
# https://github.com/tangem/vico
|
||||
|
||||
tangemBlockchainSdk = "releases-5.30-1299"
|
||||
tangemBlockchainSdk = "releases-5.30-1305"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "releases-5.30-567"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue