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( override suspend fun saveTokenProtocolStatus(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency, cryptoCurrency: CryptoCurrency,
yieldSupplyEnterStatus: YieldSupplyEnterStatus, yieldSupplyEnterStatus: YieldSupplyEnterStatus,
) { ) {
statusMap[cryptoCurrency.id.value] = yieldSupplyEnterStatus statusMap["${userWalletId}_${cryptoCurrency.id.value}"] = yieldSupplyEnterStatus
} }
override fun getTokenProtocolStatus(cryptoCurrency: CryptoCurrency): YieldSupplyEnterStatus? { override fun getTokenProtocolStatus(
return statusMap[cryptoCurrency.id.value] userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
): YieldSupplyEnterStatus? {
return statusMap["${userWalletId}_${cryptoCurrency.id.value}"]
} }
private fun List<YieldMarketToken>.enrichNetworkIds(): List<YieldMarketToken> { private fun List<YieldMarketToken>.enrichNetworkIds(): List<YieldMarketToken> {

View file

@ -59,25 +59,32 @@ interface YieldSupplyRepository {
suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean 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 * 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 * 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 cryptoCurrency the currency or token the action relates to
* @param yieldSupplyEnterStatus the last action intent: [YieldSupplyEnterStatus.Enter] or [YieldSupplyEnterStatus.Exit] * @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 * 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 * @param cryptoCurrency the currency or token to query
* @return the last action intent or null if nothing has been recorded * @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") @Suppress("MaximumLineLength")
private fun onCryptoCurrencyStatusUpdated(cryptoCurrencyStatus: CryptoCurrencyStatus) { private fun onCryptoCurrencyStatusUpdated(cryptoCurrencyStatus: CryptoCurrencyStatus) {
val yieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus val yieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus
val tokenProtocolStatus = yieldSupplyRepository.getTokenProtocolStatus(cryptoCurrency) val tokenProtocolStatus = yieldSupplyRepository.getTokenProtocolStatus(
userWallet.walletId,
cryptoCurrency,
)
val isActive = yieldSupplyStatus?.isActive == true val isActive = yieldSupplyStatus?.isActive == true
val isCryptoCurrencyStatusFromCache = cryptoCurrencyStatus.value.sources.networkSource != StatusSource.ACTUAL val isCryptoCurrencyStatusFromCache = cryptoCurrencyStatus.value.sources.networkSource != StatusSource.ACTUAL
val processing = uiState.value is YieldSupplyUM.Processing val processing = uiState.value is YieldSupplyUM.Processing

View file

@ -244,38 +244,48 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
) )
}, },
ifRight = { ifRight = {
yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Enter) onStartEarningTransactionSuccess(yieldSupplyFeeUM)
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 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() { private fun subscribeOnCurrencyStatusUpdates() {
modelScope.launch { modelScope.launch {
getUserWalletUseCase(params.userWalletId).fold( getUserWalletUseCase(params.userWalletId).fold(

View file

@ -165,37 +165,45 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
) )
}, },
ifRight = { ifRight = {
yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Exit) onStopEarningTransactionSuccess()
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 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() { private fun subscribeOnCurrencyStatusUpdates() {
modelScope.launch { modelScope.launch {
feeCryptoCurrencyStatusFlow.update { feeCryptoCurrencyStatusFlow.update {