Updated on 2026-08-14

This commit is contained in:
Tangem 2024-04-25 11:35:55 +02:00
parent 06941914cd
commit 396bc35770
8 changed files with 126 additions and 218 deletions

View file

@ -6,7 +6,6 @@ import com.tangem.domain.tokens.*
import com.tangem.domain.tokens.repository.*
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.feature.swap.domain.api.SwapRepository
import com.tangem.features.send.api.featuretoggles.SendFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
import dagger.Provides
@ -190,7 +189,6 @@ internal object TokensDomainModule {
currenciesRepository: CurrenciesRepository,
quotesRepository: QuotesRepository,
networksRepository: NetworksRepository,
sendFeatureToggles: SendFeatureToggles,
dispatchers: CoroutineDispatcherProvider,
): GetCryptoCurrencyActionsUseCase {
return GetCryptoCurrencyActionsUseCase(
@ -199,7 +197,6 @@ internal object TokensDomainModule {
currenciesRepository = currenciesRepository,
quotesRepository = quotesRepository,
networksRepository = networksRepository,
sendFeatureToggles = sendFeatureToggles,
dispatchers = dispatchers,
)
}

View file

@ -4,16 +4,12 @@
<string name="add_tokens_title">Валюты</string>
<string name="address_qr_code_message_format">Отправляйте только %1$s (%2$s) в сети %3$s на этот адрес. Использование другой сети может привести к утрате средств.</string>
<string name="alert_button_request_support">Обратиться в поддержку</string>
<string name="alert_button_try_again">Попробовать снова</string>
<string name="alert_demo_feature_disabled">Эта функция недоступна в демонстрационном режиме</string>
<string name="alert_failed_to_send_transaction_message">Причина: %s</string>
<string name="alert_failed_to_send_transaction_title">Не могу отправить транзакцию</string>
<string name="alert_manage_tokens_unsupported_blockchain_by_card_message">Выбранный кошелёк не поддерживает сеть %1$s</string>
<string name="alert_manage_tokens_unsupported_curve_message">Для активации криптографии сети %1$s необходимо сбросить кошелек до заводских настроек. Пожалуйста, выведите свои средства, чтобы не потерять их, после сброса доступ к текущему кошельку будет невозможен.</string>
<string name="alert_manage_tokens_unsupported_message">Токены в сети %1$s не поддерживаются этой картой из-за ограничений прошивки.</string>
<string name="alert_negative_app_rate_sent_message">Спасибо за ваш отзыв. Мы ответим в кратчайшие сроки.</string>
<string name="alert_negative_app_rate_sent_title">Ваши предложения отправлены</string>
<string name="alert_troubleshooting_scan_card_message">Пожалуйста, попробуйте приложить карту в точности, как показано на анимации, или запросите поддержку.</string>
<string name="alert_troubleshooting_scan_card_title">У вас возникли трудности со сканированием карты?</string>
<string name="alert_unsupported_card">Эта карта не предназначена для работы с этим приложением</string>
<string name="app_settings_default_fee_footer">Подключите функцию комиссии по умолчанию и при формировании транзакции на отправку средств комиссия будет выставлена автоматически, а экран комиссии пропущен. Вы всегда сможете на него вернуться.</string>
@ -28,8 +24,6 @@
<string name="app_settings_theme_mode_dark">Тёмная</string>
<string name="app_settings_theme_mode_light">Светлая</string>
<string name="app_settings_theme_mode_system">Как в системе</string>
<string name="app_settings_theme_selection_footer">При выборе настройки как в системе приложение будет использовать тему в соответствии с настройками вашего устройства</string>
<string name="app_settings_theme_selection_system_short">Системная</string>
<string name="app_settings_theme_selector_title">Тема</string>
<string name="app_settings_title">Настройки приложения</string>
<string name="balance_hidden_description">Чтобы скрыть или показать баланс, просто поверните ваше устройство вниз или отключите опцию его в разделе \"Настройки\"</string>
@ -81,7 +75,6 @@
<string name="common_create">Создать</string>
<string name="common_delete">Удалить</string>
<string name="common_disabled">Отключено</string>
<string name="common_disconnect">Отключить</string>
<string name="common_done">Готово</string>
<string name="common_enable">Включить</string>
<string name="common_enabled">Включено</string>
@ -114,7 +107,6 @@
<string name="common_reject">Отклонить</string>
<string name="common_reload">Перезагрузить</string>
<string name="common_rename">Переименовать</string>
<string name="common_retry">Повторить</string>
<string name="common_save_changes">Сохранить изменения</string>
<string name="common_search">Искать</string>
<string name="common_search_tokens">Поиск токенов</string>
@ -138,7 +130,6 @@
<string name="common_understand">Я понял</string>
<string name="common_unknown_error">Произошла ошибка. Пожалуйста, попробуйте снова.</string>
<string name="common_unreachable">Недоступно</string>
<string name="common_warning">Предупреждение</string>
<string name="common_yes">Да</string>
<string name="contract_address_copied_message">Адрес контракта скопирован!</string>
<string name="currency_subtitle_expanded">Доступные сети</string>
@ -185,7 +176,6 @@
<string name="details_row_title_flip_to_hide">Скрывать балансы жестом переворота</string>
<string name="details_row_title_issuer">Эмитент</string>
<string name="details_row_title_signed_hashes">Подписано</string>
<string name="details_security_management_warning">Если вы забудете код, то потеряете доступ к своим средствам. Восстановление кода невозможно.</string>
<string name="details_title">Подробности</string>
<string name="disclaimer_error_loading">Проверьте подключение с интернетом или переключитесь на другую сеть</string>
<string name="disclaimer_title">Условия использования</string>
@ -551,12 +541,12 @@
<string name="toast_balances_shown">Балансы показаны</string>
<string name="toast_undo">Отменить</string>
<string name="token_button_unavailability_generic_description">Выбранная операция в данный момент недоступна. Попробуйте позже.</string>
<string name="token_button_unavailability_reason_buy_unavailable">В данный момент покупка монеты %s недоступна. Но мы работаем над её добавлением.</string>
<string name="token_button_unavailability_reason_empty_balance">У вас нет средств для отправки. Пополните счет, чтобы иметь возможность отправить с него средства.</string>
<string name="token_button_unavailability_reason_no_quotes">Выбранная операция в данный момент недоступна. Попробуйте позже.</string>
<string name="token_button_unavailability_reason_not_exchangeable">Обмен %s не доступен. Но мы работаем над его добавлением.</string>
<string name="token_button_unavailability_reason_sell_unavailable">В данный момент продажа монеты %s недоступна. Но мы работаем над её добавлением.</string>
<string name="token_details_choose_address">Выберите адрес</string>
<string name="token_button_unavailability_reason_buy_unavailable">В данный момент покупка монеты %s недоступна. Следите за нашими обновлениями.</string>
<string name="token_button_unavailability_reason_empty_balance_sell">У вас нет средств для продажи. Пополните счет, чтобы иметь возможность продать с него средства.</string>
<string name="token_button_unavailability_reason_empty_balance_send">У вас нет средств для отправки. Пополните счет, чтобы иметь возможность отправить с него средства.</string>
<string name="token_button_unavailability_reason_not_exchangeable">В данный момент обмен монеты %s недоступен. Следите за нашими обновлениями.</string>
<string name="token_button_unavailability_reason_pending_transaction_sell">Продажа средств станет доступной после завершения транзакции %s</string>
<string name="token_button_unavailability_reason_sell_unavailable">В данный момент продажа %s недоступна. Следите за нашими обновлениями.</string>
<string name="token_details_generate_xpub">Сгенерировать XPUB</string>
<string name="token_details_hide_alert_hide">Скрыть</string>
<string name="token_details_hide_alert_message">Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно через страницу управления токенами.</string>
@ -667,9 +657,10 @@
<string name="warning_failed_to_verify_card_message">Возможно, данная карта - образец или подделка</string>
<string name="warning_failed_to_verify_card_title">Ошибка проверки подлинности</string>
<string name="warning_hedera_missing_token_association_button_title">Ассоциировать</string>
<string name="warning_hedera_missing_token_association_message">Этот токен должен быть ассоциирован с вашей учетной записью Hedera, прежде чем вы сможете его принять. Стоимость ассоциации ~%.4f %s</string>
<string name="warning_hedera_missing_token_association_message">Этот токен должен быть ассоциирован с вашей учетной записью Hedera, прежде чем вы сможете его принять. Стоимость ассоциации ~%1$s %2$s </string>
<string name="warning_hedera_missing_token_association_message_brief">Этот токен должен быть ассоциирован с вашей учетной записью Hedera, прежде чем вы сможете его принять</string>
<string name="warning_hedera_missing_token_association_title">Ассоциируете свой токен</string>
<string name="warning_hedera_token_association_not_enough_hbar_message">Недостаточно %s. Пополните ваш аккаунт Hedera для ассоциации этого токена</string>
<string name="warning_low_signatures_message">На этой карте осталось всего %s подписей. Вам следует вывести все ваши средства.</string>
<string name="warning_low_signatures_title">Малое количество подписей</string>
<string name="warning_manage_tokens_legacy_derivation_message">Токены на разных сетях могут иметь разные адреса. Пожалуйста, убедитесь при переводе средств, что ваш адрес соответствует сети.</string>
@ -689,6 +680,7 @@
<string name="warning_number_of_signed_hashes_incorrect_title">Карта уже подписывала транзакции</string>
<string name="warning_rate_app_message">Ваш отзыв мотивирует нас сделать кошелек Tangem еще лучше</string>
<string name="warning_rate_app_title">Нравится Tangem?</string>
<string name="warning_receive_blocked_hedera_token_association_required_message">Вам необходимо провести ассоциацию токена для того, чтобы иметь возможность принимать его</string>
<string name="warning_rent_fee_title">Необходима плата за аренду сети</string>
<string name="warning_send_blocked_funds_for_fee_message">%1$s - это монета в сети %2$s. Для совершения транзакции %3$s, вам необходимо внести немного %4$s (%5$s), чтобы покрыть комиссию сети.</string>
<string name="warning_send_blocked_funds_for_fee_title">Недостаточно %1$s для оплаты комиссии сети</string>

View file

@ -4,16 +4,12 @@
<string name="add_tokens_title">Manage tokens</string>
<string name="address_qr_code_message_format">Send only %1$s (%2$s) from %3$s network to this address. Using other tokens and networks may result in loss of funds.</string>
<string name="alert_button_request_support">Request support</string>
<string name="alert_button_try_again">Try again</string>
<string name="alert_demo_feature_disabled">This feature is disabled in Demo mode</string>
<string name="alert_failed_to_send_transaction_message">Reason: %s</string>
<string name="alert_failed_to_send_transaction_title">Can\'t send a transaction</string>
<string name="alert_manage_tokens_unsupported_blockchain_by_card_message">The selected does not support the %1$s network</string>
<string name="alert_manage_tokens_unsupported_curve_message">To activate the %1$s blockchain\'s cryptographic encryption, you\'ll need to reset the wallet to factory settings. Please withdraw your funds before doing so to ensure that you don\'t lose them, and then complete the reset process. Access to the current wallet will not be possible after the reset.</string>
<string name="alert_manage_tokens_unsupported_message">Tokens in %1$s network are not supported by this card due to firmware limitation.</string>
<string name="alert_negative_app_rate_sent_message">Thank you for your feedback. We will respond as soon as possible</string>
<string name="alert_negative_app_rate_sent_title">Your suggestions were sent</string>
<string name="alert_troubleshooting_scan_card_message">Please try to tap the card exactly as shown in the animation or request support.</string>
<string name="alert_troubleshooting_scan_card_title">Are you having difficulty scanning your card?</string>
<string name="alert_unsupported_card">This card is not designed to work with this app</string>
<string name="app_settings_default_fee">Default Fee</string>
@ -29,8 +25,6 @@
<string name="app_settings_theme_mode_dark">Dark</string>
<string name="app_settings_theme_mode_light">Light</string>
<string name="app_settings_theme_mode_system">System default</string>
<string name="app_settings_theme_selection_footer">If system is selected, the app will auto-adjust based on your device\'s system settings</string>
<string name="app_settings_theme_selection_system_short">System</string>
<string name="app_settings_theme_selector_title">Theme</string>
<string name="app_settings_title">App Settings</string>
<string name="balance_hidden_description">To hide or show your balances, simply flip your device screen down, or switch it off in Settings</string>
@ -80,7 +74,6 @@
<string name="common_create">Create</string>
<string name="common_delete">Delete</string>
<string name="common_disabled">Disabled</string>
<string name="common_disconnect">Disconnect</string>
<string name="common_done">Done</string>
<string name="common_enable">Enable</string>
<string name="common_enabled">Enabled</string>
@ -113,7 +106,6 @@
<string name="common_reject">Reject</string>
<string name="common_reload">Reload</string>
<string name="common_rename">Rename</string>
<string name="common_retry">Retry</string>
<string name="common_save_changes">Save changes</string>
<string name="common_search">Search</string>
<string name="common_search_tokens">Search tokens</string>
@ -137,7 +129,6 @@
<string name="common_understand">I understand</string>
<string name="common_unknown_error">There was an error. Please try again.</string>
<string name="common_unreachable">Unreachable</string>
<string name="common_warning">Warning</string>
<string name="common_yes">Yes</string>
<string name="contract_address_copied_message">Contract address copied!</string>
<string name="currency_subtitle_expanded">Available networks</string>
@ -184,7 +175,6 @@
<string name="details_row_title_flip_to_hide">Flip-to-Hide Balances</string>
<string name="details_row_title_issuer">Issuer</string>
<string name="details_row_title_signed_hashes">Signed</string>
<string name="details_security_management_warning">If you forget the code you will lose access to your funds. Code recovery is not possible.</string>
<string name="details_title">Details</string>
<string name="disclaimer_error_loading">Check your internet connection or switch to a different network</string>
<string name="disclaimer_title">Terms of Service</string>
@ -552,12 +542,12 @@
<string name="toast_balances_shown">Balances shown</string>
<string name="toast_undo">Undo</string>
<string name="token_button_unavailability_generic_description">This operation is currently unavailable. Please try again later.</string>
<string name="token_button_unavailability_reason_buy_unavailable">The purchase of the %s is currently unavailable. But we are working on adding it.</string>
<string name="token_button_unavailability_reason_empty_balance">You do not have funds to send. Top up your account to be able to send funds from it.</string>
<string name="token_button_unavailability_reason_no_quotes">This operation is currently unavailable. Please try again later.</string>
<string name="token_button_unavailability_reason_not_exchangeable">%s swap is not available. But we are working on adding it.</string>
<string name="token_button_unavailability_reason_sell_unavailable">Sell of the %s coin is currently unavailable. But we are working on adding it.</string>
<string name="token_details_choose_address">Choose address</string>
<string name="token_button_unavailability_reason_buy_unavailable">Buying %s is not available at the moment. Please check our updates.</string>
<string name="token_button_unavailability_reason_empty_balance_sell">You do not have funds to sell. Top up your account to be able to sell funds from it.</string>
<string name="token_button_unavailability_reason_empty_balance_send">You do not have funds to send. Top up your account to be able to send funds from it.</string>
<string name="token_button_unavailability_reason_not_exchangeable">Swapping %s is not available at the moment. Please check our updates.</string>
<string name="token_button_unavailability_reason_pending_transaction_sell">Selling funds will be available once the %s transaction is complete</string>
<string name="token_button_unavailability_reason_sell_unavailable">Selling %s is not available at the moment. Please check our updates.</string>
<string name="token_details_generate_xpub">Generate XPUB</string>
<string name="token_details_hide_alert_hide">Hide</string>
<string name="token_details_hide_alert_message">You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page.</string>
@ -668,9 +658,10 @@
<string name="warning_failed_to_verify_card_message">This card might be a production sample or counterfeit</string>
<string name="warning_failed_to_verify_card_title">Authenticity check failed</string>
<string name="warning_hedera_missing_token_association_button_title">Associate</string>
<string name="warning_hedera_missing_token_association_message">This token must be associated with your Hedera account before you can receive it. Association fee ~%.4f %s</string>
<string name="warning_hedera_missing_token_association_message">This token must be associated with your Hedera account before you can receive it. Association fee ~%1$s %2$s</string>
<string name="warning_hedera_missing_token_association_message_brief">This token must be associated with your Hedera account before you can receive it</string>
<string name="warning_hedera_missing_token_association_title">Associate your token</string>
<string name="warning_hedera_token_association_not_enough_hbar_message">Hot enough %s. Top up your Hedera account to associate this token</string>
<string name="warning_low_signatures_message">Only %s signatures are left on this card. You must withdraw all of your funds.</string>
<string name="warning_low_signatures_title">Low signature count</string>
<string name="warning_manage_tokens_legacy_derivation_message">Tokens on different networks can have different addresses. Double-check that your address matches the network when you transfer funds.</string>
@ -688,6 +679,7 @@
<string name="warning_number_of_signed_hashes_incorrect_title">Card has already signed transactions</string>
<string name="warning_rate_app_message">Your review keeps us motivated to make Tangem Wallet even better</string>
<string name="warning_rate_app_title">Enjoying Tangem?</string>
<string name="warning_receive_blocked_hedera_token_association_required_message">You must associate your token before receiving tokens</string>
<string name="warning_rent_fee_title">Network rent fee required</string>
<string name="warning_send_blocked_funds_for_fee_message">%1$s is an asset in the %2$s network. To make a %3$s transaction, you must deposit some %4$s (%5$s) to cover the network fee.</string>
<string name="warning_send_blocked_funds_for_fee_title">Insufficient %1$s to cover network fee</string>

View file

@ -6,6 +6,8 @@ import com.tangem.domain.tokens.model.CryptoCurrency
* Manager that holds info about available actions as Sell and Buy
*/
interface RampStateManager {
fun availableForBuy(cryptoCurrency: CryptoCurrency): Boolean
fun availableForSell(cryptoCurrency: CryptoCurrency): Boolean
}

View file

@ -9,13 +9,10 @@ import com.tangem.domain.tokens.repository.MarketCryptoCurrencyRepository
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.features.send.api.featuretoggles.SendFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.isNullOrZero
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import java.math.BigDecimal
/**
* Use case to determine which TokenActions are available for a [CryptoCurrency]
@ -29,7 +26,6 @@ class GetCryptoCurrencyActionsUseCase(
private val currenciesRepository: CurrenciesRepository,
private val quotesRepository: QuotesRepository,
private val networksRepository: NetworksRepository,
private val sendFeatureToggles: SendFeatureToggles,
private val dispatchers: CoroutineDispatcherProvider,
) {
@ -82,8 +78,9 @@ class GetCryptoCurrencyActionsUseCase(
/**
* Creates list of action for expected order
* Actions priority: [Buy Send Receive Sell Swap]
* Actions priority: [Receive Send Swap Buy Sell]
*/
@Suppress("CyclomaticComplexMethod", "LongMethod")
private suspend fun createListOfActions(
userWallet: UserWallet,
coinStatus: CryptoCurrencyStatus?,
@ -112,7 +109,6 @@ class GetCryptoCurrencyActionsUseCase(
// send
val sendUnavailabilityReason = getSendUnavailabilityReason(
userWalletId = userWallet.walletId,
cryptoCurrencyStatus = cryptoCurrencyStatus,
coinStatus = coinStatus,
)
@ -124,7 +120,10 @@ class GetCryptoCurrencyActionsUseCase(
// swap
if (userWallet.isMultiCurrency) {
if (marketCryptoCurrencyRepository.isExchangeable(userWallet.walletId, cryptoCurrency)) {
if (
marketCryptoCurrencyRepository.isExchangeable(userWallet.walletId, cryptoCurrency) &&
cryptoCurrencyStatus.value !is CryptoCurrencyStatus.NoQuote
) {
activeList.add(TokenActionsState.ActionState.Swap(ScenarioUnavailabilityReason.None))
} else {
disabledList.add(
@ -145,14 +144,42 @@ class GetCryptoCurrencyActionsUseCase(
}
// sell
if (rampManager.availableForSell(cryptoCurrency)) {
activeList.add(TokenActionsState.ActionState.Sell(ScenarioUnavailabilityReason.None))
} else {
disabledList.add(
TokenActionsState.ActionState.Sell(
unavailabilityReason = ScenarioUnavailabilityReason.SellUnavailable(cryptoCurrency.name),
),
)
val sellSupportedByService = rampManager.availableForSell(cryptoCurrency)
val sendAvailable = sendUnavailabilityReason is ScenarioUnavailabilityReason.None
when {
sellSupportedByService && sendAvailable -> {
activeList.add(TokenActionsState.ActionState.Sell(ScenarioUnavailabilityReason.None))
}
sellSupportedByService && !sendAvailable -> {
(sendUnavailabilityReason as? ScenarioUnavailabilityReason.EmptyBalance)?.let {
disabledList.add(
TokenActionsState.ActionState.Sell(
unavailabilityReason = it.copy(
withdrawalScenario = ScenarioUnavailabilityReason.WithdrawalScenario.SELL,
),
),
)
}
(sendUnavailabilityReason as? ScenarioUnavailabilityReason.PendingTransaction)?.let {
disabledList.add(
TokenActionsState.ActionState.Sell(
unavailabilityReason = it.copy(
withdrawalScenario = ScenarioUnavailabilityReason.WithdrawalScenario.SELL,
),
),
)
}
}
else -> {
disabledList.add(
TokenActionsState.ActionState.Sell(
unavailabilityReason = ScenarioUnavailabilityReason.NotSupportedBySellService(
cryptoCurrency.name,
),
),
)
}
}
// hide
@ -180,9 +207,9 @@ class GetCryptoCurrencyActionsUseCase(
),
)
}
actionsList.add(TokenActionsState.ActionState.Send(ScenarioUnavailabilityReason.NoQuotes))
actionsList.add(TokenActionsState.ActionState.Swap(ScenarioUnavailabilityReason.NoQuotes))
actionsList.add(TokenActionsState.ActionState.Sell(ScenarioUnavailabilityReason.NoQuotes))
actionsList.add(TokenActionsState.ActionState.Send(ScenarioUnavailabilityReason.Unreachable))
actionsList.add(TokenActionsState.ActionState.Swap(ScenarioUnavailabilityReason.Unreachable))
actionsList.add(TokenActionsState.ActionState.Sell(ScenarioUnavailabilityReason.Unreachable))
if (isAddressAvailable(cryptoCurrencyStatus.value.networkAddress)) {
actionsList.add(TokenActionsState.ActionState.Receive(ScenarioUnavailabilityReason.None))
@ -191,34 +218,22 @@ class GetCryptoCurrencyActionsUseCase(
return actionsList
}
private suspend fun getSendUnavailabilityReason(
userWalletId: UserWalletId,
private fun getSendUnavailabilityReason(
cryptoCurrencyStatus: CryptoCurrencyStatus,
coinStatus: CryptoCurrencyStatus?,
): ScenarioUnavailabilityReason {
val insufficientFundsForFee = insufficientFundsForFee(
userWalletId = userWalletId,
tokenStatus = cryptoCurrencyStatus,
coinStatus = coinStatus,
)
return when {
cryptoCurrencyStatus.value.amount.isNullOrZero() -> {
ScenarioUnavailabilityReason.EmptyBalance
}
insufficientFundsForFee != null -> {
ScenarioUnavailabilityReason.InsufficientFundsForFee(
currencyName = insufficientFundsForFee.currencyName,
networkName = insufficientFundsForFee.networkName,
feeCurrencyName = insufficientFundsForFee.feeCurrencyName,
feeCurrencySymbol = insufficientFundsForFee.feeCurrencySymbol,
)
ScenarioUnavailabilityReason.EmptyBalance(ScenarioUnavailabilityReason.WithdrawalScenario.SEND)
}
currenciesRepository.hasPendingTransactions(
cryptoCurrencyStatus = cryptoCurrencyStatus,
coinStatus = coinStatus,
) -> {
ScenarioUnavailabilityReason.PendingTransaction(coinStatus?.currency?.symbol.orEmpty())
ScenarioUnavailabilityReason.PendingTransaction(
withdrawalScenario = ScenarioUnavailabilityReason.WithdrawalScenario.SEND,
cryptoCurrencySymbol = coinStatus?.currency?.symbol.orEmpty(),
)
}
else -> {
ScenarioUnavailabilityReason.None
@ -226,93 +241,7 @@ class GetCryptoCurrencyActionsUseCase(
}
}
private suspend fun insufficientFundsForFee(
userWalletId: UserWalletId,
tokenStatus: CryptoCurrencyStatus,
coinStatus: CryptoCurrencyStatus?,
): FeeInfo? {
val feePaidCurrency = currenciesRepository.getFeePaidCurrency(userWalletId, tokenStatus.currency)
coinStatus ?: return null
return when {
sendFeatureToggles.isRedesignedSendEnabled && !tokenStatus.value.amount.isZero() -> {
null
}
feePaidCurrency is FeePaidCurrency.Coin &&
!tokenStatus.value.amount.isZero() &&
coinStatus.value.amount.isZero() -> {
FeeInfo(
currencyName = tokenStatus.currency.name,
networkName = coinStatus.currency.network.name,
feeCurrencyName = coinStatus.currency.name,
feeCurrencySymbol = coinStatus.currency.symbol,
)
}
feePaidCurrency is FeePaidCurrency.SameCurrency && !tokenStatus.value.amount.isZero() -> {
FeeInfo(
currencyName = tokenStatus.currency.name,
networkName = coinStatus.currency.network.name,
feeCurrencyName = coinStatus.currency.name,
feeCurrencySymbol = coinStatus.currency.symbol,
)
}
feePaidCurrency is FeePaidCurrency.Token -> {
val feePaidTokenBalance = feePaidCurrency.balance
val amount = tokenStatus.value.amount ?: return null
if (!amount.isZero() && feePaidTokenBalance.isZero()) {
constructTokenBalanceNotEnoughWarning(
userWalletId = userWalletId,
tokenStatus = tokenStatus,
feePaidToken = feePaidCurrency,
)
} else {
null
}
}
else -> null
}
}
private suspend fun constructTokenBalanceNotEnoughWarning(
userWalletId: UserWalletId,
tokenStatus: CryptoCurrencyStatus,
feePaidToken: FeePaidCurrency.Token,
): FeeInfo {
val token = currenciesRepository
.getMultiCurrencyWalletCurrenciesSync(userWalletId)
.find {
it is CryptoCurrency.Token &&
it.contractAddress.equals(feePaidToken.contractAddress, ignoreCase = true) &&
it.network.derivationPath == tokenStatus.currency.network.derivationPath
}
return if (token != null) {
FeeInfo(
currencyName = tokenStatus.currency.name,
networkName = token.network.name,
feeCurrencyName = feePaidToken.name,
feeCurrencySymbol = feePaidToken.symbol,
)
} else {
FeeInfo(
currencyName = tokenStatus.currency.name,
networkName = tokenStatus.currency.network.name,
feeCurrencyName = feePaidToken.name,
feeCurrencySymbol = feePaidToken.symbol,
)
}
}
private fun isAddressAvailable(networkAddress: NetworkAddress?): Boolean {
return networkAddress != null && networkAddress.defaultAddress.value.isNotEmpty()
}
private fun BigDecimal?.isZero(): Boolean {
return this?.signum() == 0
}
data class FeeInfo(
val currencyName: String,
val networkName: String,
val feeCurrencyName: String,
val feeCurrencySymbol: String,
)
}

View file

@ -3,15 +3,12 @@ package com.tangem.domain.tokens.model
sealed class ScenarioUnavailabilityReason {
data object None : ScenarioUnavailabilityReason()
// send-specific
data class PendingTransaction(val cryptoCurrencySymbol: String) : ScenarioUnavailabilityReason()
data object EmptyBalance : ScenarioUnavailabilityReason()
data class InsufficientFundsForFee(
val currencyName: String,
val networkName: String,
val feeCurrencyName: String,
val feeCurrencySymbol: String,
// send&sell-specific
data class PendingTransaction(
val withdrawalScenario: WithdrawalScenario,
val cryptoCurrencySymbol: String,
) : ScenarioUnavailabilityReason()
data class EmptyBalance(val withdrawalScenario: WithdrawalScenario) : ScenarioUnavailabilityReason()
// buy-specific
data class BuyUnavailable(val cryptoCurrencyName: String) : ScenarioUnavailabilityReason()
@ -20,7 +17,11 @@ sealed class ScenarioUnavailabilityReason {
data class NotExchangeable(val cryptoCurrencyName: String) : ScenarioUnavailabilityReason()
// sell-specific
data class SellUnavailable(val cryptoCurrencyName: String) : ScenarioUnavailabilityReason()
data class NotSupportedBySellService(val cryptoCurrencyName: String) : ScenarioUnavailabilityReason()
data object NoQuotes : ScenarioUnavailabilityReason()
data object Unreachable : ScenarioUnavailabilityReason()
enum class WithdrawalScenario {
SELL, SEND
}
}

View file

@ -334,29 +334,27 @@ internal class TokenDetailsStateFactory(
private fun getUnavailabilityReasonText(unavailabilityReason: ScenarioUnavailabilityReason): TextReference {
return when (unavailabilityReason) {
// send
is ScenarioUnavailabilityReason.PendingTransaction -> {
resourceReference(
id = R.string.warning_send_blocked_pending_transactions_message,
formatArgs = wrappedList(unavailabilityReason.cryptoCurrencySymbol),
)
when (unavailabilityReason.withdrawalScenario) {
ScenarioUnavailabilityReason.WithdrawalScenario.SEND -> resourceReference(
id = R.string.warning_send_blocked_pending_transactions_message,
formatArgs = wrappedList(unavailabilityReason.cryptoCurrencySymbol),
)
ScenarioUnavailabilityReason.WithdrawalScenario.SELL -> resourceReference(
id = R.string.token_button_unavailability_reason_pending_transaction_sell,
formatArgs = wrappedList(unavailabilityReason.cryptoCurrencySymbol),
)
}
}
ScenarioUnavailabilityReason.EmptyBalance -> {
resourceReference(
id = R.string.token_button_unavailability_reason_empty_balance,
)
}
is ScenarioUnavailabilityReason.InsufficientFundsForFee -> {
resourceReference(
id = R.string.warning_send_blocked_funds_for_fee_message,
formatArgs = wrappedList(
unavailabilityReason.currencyName,
unavailabilityReason.networkName,
unavailabilityReason.currencyName,
unavailabilityReason.feeCurrencyName,
unavailabilityReason.feeCurrencySymbol,
),
)
is ScenarioUnavailabilityReason.EmptyBalance -> {
when (unavailabilityReason.withdrawalScenario) {
ScenarioUnavailabilityReason.WithdrawalScenario.SEND -> resourceReference(
id = R.string.token_button_unavailability_reason_empty_balance_send,
)
ScenarioUnavailabilityReason.WithdrawalScenario.SELL -> resourceReference(
id = R.string.token_button_unavailability_reason_empty_balance_sell,
)
}
}
is ScenarioUnavailabilityReason.BuyUnavailable -> {
resourceReference(
@ -370,18 +368,17 @@ internal class TokenDetailsStateFactory(
formatArgs = wrappedList(unavailabilityReason.cryptoCurrencyName),
)
}
is ScenarioUnavailabilityReason.SellUnavailable -> {
is ScenarioUnavailabilityReason.NotSupportedBySellService -> {
resourceReference(
id = R.string.token_button_unavailability_reason_sell_unavailable,
formatArgs = wrappedList(unavailabilityReason.cryptoCurrencyName),
)
}
ScenarioUnavailabilityReason.NoQuotes -> {
ScenarioUnavailabilityReason.Unreachable -> {
resourceReference(
id = R.string.token_button_unavailability_reason_no_quotes,
id = R.string.token_button_unavailability_generic_description,
)
}
ScenarioUnavailabilityReason.None -> {
throw IllegalArgumentException("The unavailability reason must be other than None")
}

View file

@ -446,29 +446,27 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
private fun getUnavailabilityReasonText(unavailabilityReason: ScenarioUnavailabilityReason): TextReference {
return when (unavailabilityReason) {
// send
is ScenarioUnavailabilityReason.PendingTransaction -> {
resourceReference(
id = R.string.warning_send_blocked_pending_transactions_message,
formatArgs = wrappedList(unavailabilityReason.cryptoCurrencySymbol),
)
when (unavailabilityReason.withdrawalScenario) {
ScenarioUnavailabilityReason.WithdrawalScenario.SEND -> resourceReference(
id = R.string.warning_send_blocked_pending_transactions_message,
formatArgs = wrappedList(unavailabilityReason.cryptoCurrencySymbol),
)
ScenarioUnavailabilityReason.WithdrawalScenario.SELL -> resourceReference(
id = R.string.token_button_unavailability_reason_pending_transaction_sell,
formatArgs = wrappedList(unavailabilityReason.cryptoCurrencySymbol),
)
}
}
ScenarioUnavailabilityReason.EmptyBalance -> {
resourceReference(
id = R.string.token_button_unavailability_reason_empty_balance,
)
}
is ScenarioUnavailabilityReason.InsufficientFundsForFee -> {
resourceReference(
id = R.string.warning_send_blocked_funds_for_fee_message,
formatArgs = wrappedList(
unavailabilityReason.currencyName,
unavailabilityReason.networkName,
unavailabilityReason.currencyName,
unavailabilityReason.feeCurrencyName,
unavailabilityReason.feeCurrencySymbol,
),
)
is ScenarioUnavailabilityReason.EmptyBalance -> {
when (unavailabilityReason.withdrawalScenario) {
ScenarioUnavailabilityReason.WithdrawalScenario.SEND -> resourceReference(
id = R.string.token_button_unavailability_reason_empty_balance_send,
)
ScenarioUnavailabilityReason.WithdrawalScenario.SELL -> resourceReference(
id = R.string.token_button_unavailability_reason_empty_balance_sell,
)
}
}
is ScenarioUnavailabilityReason.BuyUnavailable -> {
resourceReference(
@ -482,15 +480,15 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
formatArgs = wrappedList(unavailabilityReason.cryptoCurrencyName),
)
}
is ScenarioUnavailabilityReason.SellUnavailable -> {
is ScenarioUnavailabilityReason.NotSupportedBySellService -> {
resourceReference(
id = R.string.token_button_unavailability_reason_sell_unavailable,
formatArgs = wrappedList(unavailabilityReason.cryptoCurrencyName),
)
}
ScenarioUnavailabilityReason.NoQuotes -> {
ScenarioUnavailabilityReason.Unreachable -> {
resourceReference(
id = R.string.token_button_unavailability_reason_no_quotes,
id = R.string.token_button_unavailability_generic_description,
)
}
ScenarioUnavailabilityReason.None -> {