Updated on 2026-08-14

This commit is contained in:
Tangem 2023-10-13 13:51:55 +03:00
parent 3f3a114dad
commit 355acaea56
14 changed files with 80 additions and 35 deletions

View file

@ -7,7 +7,7 @@
<string name="eth_gas_required_exceeds_allowance">Недостаточно средств для совершения транзакции. Пожалуйста, пополните свой аккаунт.</string>
<string name="generic_error_code">Произошла ошибка. Код: %s.</string>
<string name="kaspa_withdrawal_message_warning">Из-за ограничений Kaspa в одну транзакцию может поместиться только %1$d UTXO. Это означает, что вы можете отправить только %2$s или меньше. Вам нужно уменьшить сумму.</string>
<string name="no_account_generic">Пополните счет на %1$s+ %2$s, чтобы создать аккаунт</string>
<string name="no_account_generic">Чтобы использовать сеть %1$s, вы должны оплатить резерв аккаунта (%2$s %3$s), который блокируется и не используется в вашем балансе.</string>
<string name="no_account_polkadot">Аккаунт получателя не активирован. Отправьте %s или более для активации аккаунта.</string>
<string name="send_error_dust_amount_format">Минимальная сумма: %s</string>
<string name="send_error_dust_change">Сдача слишком мала</string>

View file

@ -7,7 +7,7 @@
<string name="eth_gas_required_exceeds_allowance">Not enough funds for the transaction. Please top up your account.</string>
<string name="generic_error_code">An error occurred. Code: %s.</string>
<string name="kaspa_withdrawal_message_warning">Due to Kaspa limitations only %1$d UTXOs can fit in a single transaction. This means you can only send %2$s or less. You need to reduce the amount.</string>
<string name="no_account_generic">Load %1$s+ %2$s to create account</string>
<string name="no_account_generic">To use the %1$s network, you must pay the account reserve (%2$s %3$s), which locks up and hides that amount indefinitely.</string>
<string name="no_account_polkadot">Destination account is not active. Send %s or more to activate the account.</string>
<string name="send_error_dust_amount_format">Minimum amount is %s</string>
<string name="send_error_dust_change">Change is too small</string>

View file

@ -608,7 +608,6 @@
<string name="warning_some_networks_unreachable_message">Some networks currently are unreachable. Please try again later.</string>
<string name="warning_some_networks_unreachable_title">Some networks are unreachable</string>
<string name="warning_testnet_card_message">This is a Testnet card. Don\'t accept it as a payment. This card must only be used for testing and development purposes.</string>
<string name="warning_title_note_top_up">Note top up</string>
<string name="welcome_interrupted_backup_alert_discard">Discard</string>
<string name="welcome_interrupted_backup_alert_message">You have an interrupted backup. Do you want to resume?</string>
<string name="welcome_interrupted_backup_alert_resume">Yes, resume</string>

View file

@ -71,10 +71,10 @@ data class CryptoCurrencyStatus(
/**
* Represents a state where there is no account associated with the cryptocurrency
*
* @property errorMessage error message
* @property amountToCreateAccount base reserve amount for account creation
*/
data class NoAccount(
val errorMessage: String,
val amountToCreateAccount: BigDecimal,
override val priceChange: BigDecimal?,
override val fiatRate: BigDecimal?,
) : Status(isError = false) {

View file

@ -18,6 +18,11 @@ sealed class CryptoCurrencyWarning {
object SomeNetworksUnreachable : CryptoCurrencyWarning()
data class SomeNetworksNoAccount(
val amountToCreateAccount: BigDecimal,
val amountCurrency: CryptoCurrency,
) : CryptoCurrencyWarning()
/**
* Represents wallet blockchain rent
* @param rent Amount that will be charged in overtime if the blockchain does not have an amount greater than

View file

@ -40,7 +40,8 @@ class GetCurrencyWarningsUseCase(
flowOf(walletManagersFacade.getRentInfo(userWalletId, currency.network)),
flowOf(walletManagersFacade.getExistentialDeposit(userWalletId, currency.network)),
flowOf(getNetworkUnavailableWarning(currencyStatus)),
) { maybeFeeWarning, maybeRentWarning, maybeEdWarning, maybeNetworkUnavailable ->
flowOf(getNetworkNoAccountWarning(currencyStatus)),
) { maybeFeeWarning, maybeRentWarning, maybeEdWarning, maybeNetworkUnavailable, maybeNetworkNoAccount ->
setOfNotNull(
maybeRentWarning,
maybeEdWarning?.let {
@ -51,6 +52,7 @@ class GetCurrencyWarningsUseCase(
},
maybeFeeWarning,
maybeNetworkUnavailable,
maybeNetworkNoAccount,
)
}.flowOn(dispatchers.io)
}
@ -106,6 +108,15 @@ class GetCurrencyWarningsUseCase(
}
}
private fun getNetworkNoAccountWarning(currencyStatus: CryptoCurrencyStatus): CryptoCurrencyWarning? {
return (currencyStatus.value as? CryptoCurrencyStatus.NoAccount)?.let {
CryptoCurrencyWarning.SomeNetworksNoAccount(
amountToCreateAccount = it.amountToCreateAccount,
amountCurrency = currencyStatus.currency,
)
}
}
private fun BigDecimal?.isZero(): Boolean {
return this?.signum() == 0
}

View file

@ -20,7 +20,7 @@ internal class CurrencyStatusOperations(
null -> CryptoCurrencyStatus.Loading
is NetworkStatus.MissedDerivation -> createMissedDerivationStatus()
is NetworkStatus.Unreachable -> createUnreachableStatus()
is NetworkStatus.NoAccount -> createNoAccountStatus(status.errorMessage)
is NetworkStatus.NoAccount -> createNoAccountStatus(status.amountToCreateAccount)
is NetworkStatus.Verified -> createStatus(status)
}
}
@ -31,11 +31,12 @@ internal class CurrencyStatusOperations(
private fun createUnreachableStatus(): CryptoCurrencyStatus.Unreachable =
CryptoCurrencyStatus.Unreachable(priceChange = quote?.priceChange, fiatRate = quote?.fiatRate)
private fun createNoAccountStatus(message: String): CryptoCurrencyStatus.NoAccount = CryptoCurrencyStatus.NoAccount(
errorMessage = message,
priceChange = quote?.priceChange,
fiatRate = quote?.fiatRate,
)
private fun createNoAccountStatus(amount: BigDecimal): CryptoCurrencyStatus.NoAccount =
CryptoCurrencyStatus.NoAccount(
amountToCreateAccount = amount,
priceChange = quote?.priceChange,
fiatRate = quote?.fiatRate,
)
private fun createStatus(status: NetworkStatus.Verified): CryptoCurrencyStatus.Status {
val amount = status.amounts[currency.id]

View file

@ -48,7 +48,7 @@ internal object MockTokenLists {
val loadingUngroupedTokenList = with(failedUngroupedTokenList) {
copy(
currencies = currencies.map { it.copy(value = CryptoCurrencyStatus.Loading) },
currencies = currencies.map { it.copy(value = CryptoCurrencyStatus.Loading) }.toNonEmptyListOrNull() ?: emptyList(),
totalFiatBalance = TokenList.FiatBalance.Loading,
)
}

View file

@ -60,7 +60,7 @@ internal object MockTokensStates {
value = CryptoCurrencyStatus.NoAccount(
priceChange = MockQuotes.quote7.priceChange,
fiatRate = MockQuotes.quote7.fiatRate,
errorMessage = "",
amountToCreateAccount = MockNetworks.amountToCreateAccount,
),
)
@ -69,7 +69,7 @@ internal object MockTokensStates {
value = CryptoCurrencyStatus.NoAccount(
priceChange = MockQuotes.quote8.priceChange,
fiatRate = MockQuotes.quote8.fiatRate,
errorMessage = "",
amountToCreateAccount = MockNetworks.amountToCreateAccount,
),
)
@ -78,7 +78,7 @@ internal object MockTokensStates {
value = CryptoCurrencyStatus.NoAccount(
priceChange = MockQuotes.quote9.priceChange,
fiatRate = MockQuotes.quote9.fiatRate,
errorMessage = "",
amountToCreateAccount = MockNetworks.amountToCreateAccount,
),
)
@ -87,7 +87,7 @@ internal object MockTokensStates {
value = CryptoCurrencyStatus.NoAccount(
priceChange = MockQuotes.quote10.priceChange,
fiatRate = MockQuotes.quote10.fiatRate,
errorMessage = "",
amountToCreateAccount = MockNetworks.amountToCreateAccount,
),
)

View file

@ -9,9 +9,8 @@ import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
import com.tangem.features.tokendetails.impl.R
// TODO: Finalize notification strings [REDACTED_JIRA]
@Immutable
sealed class TokenDetailsNotification {
internal sealed class TokenDetailsNotification {
abstract val config: NotificationConfig
@ -83,4 +82,15 @@ sealed class TokenDetailsNotification {
iconResId = R.drawable.img_attention_20,
)
}
class NetworksNoAccount(val network: String, val symbol: String, val amount: String) : Informational() {
override val config = NotificationConfig(
title = resourceReference(R.string.warning_no_account_title),
subtitle = resourceReference(
R.string.no_account_generic,
wrappedList(network, amount, symbol),
),
iconResId = R.drawable.ic_alert_circle_24,
)
}
}

View file

@ -37,6 +37,11 @@ internal class TokenDetailsNotificationConverter(
onCloseClick = clickIntents::onCloseRentInfoNotification,
)
CryptoCurrencyWarning.SomeNetworksUnreachable -> TokenDetailsNotification.NetworksUnreachable
is CryptoCurrencyWarning.SomeNetworksNoAccount -> TokenDetailsNotification.NetworksNoAccount(
network = warning.amountCurrency.name,
amount = warning.amountToCreateAccount.toString(),
symbol = warning.amountCurrency.symbol,
)
}
}
}

View file

@ -2,7 +2,10 @@ package com.tangem.feature.wallet.presentation.wallet.state.components
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.pluralReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.feature.wallet.impl.R
/**
@ -88,11 +91,6 @@ sealed class WalletNotification(val config: NotificationConfig) {
subtitle = resourceReference(id = R.string.warning_some_networks_unreachable_message),
)
data class TopUpNote(val errorMessage: String) : Warning(
title = resourceReference(id = R.string.warning_title_note_top_up),
subtitle = stringReference(value = errorMessage),
)
data class NumberOfSignedHashesIncorrect(val onCloseClick: () -> Unit) : Warning(
title = resourceReference(id = R.string.common_warning),
subtitle = resourceReference(id = R.string.alert_card_signed_transactions),
@ -117,6 +115,17 @@ sealed class WalletNotification(val config: NotificationConfig) {
),
)
data class NoAccount(val network: String, val symbol: String, val amount: String) : WalletNotification(
config = NotificationConfig(
title = resourceReference(id = R.string.warning_no_account_title),
subtitle = resourceReference(
id = R.string.no_account_generic,
wrappedList(network, amount, symbol),
),
iconResId = R.drawable.ic_alert_circle_24,
),
)
data class UnlockWallets(val onClick: () -> Unit) : WalletNotification(
config = NotificationConfig(
title = resourceReference(id = R.string.common_unlock_needed),

View file

@ -32,6 +32,7 @@ internal fun LazyListScope.notifications(configs: ImmutableList<WalletNotificati
is WalletNotification.MissingAddresses -> TangemTheme.colors.icon.accent
is WalletNotification.RateApp -> TangemTheme.colors.icon.attention
is WalletNotification.UnlockWallets -> TangemTheme.colors.icon.primary1
is WalletNotification.NoAccount -> TangemTheme.colors.icon.accent
is WalletNotification.Warning -> null
},
)

View file

@ -143,10 +143,7 @@ internal class WalletNotificationsListFactory(
condition = cryptoCurrencyList.hasUnreachableNetworks(),
)
val errorMessage = cryptoCurrencyList.geNoAccountStatusMessage()
if (errorMessage != null) {
add(element = WalletNotification.Warning.TopUpNote(errorMessage = errorMessage))
}
addNoAccountWarning(cryptoCurrencyList)
addIf(
element = WalletNotification.Warning.NumberOfSignedHashesIncorrect(
@ -169,12 +166,19 @@ internal class WalletNotificationsListFactory(
return any { it.value is CryptoCurrencyStatus.Unreachable }
}
private fun List<CryptoCurrencyStatus>.geNoAccountStatusMessage(): String? {
return this
.map(CryptoCurrencyStatus::value)
.filterIsInstance<CryptoCurrencyStatus.NoAccount>()
.firstOrNull()
?.errorMessage
private fun MutableList<WalletNotification>.addNoAccountWarning(cryptoCurrencyList: List<CryptoCurrencyStatus>) {
val noAccountNetwork = cryptoCurrencyList.firstOrNull { it.value is CryptoCurrencyStatus.NoAccount }
if (noAccountNetwork != null) {
val amountToCreateAccount = (noAccountNetwork.value as? CryptoCurrencyStatus.NoAccount)
?.amountToCreateAccount.toString()
add(
element = WalletNotification.NoAccount(
network = noAccountNetwork.currency.name,
amount = amountToCreateAccount,
symbol = noAccountNetwork.currency.symbol,
),
)
}
}
/**