Updated on 2026-08-14

This commit is contained in:
Tangem 2025-11-06 22:10:57 +05:00
parent 540ee066e2
commit 7e5a678d84
5 changed files with 95 additions and 63 deletions

View file

@ -103,14 +103,18 @@ internal class DefaultYieldSupplyRepository(
}
override suspend fun saveTokenProtocolStatus(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
yieldSupplyEnterStatus: YieldSupplyEnterStatus,
) {
statusMap[cryptoCurrency.id.value] = yieldSupplyEnterStatus
statusMap["${userWalletId}_${cryptoCurrency.id.value}"] = yieldSupplyEnterStatus
}
override fun getTokenProtocolStatus(cryptoCurrency: CryptoCurrency): YieldSupplyEnterStatus? {
return statusMap[cryptoCurrency.id.value]
override fun getTokenProtocolStatus(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
): YieldSupplyEnterStatus? {
return statusMap["${userWalletId}_${cryptoCurrency.id.value}"]
}
private fun List<YieldMarketToken>.enrichNetworkIds(): List<YieldMarketToken> {

View file

@ -59,25 +59,32 @@ interface YieldSupplyRepository {
suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean
/**
* Save the last user-initiated yield protocol action for the given currency.
* Save the last userinitiated yield protocol action for the given wallet and currency.
*
* The saved value helps the UI render an intermediate "processing" state while waiting
* for the definitive protocol status to be fetched from the network. This information
* is transient and not intended to be persisted across app restarts.
* is transient (inmemory only) and is not persisted across app restarts.
*
* @param userWalletId the wallet the action was performed with
* @param cryptoCurrency the currency or token the action relates to
* @param yieldSupplyEnterStatus the last action intent: [YieldSupplyEnterStatus.Enter] or [YieldSupplyEnterStatus.Exit]
*/
suspend fun saveTokenProtocolStatus(cryptoCurrency: CryptoCurrency, yieldSupplyEnterStatus: YieldSupplyEnterStatus)
suspend fun saveTokenProtocolStatus(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
yieldSupplyEnterStatus: YieldSupplyEnterStatus,
)
/**
* Get the last saved user-initiated yield protocol action for the given currency, if any.
* Get the last saved userinitiated 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.
* until the protocol status retrieved from backend reflects the change. The value is
* transient (inmemory only) and is not persisted across app restarts.
*
* @param userWalletId the wallet to query
* @param cryptoCurrency the currency or token to query
* @return the last action intent or null if nothing has been recorded
*/
fun getTokenProtocolStatus(cryptoCurrency: CryptoCurrency): YieldSupplyEnterStatus?
fun getTokenProtocolStatus(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): YieldSupplyEnterStatus?
}

View file

@ -185,7 +185,10 @@ internal class YieldSupplyModel @Inject constructor(
@Suppress("MaximumLineLength")
private fun onCryptoCurrencyStatusUpdated(cryptoCurrencyStatus: CryptoCurrencyStatus) {
val yieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus
val tokenProtocolStatus = yieldSupplyRepository.getTokenProtocolStatus(cryptoCurrency)
val tokenProtocolStatus = yieldSupplyRepository.getTokenProtocolStatus(
userWallet.walletId,
cryptoCurrency,
)
val isActive = yieldSupplyStatus?.isActive == true
val isCryptoCurrencyStatusFromCache = cryptoCurrencyStatus.value.sources.networkSource != StatusSource.ACTUAL
val processing = uiState.value is YieldSupplyUM.Processing

View file

@ -244,38 +244,48 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
)
},
ifRight = {
yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Enter)
val event = AnalyticsParam.TxSentFrom.Earning(
blockchain = cryptoCurrency.network.name,
token = cryptoCurrency.symbol,
feeType = AnalyticsParam.FeeType.Normal,
)
analytics.send(YieldSupplyAnalytics.FundsEarned(
blockchain = cryptoCurrency.network.name,
token = cryptoCurrency.symbol,
))
yieldSupplyFeeUM.transactionDataList.forEach {
analytics.send(
Basic.TransactionSent(
sentFrom = event,
memoType = Basic.TransactionSent.MemoType.Null,
),
)
}
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
if (address != null) {
yieldSupplyActivateUseCase(cryptoCurrency, address)
}
modelScope.launch {
params.callback.onTransactionSent()
}
onStartEarningTransactionSuccess(yieldSupplyFeeUM)
},
)
}
}
private suspend fun onStartEarningTransactionSuccess(yieldSupplyFeeUM: YieldSupplyFeeUM.Content) {
yieldSupplyRepository.saveTokenProtocolStatus(
userWallet.walletId,
cryptoCurrency,
YieldSupplyEnterStatus.Enter,
)
val event = AnalyticsParam.TxSentFrom.Earning(
blockchain = cryptoCurrency.network.name,
token = cryptoCurrency.symbol,
feeType = AnalyticsParam.FeeType.Normal,
)
analytics.send(
YieldSupplyAnalytics.FundsEarned(
blockchain = cryptoCurrency.network.name,
token = cryptoCurrency.symbol,
),
)
yieldSupplyFeeUM.transactionDataList.forEach {
analytics.send(
Basic.TransactionSent(
sentFrom = event,
memoType = Basic.TransactionSent.MemoType.Null,
),
)
}
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
if (address != null) {
yieldSupplyActivateUseCase(cryptoCurrency, address)
}
modelScope.launch {
params.callback.onTransactionSent()
}
}
private fun subscribeOnCurrencyStatusUpdates() {
modelScope.launch {
getUserWalletUseCase(params.userWalletId).fold(

View file

@ -165,37 +165,45 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
)
},
ifRight = {
yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Exit)
analytics.send(
YieldSupplyAnalytics.FundsWithdrawn(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
),
)
val event = AnalyticsParam.TxSentFrom.Earning(
blockchain = cryptoCurrency.network.name,
token = cryptoCurrency.symbol,
feeType = AnalyticsParam.FeeType.Normal,
)
analytics.send(
Basic.TransactionSent(
sentFrom = event,
memoType = Basic.TransactionSent.MemoType.Null,
),
)
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
if (address != null) {
yieldSupplyDeactivateUseCase(cryptoCurrency, address)
}
modelScope.launch {
params.callback.onTransactionSent()
}
onStopEarningTransactionSuccess()
},
)
}
}
private suspend fun onStopEarningTransactionSuccess() {
yieldSupplyRepository.saveTokenProtocolStatus(
userWallet.walletId,
cryptoCurrency,
YieldSupplyEnterStatus.Exit,
)
analytics.send(
YieldSupplyAnalytics.FundsWithdrawn(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
),
)
val event = AnalyticsParam.TxSentFrom.Earning(
blockchain = cryptoCurrency.network.name,
token = cryptoCurrency.symbol,
feeType = AnalyticsParam.FeeType.Normal,
)
analytics.send(
Basic.TransactionSent(
sentFrom = event,
memoType = Basic.TransactionSent.MemoType.Null,
),
)
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
if (address != null) {
yieldSupplyDeactivateUseCase(cryptoCurrency, address)
}
modelScope.launch {
params.callback.onTransactionSent()
}
}
private fun subscribeOnCurrencyStatusUpdates() {
modelScope.launch {
feeCryptoCurrencyStatusFlow.update {