Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-05 13:19:12 +03:00
parent 411a591509
commit 94a4486443
28 changed files with 393 additions and 178 deletions

View file

@ -54,8 +54,8 @@ internal object SettingsDomainModule {
@Singleton
fun providesShouldShowSaveWalletScreenUseCase(
settingsRepository: SettingsRepository,
): ShouldShowSaveWalletScreenUseCase {
return ShouldShowSaveWalletScreenUseCase(settingsRepository = settingsRepository)
): ShouldShowAskBiometryUseCase {
return ShouldShowAskBiometryUseCase(settingsRepository = settingsRepository)
}
@Provides
@ -138,10 +138,8 @@ internal object SettingsDomainModule {
@Provides
@Singleton
fun provideSetSaveWalletScreenShownUseCase(
settingsRepository: SettingsRepository,
): SetSaveWalletScreenShownUseCase {
return SetSaveWalletScreenShownUseCase(settingsRepository = settingsRepository)
fun provideSetSaveWalletScreenShownUseCase(settingsRepository: SettingsRepository): SetAskBiometryShownUseCase {
return SetAskBiometryShownUseCase(settingsRepository = settingsRepository)
}
@Provides

View file

@ -8,6 +8,7 @@ import com.tangem.common.json.TangemSdkAdapter
import com.tangem.common.services.secure.SecureStorage
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.models.scan.serialization.*
import com.tangem.domain.visa.model.VisaActivationRemoteState
import com.tangem.domain.visa.model.VisaCardActivationStatus
@ -122,6 +123,7 @@ internal object UserWalletsListManagerModule {
passwordRequester: HotWalletPasswordRequester,
appPreferencesStore: AppPreferencesStore,
hotWalletAccessCodeAttemptsRepository: HotWalletAccessCodeAttemptsRepository,
scanCardProcessor: ScanCardProcessor,
): UserWalletsListRepository {
val moshi = buildMoshi()
val secureStorage = buildSecureStorage(applicationContext = applicationContext)
@ -168,6 +170,7 @@ internal object UserWalletsListManagerModule {
appPreferencesStore = appPreferencesStore,
savePersistentInformation = ProviderSuspend { true }, // Always save persistent information for now
hotWalletAccessCodeAttemptsRepository = hotWalletAccessCodeAttemptsRepository,
scanCardProcessor = scanCardProcessor,
)
}

View file

@ -11,6 +11,7 @@ import com.tangem.common.map
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.getSyncOrDefault
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.isLocked
@ -38,6 +39,9 @@ import com.tangem.utils.ProviderSuspend
import com.tangem.utils.extensions.indexOfFirstOrNull
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import com.tangem.core.analytics.models.AnalyticsParam
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
@Suppress("LongParameterList", "LargeClass")
internal class DefaultUserWalletsListRepository(
@ -50,36 +54,45 @@ internal class DefaultUserWalletsListRepository(
private val savePersistentInformation: ProviderSuspend<Boolean>,
private val appPreferencesStore: AppPreferencesStore,
private val hotWalletAccessCodeAttemptsRepository: HotWalletAccessCodeAttemptsRepository,
private val scanCardProcessor: ScanCardProcessor,
) : UserWalletsListRepository {
override val userWallets = MutableStateFlow<List<UserWallet>?>(null)
override val selectedUserWallet = MutableStateFlow<UserWallet?>(null)
private val mutex = Mutex()
override suspend fun load() {
if (userWallets.value != null) return
mutex.withLock {
if (userWallets.value != null) return
if (savePersistentInformation().not()) {
// If we don't save persistent information, we don't need to load user wallets
// and we should clear any existing data
clearPersistentData()
updateWallets { emptyList() }
return
}
val unsecuredEncryptionKeys = userWalletEncryptionKeysRepository.getAllUnsecured()
publicInformationRepository.getAll()
.map { it.toUserWallets() }
.flatMap { wallets ->
sensitiveInformationRepository.getAll(unsecuredEncryptionKeys)
.map { wallets.updateWith(it) }
}.doOnSuccess {
userWallets.value = it
if (savePersistentInformation().not()) {
// If we don't save persistent information, we don't need to load user wallets
// and we should clear any existing data
clearPersistentData()
updateWallets { emptyList() }
return
}
val selectedUserWalletId = selectedUserWalletRepository.get()
selectedUserWallet.value = userWallets.value?.firstOrNull { it.walletId == selectedUserWalletId }
?: userWallets.value?.firstOrNull()
val unsecuredEncryptionKeys = userWalletEncryptionKeysRepository.getAllUnsecured()
publicInformationRepository.getAll()
.map { it.toUserWallets() }
.flatMap { wallets ->
sensitiveInformationRepository.getAll(unsecuredEncryptionKeys)
.map { wallets.updateWith(it) }
}
.doOnSuccess { loadedWallets ->
userWallets.update { toUpdate ->
val selectedUserWalletId = selectedUserWalletRepository.get()
selectedUserWallet.value = loadedWallets.firstOrNull { it.walletId == selectedUserWalletId }
?: loadedWallets.firstOrNull()?.also {
selectedUserWalletRepository.set(it.walletId)
}
loadedWallets
}
}
}
}
override suspend fun userWalletsSync(): List<UserWallet> {
@ -191,18 +204,17 @@ internal class DefaultUserWalletsListRepository(
userWalletEncryptionKeysRepository.delete(userWalletIds)
val userWalletsBeforeDelete = userWallets.value ?: return@either
userWallets.update { currentWallets ->
currentWallets?.filterNot { it.walletId in userWalletIds }
}
selectedUserWallet.update { currentSelected ->
if (currentSelected == null) return@update null
userWallets.value?.findAvailableUserWallet(
userWalletsBeforeDelete.indexOfFirstOrNull { it.walletId == currentSelected.walletId } ?: 0,
)
val updatedWallets = currentWallets?.filter { userWalletIds.contains(it.walletId).not() }
selectedUserWallet.update { currentSelected ->
if (currentSelected == null) return@update null
val newSelected = updatedWallets?.findAvailableUserWallet(
currentWallets.indexOfFirstOrNull { it.walletId == currentSelected.walletId } ?: 0,
)
selectedUserWalletRepository.set(newSelected?.walletId)
newSelected
}
updatedWallets
}
}
@ -258,7 +270,7 @@ internal class DefaultUserWalletsListRepository(
raise(UnlockWalletError.UnableToUnlock)
}
tangemSdkManagerProvider().scanProduct()
scanCardProcessor.scan(analyticsSource = AnalyticsParam.ScreensSources.SignIn)
.doOnSuccess { scanResponse ->
val expectedId = UserWalletIdBuilder.scanResponse(scanResponse).build()
@ -266,9 +278,14 @@ internal class DefaultUserWalletsListRepository(
raise(UnlockWalletError.ScannedCardWalletNotMatched)
}
saveWithoutLock(userWallet.copy(scanResponse = scanResponse), canOverride = true)
.mapLeft { UnlockWalletError.UnableToUnlock }
.bind()
val encryptionKey = UserWalletEncryptionKey(
walletId = userWallet.walletId,
encryptionKey = scanResponse.encryptionKey ?: raise(UnlockWalletError.UnableToUnlock),
)
sensitiveInformationRepository.getAll(listOf(encryptionKey))
.doOnSuccess { sensitiveInfo -> updateWallets { it?.updateWith(sensitiveInfo) } }
.doOnFailure { error -> raise(UnlockWalletError.UnableToUnlock) }
}
.doOnFailure {
raise(UnlockWalletError.UserCancelled)
@ -278,7 +295,8 @@ internal class DefaultUserWalletsListRepository(
}
override suspend fun unlockAllWallets(): Either<UnlockWalletError, Unit> = either {
val userWalletIds = userWalletsSync().map { it.walletId }.toSet()
val userWallets = userWalletsSync()
val userWalletIds = userWallets.map { it.walletId }.toSet()
val biometricKeys = runCatching {
userWalletEncryptionKeysRepository.getAllBiometric()
}.getOrElse {
@ -291,7 +309,7 @@ internal class DefaultUserWalletsListRepository(
val unlockedWalletsIds = allKeys.map { it.walletId }
val unlockedWallets = unlockedWalletsIds.mapNotNull { id ->
userWalletsSync().firstOrNull { it.walletId == id }
userWallets.firstOrNull { it.walletId == id }
}
// Remove all password attempts for unlocked hot wallets
@ -306,7 +324,7 @@ internal class DefaultUserWalletsListRepository(
sensitiveInformationRepository.getAll(allKeys)
.doOnSuccess { sensitiveInfo ->
updateWallets { it?.updateWith(sensitiveInfo) }
updateWallets { userWallets.updateWith(sensitiveInfo) }
}
.doOnFailure { raise(UnlockWalletError.UnableToUnlock) }
}
@ -390,11 +408,13 @@ internal class DefaultUserWalletsListRepository(
}
private fun updateWallets(block: (List<UserWallet>?) -> List<UserWallet>?) {
userWallets.update(block)
selectedUserWallet.update { currentSelected ->
if (currentSelected == null) return@update null
userWallets.value?.find { it.walletId == currentSelected.walletId }
userWallets.update {
val updated = block(it)
selectedUserWallet.update { currentSelected ->
if (currentSelected == null) return@update null
updated?.find { it.walletId == currentSelected.walletId }
}
updated
}
}

View file

@ -4,6 +4,7 @@ import com.tangem.common.extensions.calculateSha256
import com.tangem.domain.common.extensions.calculateHmacSha256
import com.tangem.domain.models.MobileWallet
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.models.wallet.UserWallet
internal val UserWallet.encryptionKey: ByteArray?
@ -19,6 +20,9 @@ private fun calculateEncryptionKey(publicKey: ByteArray): ByteArray {
return message.calculateHmacSha256(keyHash)
}
val ScanResponse.encryptionKey: ByteArray?
get() = findPublicKey(this.card.wallets)?.let { calculateEncryptionKey(it) }
private fun findPublicKey(wallets: List<CardDTO.Wallet>): ByteArray? {
return wallets.firstOrNull()?.publicKey
}

View file

@ -34,7 +34,7 @@ class UserWalletItemUMConverter(
private val appCurrency: AppCurrency? = null,
private val balance: TotalFiatBalance? = null,
private val isBalanceHidden: Boolean = false,
private val authMode: Boolean = false,
private val isAuthMode: Boolean = false,
private val endIcon: UserWalletItemUM.EndIcon = UserWalletItemUM.EndIcon.None,
artwork: UserWalletItemUM.ImageState? = null,
) : Converter<UserWallet, UserWalletItemUM> {
@ -58,11 +58,11 @@ class UserWalletItemUMConverter(
}
private fun isEnabled(userWallet: UserWallet): Boolean {
return authMode || userWallet.isLocked.not()
return isAuthMode || userWallet.isLocked.not()
}
private fun getLabelOrNull(userWallet: UserWallet): LabelUM? {
return if (authMode.not() && userWallet is UserWallet.Hot && !userWallet.backedUp) {
return if (isAuthMode.not() && userWallet is UserWallet.Hot && !userWallet.backedUp) {
LabelUM(
text = resourceReference(R.string.hw_backup_no_backup),
style = LabelStyle.WARNING,
@ -92,7 +92,7 @@ class UserWalletItemUMConverter(
private fun getBalanceInfo(userWallet: UserWallet): UserWalletItemUM.Balance {
return when {
userWallet.isLocked -> UserWalletItemUM.Balance.Locked
authMode -> UserWalletItemUM.Balance.NotShowing
isAuthMode -> UserWalletItemUM.Balance.NotShowing
isBalanceHidden -> UserWalletItemUM.Balance.Hidden
balance == null -> UserWalletItemUM.Balance.Loading
else -> {

View file

@ -7,7 +7,7 @@ import com.tangem.datasource.local.preferences.PreferencesKeys.IS_TANGEM_TOS_ACC
import com.tangem.datasource.local.preferences.PreferencesKeys.SAVE_USER_WALLETS_KEY
import com.tangem.datasource.local.preferences.PreferencesKeys.SHOULD_OPEN_WELCOME_ON_RESUME_KEY
import com.tangem.datasource.local.preferences.PreferencesKeys.SHOULD_SAVE_ACCESS_CODES_KEY
import com.tangem.datasource.local.preferences.PreferencesKeys.SHOULD_SHOW_SAVE_USER_WALLET_SCREEN_KEY
import com.tangem.datasource.local.preferences.PreferencesKeys.SHOULD_SHOW_ASK_BIOMETRY_KEY
import com.tangem.datasource.local.preferences.PreferencesKeys.SHOW_RATING_DIALOG_AT_LAUNCH_COUNT_KEY
import com.tangem.datasource.local.preferences.PreferencesKeys.USED_CARDS_INFO_KEY
import com.tangem.datasource.local.preferences.PreferencesKeys.USER_WAS_INTERACT_WITH_RATING_KEY
@ -26,7 +26,7 @@ object PreferencesKeys {
val SAVE_USER_WALLETS_KEY by lazy { booleanPreferencesKey(name = "saveUserWallets") }
val SHOULD_SHOW_SAVE_USER_WALLET_SCREEN_KEY by lazy { booleanPreferencesKey("saveUserWalletShown") }
val SHOULD_SHOW_ASK_BIOMETRY_KEY by lazy { booleanPreferencesKey("saveUserWalletShown") }
val APP_LAUNCH_COUNT_KEY by lazy { intPreferencesKey(name = "launchCount") }
@ -183,7 +183,7 @@ object PreferencesKeys {
internal fun getTapPrefKeysToMigrate(): Set<String> {
return setOf(
SAVE_USER_WALLETS_KEY,
SHOULD_SHOW_SAVE_USER_WALLET_SCREEN_KEY,
SHOULD_SHOW_ASK_BIOMETRY_KEY,
APP_LAUNCH_COUNT_KEY,
SHOW_RATING_DIALOG_AT_LAUNCH_COUNT_KEY,
FUNDS_FOUND_DATE_KEY,

View file

@ -452,7 +452,7 @@
<string name="express_fetch_best_rates">Aktuelle Preise werden abgerufen ...</string>
<string name="express_floating_rate">Variabler Zinssatz</string>
<string name="express_legal_one_placeholder">Durch die Nutzung der Swap-Funktion erklärst du dich mit den folgenden Bedingungen des Anbieters einverstanden %s</string>
<string name="express_legal_two_placeholders">Durch die Nutzung der Swap-Funktionalität erklärst du dich mit des Anbieters %1$s und %2$s einverstanden</string>
<string name="express_legal_two_placeholders">Durch die Nutzung der Swap-Funktionalität erklärst du dich mit des Anbieters %1$s und %2$s einverstanden.</string>
<string name="express_more_providers_soon">Weitere Anbieter folgen in Kürze</string>
<string name="express_provider">Anbieter</string>
<string name="express_provider_best_rate">Bester Preis</string>
@ -1039,7 +1039,7 @@
<string name="send_sending">Senden...</string>
<string name="send_summary_tap_hint">Berühre an beliebiger Stelle für Änderungen</string>
<string name="send_summary_title">Versende %s</string>
<string name="send_summary_transaction_description">Du sendest **%1$s** inklusive der Netzwerkgebühr %2$s</string>
<string name="send_summary_transaction_description">Du sendest **%1$s** inklusive der Netzwerkgebühr %2$s.</string>
<string name="send_summary_transaction_description_no_fiat_fee">Du sendest **%1$s** und %2$s</string>
<string name="send_summary_transaction_description_prefix">Du sendest **%1$s**</string>
<string name="send_summary_transaction_description_suffix_fee_covered">Die Netzwerkgebühr wird durch die Nutzung von %1$s Energieträgern gedeckt.</string>

View file

@ -26,7 +26,7 @@
<string name="add_tokens_title">Gestionar tokens</string>
<string name="address_qr_code_message_format">Envíe solo %1$s (%2$s) desde redes como %3$s a esta dirección. Usar otros tokens y redes puede resultar en la pérdida de fondos.</string>
<string name="address_type_default">Por defecto</string>
<string name="address_type_legacy">Legado</string>
<string name="address_type_legacy">Legacy</string>
<string name="alert_button_how_to_scan">Cómo escanear</string>
<string name="alert_button_request_support">Solicitar soporte</string>
<string name="alert_button_try_again">Inténtelo de nuevo</string>
@ -65,8 +65,8 @@
<string name="backup_info_save_description">Guarde estas %s palabras en un lugar seguro, como un administrador de contraseñas, y nunca las comparta con nadie.</string>
<string name="backup_info_save_title">No se puede restaurar</string>
<string name="backup_info_title">Frase de recuperación</string>
<string name="backup_seed_description">Escriba estas palabras %s en orden y guárdelas en un lugar privado y seguro</string>
<string name="backup_seed_responsibility">La responsabilidad total de la seguridad y la copia de seguridad de la billetera y la frase de recuperación recae en el usuario, no en Tangem.</string>
<string name="backup_seed_description">Escriba estas %s palabras en orden y guárdelas en un lugar privado y seguro</string>
<string name="backup_seed_responsibility">La responsabilidad total sobre la seguridad y copia de seguridad de la billetera y su frase de recuperación recae en el usuario, no en Tangem.</string>
<string name="backup_seed_title">Frase de recuperación</string>
<string name="balance_hidden_description">Para ocultar o mostrar tus saldos, simplemente gira la pantalla de tu dispositivo hacia abajo, o desactívalo en Ajustes</string>
<string name="balance_hidden_do_not_show_button">No mostrar de nuevo</string>
@ -118,7 +118,7 @@
<string name="cardano_coin_will_be_send_with_token_title">Requisitos de transacción de Cardano</string>
<string name="cardano_insufficient_balance_to_send_token_description">Para realizar una %1$s transacción, deba depositar algo de ADA para cubrir la tarifa de red y el valor mínimo de ADA (se recomiendan 5 ADA)</string>
<string name="cardano_insufficient_balance_to_send_token_title">ADA insuficiente para la transferencia de tokens</string>
<string name="cardano_low_ada">El monto enviado y el cambio no pueden ser menores a 1 ADA</string>
<string name="cardano_low_ada">La cantidad enviada y el cambio no pueden ser menores a 1 ADA</string>
<string name="cardano_max_amount_has_token_description">Deba mantener algo de ADA porque tiene algunos tokens en la blockchain de Cardano</string>
<string name="cardano_max_amount_has_token_title">ADA insuficiente</string>
<string name="common_accept">Aceptar</string>
@ -147,9 +147,9 @@
<string name="common_cancel">Cancelar</string>
<string name="common_change">Cambie</string>
<string name="common_choose_action">Elige una acción</string>
<string name="common_choose_network">Elegir red</string>
<string name="common_choose_token">Elige token</string>
<string name="common_choose_wallet">Elegir wallet</string>
<string name="common_choose_network">Elija red</string>
<string name="common_choose_token">Elija token</string>
<string name="common_choose_wallet">Elija wallet</string>
<string name="common_claim">Reclamar</string>
<string name="common_claim_rewards">Reclame recompensas</string>
<string name="common_close">Cerrar</string>
@ -221,7 +221,7 @@
<string name="common_origin_ring">Anillo primario</string>
<string name="common_passphrase">Frase de contraseña</string>
<string name="common_paste">Pegar</string>
<string name="common_privacy_policy">Política de privacidad</string>
<string name="common_privacy_policy">Política de privacidad</string>
<string name="common_range">%1$s-%2$s</string>
<string name="common_range_with_space">%1$s — %2$s</string>
<string name="common_read_more">Leer más</string>
@ -254,10 +254,10 @@
<string name="common_submit">Enviar</string>
<string name="common_success">Con éxito</string>
<string name="common_support">Soporte</string>
<string name="common_supported_networks">Redes compatibles</string>
<string name="common_supported_networks">Redes soportadas</string>
<string name="common_swap">Swap</string>
<string name="common_terms_and_conditions">términos y condiciones</string>
<string name="common_terms_of_use">Condiciones de uso</string>
<string name="common_terms_of_use">Condiciones de uso</string>
<string name="common_today">Hoy</string>
<plurals name="common_tokens_count">
<item quantity="one">%d token</item>
@ -271,7 +271,7 @@
<string name="common_unknown_error">Hubo un error. Por favor inténtelo de nuevo.</string>
<string name="common_unreachable">Inaccesible</string>
<string name="common_unstake">Termine el staking</string>
<string name="common_utxo_validate_withdrawal_message_warning">Debido a limitaciónes sobre %1$s, solos %2$d UTXO pueden caber en una sola transacción. Esto significa que solo puedes enviar %3$s o menos. Debe reducir la cantidad.</string>
<string name="common_utxo_validate_withdrawal_message_warning">Debido a limitaciones sobre %1$s, solo %2$d UTXO pueden caber en una sola transacción. Esto significa que solo puedes enviar %3$s o menos. Debe reducir la cantidad.</string>
<string name="common_value_copied">Valor copiado</string>
<string name="common_week">semana</string>
<string name="common_with">con</string>
@ -334,7 +334,8 @@
<string name="domain_receive_assets_navigation_title">Recibir activos</string>
<string name="domain_receive_assets_network_name_address">%s dirección</string>
<string name="domain_receive_assets_onboarding_description">Enviar activos a otras redes resultará en una pérdida permanente.</string>
<string name="domain_receive_assets_onboarding_title">Envíe fondos utilizando solo</string>
<string name="domain_receive_assets_onboarding_network_name">Red de %s</string>
<string name="domain_receive_assets_onboarding_title">Envíe fondos utilizando solo la</string>
<string name="email_preface_wc_error">Hola equipo de soporte, he encontrado un error con el código: %s</string>
<string name="email_subject_wc_error">Error de WalletConnect</string>
<string name="error_wrong_wallet_tapped">Ha usado una tarjeta de otra billetera. Toque la tarjeta asociada con esta billetera</string>
@ -377,7 +378,7 @@
<string name="express_exchange_status_receiving">Esperando depósito</string>
<string name="express_exchange_status_receiving_active">Esperando depósito</string>
<string name="express_exchange_status_refunded">Reembolso completado</string>
<string name="express_exchange_status_refunding">A la espera del reembolso</string>
<string name="express_exchange_status_refunding">Esperando reembolso</string>
<string name="express_exchange_status_sending">Transfiriendo a su cuenta</string>
<string name="express_exchange_status_sending_active">Enviando fondos...</string>
<string name="express_exchange_status_sent">Fondos enviados</string>
@ -389,12 +390,12 @@
<string name="express_fetch_best_rates">Buscar tarifas actuales...</string>
<string name="express_floating_rate">Tasa flotante</string>
<string name="express_legal_one_placeholder">Al utilizar la función de intercambio, acepta el %s</string>
<string name="express_legal_two_placeholders">Al utilizar la función de intercambio, aceptas las condiciones de %1$s y %2$s del proveedor</string>
<string name="express_legal_two_placeholders">Al utilizar la función de intercambio, aceptas las condiciones de %1$s y %2$s del proveedor.</string>
<string name="express_more_providers_soon">Pronto habrá más proveedores disponibles</string>
<string name="express_provider">Proveedor</string>
<string name="express_provider_best_rate">Mejor tarifa</string>
<string name="express_provider_fca_warning_list">Lista de advertencias de la FCA</string>
<string name="express_provider_in_fca_warning_list">Proveedor en la lista de advertencia de la FCA</string>
<string name="express_provider_in_fca_warning_list">Proveedor en la lista de advertencias de la FCA</string>
<string name="express_provider_max_amount">Disponible hasta %s</string>
<string name="express_provider_min_amount">Disponible desde %s</string>
<string name="express_provider_not_available">No disponible para este par</string>
@ -407,7 +408,7 @@
<string name="express_status_hide_dialog_text">Una vez oculto, el estado de la transacción no se puede volver a ver. En su lugar, basta con deslizar el dedo para descartarla.</string>
<string name="express_status_hide_dialog_title">¿Ocultar el estado de la transacción?</string>
<string name="express_swap_not_supported_text">Este token no es compatible. Por favor, elige un token diferente para intercambiar.</string>
<string name="express_swap_not_supported_title">%s no es compatible</string>
<string name="express_swap_not_supported_title">%s no está soportado</string>
<string name="express_swap_with">Intercambiar con</string>
<string name="express_token_list_empty_search">No se encontraron fichas. Por favor intenta con otra solicitud</string>
<string name="express_transaction_id">ID : %s</string>
@ -436,8 +437,8 @@
<string name="give_permission_swap_subtitle" formatted="false">Para continuar, de autorización a los smart contracts de %1s para usar su %2s</string>
<string name="give_permission_title">Dar autorización</string>
<string name="give_permission_unlimited">Ilimitado</string>
<string name="home_button_add_existing_wallet">Agregar billetera existente</string>
<string name="home_button_create_new_wallet">Crear nueva billetera</string>
<string name="home_button_add_existing_wallet">Agregar Billetera Existente</string>
<string name="home_button_create_new_wallet">Crear Nueva Billetera</string>
<string name="home_button_order">Pedir Tangem</string>
<string name="home_button_scan">Escanee</string>
<string name="hot_crypto_add_token_subtitle">a %s</string>
@ -524,7 +525,7 @@
<string name="markets_sort_by_top_gainers_title">Top Ganadores</string>
<string name="markets_sort_by_top_losers_title">Top Perdedores</string>
<string name="markets_sort_by_trending_title">Tendencias</string>
<string name="markets_staking_banner_description_placeholder">Staking es la forma más fácil de recibir recompensas por tus criptomonedas. %s</string>
<string name="markets_staking_banner_description_placeholder">Staking es la forma más fácil de recibir recompensas por sus criptomonedas. %s</string>
<string name="markets_staking_banner_title">Gana hasta %s APY</string>
<string name="markets_token_details_about_token_title">Acerca de %s</string>
<plurals name="markets_token_details_amount_exchanges">
@ -605,14 +606,14 @@
<string name="nft_collections_title">Colecciones de NFT</string>
<string name="nft_collections_warning_subtitle">Es posible que algunos datos no se carguen</string>
<string name="nft_collections_warning_title">Problemas temporales de carga</string>
<string name="nft_details_base_information">Información de base</string>
<string name="nft_details_base_information">Información básica</string>
<string name="nft_details_chain">Cadena</string>
<string name="nft_details_contract_address">Dirección del contrato</string>
<string name="nft_details_info_chain">Cadena es la blockchain en la que está el NFT.</string>
<string name="nft_details_info_contract_address">La dirección del contrato es un identificador único para el contrato inteligente que gobierna los tokens en la blockchain</string>
<string name="nft_details_info_rarity_label">Una etiqueta que describe lo raro que es el NFT. Cuanto menor sea el valor, más único será el NFT.</string>
<string name="nft_details_info_rarity_rank">La posición de un NFT en el ranking de rareza entre otros tokens. Cuanto más alto sea el ranking, más raro y valioso será el NFT.</string>
<string name="nft_details_info_token_address">La dirección del contrato es un identificador único para el contrato inteligente que gobierna los tokens en la blockchain</string>
<string name="nft_details_info_token_address">La dirección del token es un identificador único del token en la blockchain, que permite el seguimiento de las transacciones y la propiedad</string>
<string name="nft_details_info_token_id">El ID del token es un identificador único asignado a cada token, que lo distingue de otros en la colección.</string>
<string name="nft_details_info_token_standard">El estándar de token define qué tipo de token es y cómo funciona con diferentes billeteras y plataformas</string>
<string name="nft_details_last_sale_price">Último precio de venta</string>
@ -642,13 +643,13 @@
<string name="nft_wallet_receive_nft">Pulse aquí para recibir el primer NFT</string>
<string name="nft_wallet_title">Colecciones de NFT</string>
<string name="nft_wallet_unable_to_load">No se pueden cargar los datos</string>
<string name="no_account_generic">Para utilizar la red %1$s, debe pagar la reserva de cuenta (%2$s%3$s), que bloquea y oculta ese monto indefinidamente</string>
<string name="no_account_generic">Para utilizar la red %1$s, debe pagar la reserva de cuenta (%2$s%3$s), que bloqueará y ocultará esa cantidad indefinidamente</string>
<string name="no_account_polkadot">La cuenta de destino no está activa. Envíe %s o más para activar la cuenta.</string>
<string name="no_account_send_to_create">Para crear una cuenta, envíe fondos a esta dirección</string>
<string name="no_trustline_xlm_asset">La cuenta de destino no tiene una Trustline para el activo que se envía.</string>
<string name="notification_referral_promo_button">Únete ahora</string>
<string name="notification_referral_promo_text">Comparte tu código y gana 5 USDT por venta. Tu amigo obtiene un 10% de descuento.</string>
<string name="notification_referral_promo_title">¡Obtén RECOMPENSAS por cada amigo!</string>
<string name="no_trustline_xlm_asset">La cuenta de destino no tiene una Trustline (línea de confianza) para el activo que se envía.</string>
<string name="notification_referral_promo_button">Únase ahora</string>
<string name="notification_referral_promo_text">Comparta su código y gane 5 USDT por venta. Su amigo obtiene un 10% de descuento.</string>
<string name="notification_referral_promo_title">¡Obtenga RECOMPENSAS por cada amigo!</string>
<string name="onboarding_access_code_feature_1_description">Deba configurar un único código de acceso para proteger todss sus dispositivos.</string>
<string name="onboarding_access_code_feature_1_title">Proteger</string>
<string name="onboarding_access_code_feature_2_description">Puede configurar un código de acceso individual en cada tarjeta más adelante</string>
@ -775,11 +776,11 @@
<string name="organize_tokens_title">Organizar tokens</string>
<string name="organize_tokens_ungroup">Desagrupar</string>
<string name="push_notifications_more_info">Más información</string>
<string name="push_notifications_permission_alert_description">Puedes activar las Notificaciones para Tangem en Ajustes.</string>
<string name="push_notifications_permission_alert_description">Puede activar las Notificaciones para Tangem en Ajustes.</string>
<string name="push_notifications_permission_alert_negative_button">Activar más tarde</string>
<string name="push_notifications_permission_alert_positive_button">Ajustes</string>
<string name="push_notifications_permission_alert_title">Activar notificaciones</string>
<string name="push_transactions_notifications_description">Reciba alertas de transacciones entrantes en las redes compatibles</string>
<string name="push_transactions_notifications_description">Reciba alertas de transacciones entrantes en las redes soportadas</string>
<string name="push_transactions_notifications_title">Notificaciones de transacciones</string>
<string name="qr_scanner_camera_denied_gallery_button">Seleccione de la galería</string>
<string name="qr_scanner_camera_denied_settings_button">Ajustes</string>
@ -869,11 +870,11 @@
<string name="send_enter_address_field">Introduce la dirección</string>
<string name="send_enter_address_field_ens">Nombre ENS o dirección</string>
<string name="send_error_address_same_as_wallet">La dirección es la misma que su billetera.</string>
<string name="send_error_dust_amount_format">El monto mínimo es %s</string>
<string name="send_error_dust_amount_format">La cantidad mínima es %s</string>
<string name="send_error_dust_change_format">El cambio mínimo es %s</string>
<string name="send_error_invalid_fee_value">Tarifa no válida</string>
<string name="send_error_minimum_balance_format">El saldo mínimo es %s</string>
<string name="send_error_no_target_account">No se ha creado la cuenta de destino. El monto a enviar debe ser %s + comisiones o más</string>
<string name="send_error_no_target_account">No se ha creado la cuenta de destino. La cantidad a enviar debe ser %s + comisiones o más</string>
<string name="send_error_unknown">Error desconocido</string>
<string name="send_extras_error_invalid_memo">Memo no válido. No se añadirá a la transacción.</string>
<string name="send_extras_hint_memo">Memo</string>
@ -893,7 +894,7 @@
<string name="send_memo_destination_tag_error">Memo no válido</string>
<string name="send_network_fee_warning_title">Cobertura de tarifa de red</string>
<string name="send_nonce">Nonce</string>
<string name="send_nonce_footer">Número único para cada transacción. Utilízalo para reenviar o cancelar una transacción pendiente.</string>
<string name="send_nonce_footer">Número único para cada transacción. Utilícelo para reenviar o cancelar una transacción pendiente.</string>
<string name="send_nonce_hint">Introduzca nonce..</string>
<string name="send_notification_exceed_balance_text">Fondos insuficientes para la transferencia, ya que el total de la tarifa y el importe de la transferencia supera el saldo existente</string>
<string name="send_notification_exceed_balance_title">El total supera el saldo</string>
@ -934,7 +935,7 @@
<string name="send_sending">Enviando...</string>
<string name="send_summary_tap_hint">Toque cualquier campo para editarlo</string>
<string name="send_summary_title">Enviar %s</string>
<string name="send_summary_transaction_description">Está enviando **%1$s** incluida una tarifa de red de %2$s</string>
<string name="send_summary_transaction_description">Está enviando **%1$s** incluida una tarifa de red de %2$s.</string>
<string name="send_summary_transaction_description_no_fiat_fee">Está enviando**%1$s** y %2$s</string>
<string name="send_summary_transaction_description_prefix">Está enviando **%1$s**</string>
<string name="send_summary_transaction_description_suffix_fee_covered">La tarifa de red se cubrirá al usar %1$s energía</string>
@ -943,18 +944,18 @@
<string name="send_to_address">A la dirección</string>
<string name="send_transaction_success">La transacción se firmó con éxito y se envió al nodo blockchain. El saldo de la billetera se actualizará después de un tiempo.</string>
<string name="send_tron_account_activation_error">%1$s es un activo en la red Tron. Para calcular la tarifa y realizar una transacción, deba depositar algo de Tron (TRX) en su cuenta.</string>
<string name="send_validation_amount_exceeds_balance">El monto excede el saldo</string>
<string name="send_validation_amount_exceeds_balance">La cantidad excede el saldo</string>
<string name="send_validation_destination_tag_required_description">Es necesario una etiqueta de destino (memo) para completar esta transacción para la dirección especificada.</string>
<string name="send_validation_destination_tag_required_title">Etiqueta de destino obligatoria</string>
<string name="send_validation_invalid_amount">Cantidad no válida</string>
<string name="send_validation_invalid_fee">La tarifa excede el saldo</string>
<string name="send_validation_invalid_total">El monto total excede el saldo</string>
<string name="send_validation_invalid_total">La cantidad total excede el saldo</string>
<string name="send_with_swap_confirm_title">Intercambiar y enviar</string>
<string name="send_with_swap_convert_token_alert_message">¿Continuar con la conversión? Esto borrará sus datos anteriores.</string>
<string name="send_with_swap_convert_token_alert_title">Confirmar Conversión</string>
<string name="send_with_swap_correct_recipient_network_notification_message">El envío de cualquier otra moneda supondrá su pérdida irreversible.</string>
<string name="send_with_swap_correct_recipient_network_notification_title">Seleccione la red de destino correcta</string>
<string name="send_with_swap_notification_text">Envía cualquier token y lo convertiremos en el camino. Su destinatario obtiene exactamente lo que necesita, sin problemas.</string>
<string name="send_with_swap_notification_text">Elige cualquier token para recibir. Su destinatario recibirá exactamente lo que seleccionaste, sin problemas.</string>
<string name="send_with_swap_recipient_amount_success_title">El destinatario recibirá</string>
<string name="send_with_swap_recipient_amount_text">Al destinatario</string>
<string name="send_with_swap_recipient_amount_title">Cantidad a recibir</string>
@ -966,7 +967,7 @@
<string name="settings_forget_wallet">Olvidar la billetera</string>
<string name="settings_forget_wallet_footer">Esto eliminará la wallet de la aplicación. La wallet en sí puede\nañadirse de nuevo.</string>
<string name="settings_wallet_name_title">Nombre</string>
<string name="stake_token_description">Haz que tu token trabaje por ti</string>
<string name="stake_token_description">Haga que su token trabaje para Ud.</string>
<string name="staking_amount_requirement_error">El monto del staking debe ser al menos %s</string>
<string name="staking_amount_tron_integer_error">El monto del staking se redondeará a %1$s TRX debido a las reglas de la red.</string>
<string name="staking_amount_tron_integer_error_unstaking">El monto de cancelación del staking se redondeará a %1$s TRX debido a las reglas de la red.</string>
@ -1101,7 +1102,7 @@
<string name="story_web3_title">Compatible con Web 3.0</string>
<string name="sui_not_enough_coin_for_fee_description">Se requiere una transacción entrante de al menos %1$s para proceder</string>
<string name="sui_not_enough_coin_for_fee_title">Fondos insuficientes</string>
<string name="swap_fixed_rate">Tasa fija</string>
<string name="swap_fixed_rate">Tasa Fija</string>
<string name="swap_give_permission_fee_footer">La red cobrará una tarifa de aprobación de token para verificar que está autorizando el uso de su token para el swap.</string>
<string name="swap_promo_text">Intercambie más tokens a mejores tasas directamente en su billetera.</string>
<string name="swap_promo_title">¡Nuevo proveedor de intercambio disponible!</string>
@ -1176,12 +1177,12 @@
<string name="transaction_history_transaction_from_address">desde: %s</string>
<string name="transaction_history_transaction_to_address">a: %s</string>
<string name="transaction_history_transaction_validator">validador: %s</string>
<string name="transaction_notifications_warning_description">Las notificaciones están activadas, pero no funcionarán hasta que permitas las notificaciones en la configuración de tu dispositivo.</string>
<string name="transaction_notifications_warning_description">Las notificaciones están activadas, pero no funcionarán hasta que permita las notificaciones en la configuración de su dispositivo.</string>
<string name="transaction_notifications_warning_title">Notificaciones de transacciones</string>
<string name="transfer_min_amount_error">Mínimo %s</string>
<string name="transfer_notification_invalid_minimum_transaction_amount_text">El monto mínimo para realizar esta transacción es %1$s.</string>
<string name="tron_will_be_send_token_fee_description">Las tarifas de la red Tron para tokens populares pueden ser más altas. Hacer staking de TRX puede ayudar a reducir los costos de transacción.</string>
<string name="tron_will_be_send_token_fee_title">Ahorra en las tarifas de la red Tron</string>
<string name="tron_will_be_send_token_fee_description">Las tarifas de la red Tron para tokens populares pueden ser más altas. Hacer staking de TRX puede ayudar a reducir costes de transacción.</string>
<string name="tron_will_be_send_token_fee_title">Ahorre en las tarifas de la red Tron</string>
<string name="try_to_load_data_again_button_title">Inténtelo de nuevo</string>
<string name="twin_error_same_card">Ha escaneado la misma tarjeta. Para crear una billetera gemela, necesite escanear la tarjeta con no. %d</string>
<string name="twin_error_wrong_twin">Ha escaneado la tarjeta gemela incorrecta. Por favor, intente con otra</string>
@ -1196,7 +1197,7 @@
<string name="twins_scan_twin_with_number">Toque la tarjeta gemela con el número %s y no la retira hasta el final de la operación</string>
<string name="unexpected_error_description">Por favor, inténtelo de nuevo más tarde. Si el problema persiste, póngase en contacto con el servicio de asistencia.</string>
<string name="unexpected_error_title">¡Algo salió mal!</string>
<string name="universal_error">Hemos encontrado un error. Código de error: %s. Póngase en contacto con nuestro servicio de asistencia.</string>
<string name="universal_error">Hemos encontrado un error. Código de error: %s. Póngase en contacto con nuestro servicio de soporte.</string>
<string name="unlock_wallet_description_full">Use %s o escanee una tarjeta/anillo para tener acceso a su billetera</string>
<string name="unsupported_wc_version">Error de conexión: Esta dApp utiliza la versión 1.0 de Wallet Connect, que no es compatible. Asegúrese de que la dApp sea compatible con la versión 2.0 de Wallet Connect para conectarse correctamente.</string>
<string name="user_push_notification_agreement_argument_one">Manténgase actualizado con las últimas funciones y noticias</string>
@ -1260,7 +1261,7 @@
<string name="wallet_promo_banner_description">Accede a más de 13 000 criptomonedas. Compra, vende, intercambia y realiza staking con un solo toque.\nVincula hasta tres tarjetas para hacer copias de seguridad.</string>
<string name="wallet_promo_banner_title">Descubre Tangem Wallet</string>
<string name="wallet_settings_change_access_code_title">Cambiar código de acceso</string>
<string name="wallet_settings_push_notifications_description">Manténteinformado sobre las transacciones entrantes de la billetera y las actualizaciones de Tangem.</string>
<string name="wallet_settings_push_notifications_description">Manténgase informado sobre las transacciones entrantes de la billetera y las actualizaciones de Tangem.</string>
<string name="wallet_settings_push_notifications_title">Notificaciones de transacciones</string>
<string name="wallet_settings_set_access_code_title">Establecer código de acceso</string>
<string name="wallet_settings_title">Ajustes de la wallet</string>
@ -1297,7 +1298,7 @@
<string name="warning_express_notification_invalid_reserve_amount_title">El monto a recibir debe ser de al menos %s</string>
<string name="warning_express_pair_unavailable_message">Esto puede suceder porque el proveedor actualmente no puede operar con el par que usted seleccionó. Espere un momento e inténtelo de nuevo. (Código %s)</string>
<string name="warning_express_pair_unavailable_title">El par seleccionado no está disponible temporalmente</string>
<string name="warning_express_providers_fca_warning_description">Algunos proveedores no están autorizados por la Autoridad de Conducta Financiera (FCA) del Reino Unido. Deberías evitar tratar con ellos.</string>
<string name="warning_express_providers_fca_warning_description">Algunos proveedores no están autorizados por la Autoridad de Conducta Financiera del Reino Unido. Debe evitar tratar con ellos.</string>
<string name="warning_express_refresh_required_title">Servicio no disponible temporalmente</string>
<string name="warning_express_too_maximum_amount_title">La cantidad de tokens a intercambiar no debe exceder %s</string>
<string name="warning_express_too_minimal_amount_title">El monto a cambiar debe ser de al menos %s</string>
@ -1333,10 +1334,10 @@
<string name="warning_rate_app_message">Su opinión nos motiva a hacer Tangem Wallet aún mejor</string>
<string name="warning_rate_app_title">¿Disfrutando de Tangem?</string>
<string name="warning_receive_blocked_hedera_token_association_required_message">Deba asociar su token antes de recibir tokens</string>
<string name="warning_receive_blocked_token_trustline_required_message">Debes abrir una línea de confianza para tu token antes de recibirlo</string>
<string name="warning_receive_blocked_token_trustline_required_message">Debe abrir una trustline para su token antes de recibirlo</string>
<string name="warning_rent_fee_title">Se requiere tarifa de alquiler de red</string>
<string name="warning_seedphrase_action_required_title">Acción requerida</string>
<string name="warning_seedphrase_contacted_support">¿Te pusiste en contacto con el servicio de asistencia a través de la aplicación o por correo electrónico en los 7 días posteriores a la creación de la billetera? Si lo hiciste o no estás seguro, sigue y completa las instrucciones.</string>
<string name="warning_seedphrase_contacted_support">¿Se puso en contacto con el servicio de soporte a través de la app en los 7 días posteriores a la creación de la billetera? Si lo hiciste o no estás seguro, pulse en \"Sí\" y complete las instrucciones.</string>
<string name="warning_seedphrase_issue_answer_no">¡Gracias! ¡Todo listo! No se requieren más acciones.</string>
<string name="warning_seedphrase_issue_answer_yes">Ahora será redirigido al sitio web oficial de Tangem. Por favor, lea y siga las instrucciones allí indicadas.</string>
<string name="warning_seedphrase_issue_message">¿Alguna vez contactó al equipo de soporte de Tangem directamente desde esta aplicación?</string>
@ -1353,16 +1354,16 @@
<string name="warning_testnet_card_message">Esta es una tarjeta de Testnet. No puede procesar transacciones y solo deba usarse para pruebas y desarrollo.</string>
<string name="warning_testnet_card_title">Solo para fines de prueba</string>
<string name="warning_token_balance_not_updated">El saldo podría estar desactualizado. Actualice la página.</string>
<string name="warning_token_required_min_coin_reserve">No hay suficiente %1$s. Recarga tu %2$s cuenta para asociar este token</string>
<string name="warning_token_trustline_button_title">Habilitar línea de confianza</string>
<string name="warning_token_trustline_subtitle">Una línea de confianza debe estar habilitada para recibir este token. La red requiere un %1$s %2$s reserva.</string>
<string name="warning_token_trustline_title">Se requiere línea de confianza</string>
<string name="warning_token_required_min_coin_reserve">No hay suficiente %1$s. Recargue su cuenta %2$s para asociar este token</string>
<string name="warning_token_trustline_button_title">Habilitar Trustline</string>
<string name="warning_token_trustline_subtitle">Una trustline (línea de confianza) debe estar habilitada para recibir este token. La red requiere un %1$s %2$s reserva.</string>
<string name="warning_token_trustline_title">Se requiere trustline (línea de confianza)</string>
<string name="wc_alert_add_network_to_portfolio_description">La red requerida %s no está añadida a su portafolio. Añádala primero y luego continúe con la conexión.</string>
<string name="wc_alert_add_network_to_portfolio_title">Agregue red al portafolio</string>
<string name="wc_alert_audit_malicious_domain">Dominio malicioso</string>
<string name="wc_alert_audit_unknown_domain">Dominio desconocido</string>
<string name="wc_alert_connect_anyway">Conectarse de todas formas</string>
<string name="wc_alert_connection_timeout_description">Error de tiempo de espera. Por favor, inténtalo de nuevo más tarde.</string>
<string name="wc_alert_connection_timeout_description">Error de tiempo de espera. Por favor, inténtelo de nuevo más tarde.</string>
<string name="wc_alert_connection_timeout_title">Error al establecer WalletConnect</string>
<string name="wc_alert_domain_issues_description">Este dominio no puede ser verificado. Compruebe cuidadosamente la solicitud de aprobación.</string>
<string name="wc_alert_network_not_connected_description">Para continuar, vuelva a conectar su sesión de dApp con la red requerida %s.</string>
@ -1382,10 +1383,10 @@
<string name="wc_alert_unsupported_network_description">Esta red %s no es compatible con Tangem Wallet y no puede conectarse.</string>
<string name="wc_alert_unsupported_network_title">Red no compatible</string>
<string name="wc_alert_unsupported_networks_description">Actualmente, Tangem no es compatible con una red requerida por %s.</string>
<string name="wc_alert_unsupported_networks_title">Redes no compatibles</string>
<string name="wc_alert_unsupported_networks_title">Redes no soportadas</string>
<string name="wc_alert_verified_domain_description">Este dominio ha superado las verificaciones y se considera seguro, confiable y libre de amenazas conocidas o actividades sospechosas. </string>
<string name="wc_alert_verified_domain_title">Dominio verificado</string>
<string name="wc_alert_wrong_card_description">Se seleccionó una tarjeta o un anillo incorrectos en la app</string>
<string name="wc_alert_wrong_card_description">Se seleccionó una tarjeta o un anillo incorrectos en la App</string>
<string name="wc_alert_wrong_card_title">Tenemos algún tipo de problema</string>
<string name="wc_all_dapps_disconnected">Todas las dApps desconectadas</string>
<string name="wc_allow_to_spend">Permitir gastar</string>
@ -1414,22 +1415,22 @@
<string name="wc_disconnect_all_alert_desc">Todas las sesiones de dApp se desconectarán. Su billetera ya no estará vinculada a ninguna dApp.</string>
<string name="wc_disconnect_all_alert_title">Desconectar todas las dApps</string>
<string name="wc_errors_invalid_domain_subtitle">Intente emparejar nuevamente con una URI nueva</string>
<string name="wc_errors_invalid_domain_title">Dominio de dApp no válido</string>
<string name="wc_errors_invalid_domain_title">Dominio de dApp incorrecto</string>
<string name="wc_errors_no_blockchains_subtitle">%s no especifica ninguna blockchain, ni obligatoria ni opcional. Asegúrese de haber utilizado el URI correcto</string>
<string name="wc_errors_no_blockchains_title">Sin redes</string>
<string name="wc_errors_proposal_expired_subtitle">Por favor, genere una nueva URI e intente conectarse nuevamente</string>
<string name="wc_errors_proposal_expired_title">Propuesta de conexión caducada</string>
<string name="wc_estimated_wallet_changes">Cambios estimados en la billetera</string>
<string name="wc_estimated_wallet_changes_not_simulated">La transacción no ha podido ser simulada. Por favor, proceda con precaución.</string>
<string name="wc_estimation_is_not_supported">La estimación no es compatible con %s</string>
<string name="wc_estimation_is_not_supported">La estimación no está soportada para %s</string>
<string name="wc_fee_suggested">Sugerido por %s</string>
<string name="wc_insufficient_warning_subtitle">Recargue su saldo para cubrir la tarifa de red</string>
<string name="wc_insufficient_warning_title">Insuficiente %1$s</string>
<string name="wc_malicious_transaction">Transacción maliciosa</string>
<string name="wc_missing_required_network_description">Añada la red %s a su perfil para esta billetera</string>
<string name="wc_missing_required_network_description">Añada la red %s a su portafolio para esta billetera</string>
<string name="wc_missing_required_network_title">La billetera no tiene las redes requeridas</string>
<string name="wc_new_connection">Nueva conexión</string>
<string name="wc_no_sessions_desc">Conecta tu billetera a diferentes dApps</string>
<string name="wc_no_sessions_desc">Conecte su billetera a diferentes dApps</string>
<string name="wc_no_sessions_title">Sin sesiones</string>
<string name="wc_no_wallet_changes_detected">No se han detectado cambios en la billetera</string>
<string name="wc_notification_security_risk_subtitle">Se han detectado riesgos potenciales o comportamiento malicioso. Conectarse o firmar transacciones puede resultar en la pérdida de fondos.</string>
@ -1437,7 +1438,7 @@
<string name="wc_qr_scan_hint">Abra la aplicación Web3 y elija la opción WalletConnect</string>
<string name="wc_request_from">Solicitud de</string>
<string name="wc_send_anyway">Firmar de todos modos</string>
<string name="wc_signature_type">Tipo de firma</string>
<string name="wc_signature_type">Tipo de Firma</string>
<string name="wc_specify_networks_subtitle">Se requiere al menos una red para la conexión dApp</string>
<string name="wc_specify_networks_title">Especificar las redes seleccionadas</string>
<string name="wc_successfully_signed">Firmado correctamente</string>
@ -1461,6 +1462,6 @@
<string name="welcome_unlock_description">Use %s o escanee una tarjeta/anillo para acceder a la app</string>
<string name="welcome_unlock_title">¡Bienvenido de nuevo!</string>
<string name="xtz_withdrawal_message_ignore">No, enviar todo</string>
<string name="xtz_withdrawal_message_reduce">Réduire de %s XTZ</string>
<string name="xtz_withdrawal_message_warning">Para evitar pagar una comisión mayor la próxima vez que recargue su billetera, reduzca el monto en %s</string>
<string name="xtz_withdrawal_message_reduce">Reducir en %s XTZ</string>
<string name="xtz_withdrawal_message_warning">Para evitar pagar una comisión mayor la próxima vez que recargue su billetera, reduzca el importe en %s XTZ</string>
</resources>

View file

@ -198,7 +198,7 @@
<string name="common_origin_ring">Bague principale</string>
<string name="common_passphrase">Passphrase</string>
<string name="common_paste">Coller</string>
<string name="common_privacy_policy">Politique de confidentialité</string>
<string name="common_privacy_policy">Politique de confidentialité</string>
<string name="common_range">%1$s-%2$s</string>
<string name="common_range_with_space">%1$s — %2$s</string>
<string name="common_read_more">En savoir plus</string>
@ -234,7 +234,7 @@
<string name="common_supported_networks">Réseaux pris en charge</string>
<string name="common_swap">Échanger</string>
<string name="common_terms_and_conditions">termes et conditions</string>
<string name="common_terms_of_use">Conditions d\'utilisation</string>
<string name="common_terms_of_use">Conditions d\'utilisation</string>
<string name="common_today">Aujourd\'hui</string>
<plurals name="common_tokens_count">
<item quantity="one">%d jeton</item>
@ -311,6 +311,7 @@
<string name="domain_receive_assets_navigation_title">Recevoir des actifs</string>
<string name="domain_receive_assets_network_name_address">%s adresse</string>
<string name="domain_receive_assets_onboarding_description">Lenvoi dactifs sur dautres réseaux entraînera une perte définitive.</string>
<string name="domain_receive_assets_onboarding_network_name">%s réseau</string>
<string name="domain_receive_assets_onboarding_title">Envoyez des fonds en utilisant uniquement</string>
<string name="email_preface_wc_error">Bonjour équipe de support, jai rencontré une erreur avec le code : %s</string>
<string name="email_subject_wc_error">Erreur WalletConnect</string>
@ -365,7 +366,7 @@
<string name="express_fetch_best_rates">En cherche des meilleurs taux</string>
<string name="express_floating_rate">Taux flottant</string>
<string name="express_legal_one_placeholder">En utilisant la fonctionnalité d\'échange, vous acceptez les %s</string>
<string name="express_legal_two_placeholders">En utilisant la fonctionnalité d\'échange, vous acceptez les conditions %1$s et %2$s du fournisseur</string>
<string name="express_legal_two_placeholders">En utilisant la fonctionnalité d\'échange, vous acceptez les conditions %1$s et %2$s du fournisseur.</string>
<string name="express_more_providers_soon">D\'autres fournisseurs arriveront bientôt.\nRestez branchés !</string>
<string name="express_provider">Fournisseur</string>
<string name="express_provider_best_rate">Meilleur taux</string>
@ -908,7 +909,7 @@
<string name="send_sending">En cours d\'envoi</string>
<string name="send_summary_tap_hint">Appuyez sur n\'importe quel champ pour le modifier</string>
<string name="send_summary_title">Envoyer %s</string>
<string name="send_summary_transaction_description">Vous envoyez **%1$s** incluant des frais de réseau de %2$s</string>
<string name="send_summary_transaction_description">Vous envoyez **%1$s** incluant des frais de réseau de %2$s.</string>
<string name="send_summary_transaction_description_no_fiat_fee">Vous envoyez **%1$s** et %2$s</string>
<string name="send_summary_transaction_description_prefix">Vous envoyez **%1$s**</string>
<string name="send_summary_transaction_description_suffix_fee_covered">les frais de réseau seront couverts en utilisant %1$s énergie</string>
@ -923,11 +924,20 @@
<string name="send_validation_invalid_amount">Montant invalide</string>
<string name="send_validation_invalid_fee">Les frais de commissions dépassent le solde</string>
<string name="send_validation_invalid_total">Le total dépasse le solde</string>
<string name="send_with_swap_change_token_alert_message">Êtes-vous sûr de vouloir modifier le token de réception ? Cela réinitialisera les données que vous avez saisies précédemment.</string>
<string name="send_with_swap_change_token_alert_title">Changement de token</string>
<string name="send_with_swap_confirm_title">Échanger et envoyer</string>
<string name="send_with_swap_convert_token_alert_message">Poursuivre l\'échange ? Cela effacera vos données précédentes.</string>
<string name="send_with_swap_convert_token_alert_title">Confirmer la conversion</string>
<string name="send_with_swap_correct_recipient_network_notification_message">L\'envoi de toute autre crypto entraînera sa perte irréversible.</string>
<string name="send_with_swap_correct_recipient_network_notification_title">Sélectionnez le réseau destinataire approprié.</string>
<string name="send_with_swap_notification_text">Envoyez n\'importe quel jeton et nous le convertirons en cours de route. Votre destinataire reçoit exactement ce dont il a besoin, en toute simplicité.</string>
<string name="send_with_swap_recipient_amount_success_title">Le destinataire recevra</string>
<string name="send_with_swap_recipient_amount_text">Un destinataire sera envoyé</string>
<string name="send_with_swap_recipient_amount_title">Montant à recevoir</string>
<string name="send_with_swap_recipient_get_amount">Le destinataire reçoit %s</string>
<string name="send_with_swap_remove_convert_alert_message">Êtes-vous sûr de vouloir annuler la conversion ? Vos données précédentes seront effacées.</string>
<string name="send_with_swap_remove_convert_alert_title">Supprimer la conversion</string>
<string name="send_with_swap_title">Envoyer avec swap</string>
<string name="sent_transaction_sent_title">Transaction envoyée</string>
<string name="settings_card_settings_footer">Scannez la carte/ bague que vous souhaitez configurer.</string>

View file

@ -4,6 +4,7 @@
<string name="account_details_archive_description">Вы архивируете свой аккаунт, но в любое время можете вернуть его обратно</string>
<string name="account_form_placeholder_edit_account">Аккаунт</string>
<string name="account_form_placeholder_new_account">Новый аккаунт</string>
<string name="account_main_account_title">Основной аккаунт</string>
<string name="account_unsaved_dialog_action_first">Продолжить редактирование</string>
<string name="account_unsaved_dialog_title">Несохраненные изменения</string>
<string name="action_buttons_buy_empty_search_message">Не нашли свой токен? Перейдите в раздел «Рынок» на главной странице и добавьте его в свой портфель для покупки.</string>
@ -204,7 +205,7 @@
<string name="common_origin_ring">Основное кольцо</string>
<string name="common_passphrase">Парольная фраза</string>
<string name="common_paste">Вставить</string>
<string name="common_privacy_policy">Политикой конфиденциальности</string>
<string name="common_privacy_policy">Политикой конфиденциальности</string>
<string name="common_range">%1$s-%2$s</string>
<string name="common_range_with_space">%1$s — %2$s</string>
<string name="common_read_more">Подробнее</string>
@ -237,7 +238,7 @@
<string name="common_support">Поддержка</string>
<string name="common_swap">Обменять</string>
<string name="common_terms_and_conditions">условия участия</string>
<string name="common_terms_of_use">Условиями использования</string>
<string name="common_terms_of_use">Условиями использования</string>
<string name="common_today">Сегодня</string>
<plurals name="common_tokens_count">
<item quantity="one">%d токен</item>
@ -316,7 +317,7 @@
<string name="domain_receive_assets_navigation_title">Получить активы</string>
<string name="domain_receive_assets_network_name_address">%s адрес</string>
<string name="domain_receive_assets_onboarding_description">Отправка средств в другой сети может повлечь потерю средств.</string>
<string name="domain_receive_assets_onboarding_network_name">%s сети</string>
<string name="domain_receive_assets_onboarding_network_name">%s сеть</string>
<string name="domain_receive_assets_onboarding_title">Отправляйте средства, используя только</string>
<string name="email_preface_wc_error">Привет, команда поддержки, у меня возникла ошибка с кодом: %s</string>
<string name="email_subject_wc_error">Ошибка WalletConnect</string>
@ -337,7 +338,7 @@
<string name="express_exchange_by">Обмен через %s</string>
<string name="express_exchange_notification_failed_text">Чтобы вернуть ваши деньги, посетите сайт провайдера</string>
<string name="express_exchange_notification_failed_title">Операция не выполнена провайдером</string>
<string name="express_exchange_notification_long_transaction_time_text">Ваш обмен занимает больше времени, чем ожидалось. Пожалуйста, обратитесь в службу поддержки провайдера для уточнения.</string>
<string name="express_exchange_notification_long_transaction_time_text">Ваш обмен занимает больше времени, чем обычно, но ваши средства полностью в безопасности и будут доставлены. Если возникли вопросы, вы всегда можете связаться с поддержкой провайдера.</string>
<string name="express_exchange_notification_refund_text">Отправленные средства были возвращены в %1$s на ваш кошелек в соответствии с правилами OKX или моста обмена. %2$s</string>
<string name="express_exchange_notification_refund_title">Сумма была возвращена в %1$s (%2$s сети)</string>
<string name="express_exchange_notification_verification_text">Посетите сайт провайдера для проверки</string>
@ -370,7 +371,7 @@
<string name="express_fetch_best_rates">Получение наилучших курсов...</string>
<string name="express_floating_rate">Плавающая ставка</string>
<string name="express_legal_one_placeholder">Пользуясь сервисом, вы соглашаетесь с %s</string>
<string name="express_legal_two_placeholders">Пользуясь сервисом, вы соглашаетесь с %1$s и %2$s</string>
<string name="express_legal_two_placeholders">Пользуясь сервисом, вы соглашаетесь с %1$s и %2$s.</string>
<string name="express_more_providers_soon">Больше провайдеров на подходе.\nСледите за обновлениями!</string>
<string name="express_provider">Провайдер</string>
<string name="express_provider_best_rate">Лучший курс</string>
@ -929,7 +930,7 @@
<string name="send_sending">Отправка</string>
<string name="send_summary_tap_hint">Нажмите на любое поле, чтобы изменить его</string>
<string name="send_summary_title">Отправка %s</string>
<string name="send_summary_transaction_description">Вы отправляете **%1$s**, включая комиссию сети %2$s</string>
<string name="send_summary_transaction_description">Вы отправляете **%1$s**, включая комиссию сети %2$s.</string>
<string name="send_summary_transaction_description_no_fiat_fee">Вы отправляете **%1$s** и %2$s</string>
<string name="send_summary_transaction_description_prefix">Вы отправляете **%1$s**</string>
<string name="send_summary_transaction_description_suffix_fee_covered">Комиссия сети будет покрыта за счет использования %1$s энергии</string>

View file

@ -173,6 +173,7 @@
<string name="common_generate_addresses">Синхронізувати адреси</string>
<string name="common_go_to_provider">Перейти до провайдера</string>
<string name="common_go_to_token">Перейти до токену</string>
<string name="common_got_it">Зrozуміло</string>
<string name="common_hide">Приховати</string>
<string name="common_hour">година</string>
<string name="common_import">Імпортувати</string>
@ -196,7 +197,7 @@
<string name="common_origin_ring">Основне кільце</string>
<string name="common_passphrase">Парольна фраза</string>
<string name="common_paste">Вставити</string>
<string name="common_privacy_policy">Політикою конфіденційності</string>
<string name="common_privacy_policy">Політикою конфіденційності</string>
<string name="common_range">%1$s-%2$s</string>
<string name="common_range_with_space">%1$s — %2$s</string>
<string name="common_read_more">Детальніше</string>
@ -230,7 +231,7 @@
<string name="common_support">Підтримка</string>
<string name="common_swap">Обмін</string>
<string name="common_terms_and_conditions">умови участі</string>
<string name="common_terms_of_use">Умовами використання</string>
<string name="common_terms_of_use">Умовами використання</string>
<string name="common_today">Сьогодні</string>
<plurals name="common_tokens_count">
<item quantity="one">%d токен</item>
@ -307,6 +308,7 @@
<string name="domain_receive_assets_navigation_title">Отримати активи</string>
<string name="domain_receive_assets_network_name_address">%s адреса</string>
<string name="domain_receive_assets_onboarding_description">Надсилання активів в інші мережі призведе до безповоротної втрати.</string>
<string name="domain_receive_assets_onboarding_network_name">%s мережа</string>
<string name="domain_receive_assets_onboarding_title">Надсилайте кошти, використовуючи лише</string>
<string name="email_preface_wc_error">Привіт, команда підтримки, я зіткнувся з помилкою з кодом: %s</string>
<string name="email_subject_wc_error">Помилка WalletConnect</string>
@ -327,7 +329,7 @@
<string name="express_exchange_by">Обмін через %s</string>
<string name="express_exchange_notification_failed_text">Щоб повернути ваші кошти, відвідайте сайт провайдера</string>
<string name="express_exchange_notification_failed_title">Операція не виконана провайдером</string>
<string name="express_exchange_notification_long_transaction_time_text">Ваш обмін триває довше, ніж очікувалося. Будь ласка, зверніться до служби підтримки постачальника послуг, для уточнення.</string>
<string name="express_exchange_notification_long_transaction_time_text">Ваш обмін триває довше, ніж зазвичай, але ваші кошти повністю в безпеці та будуть доставлені. Якщо ви хвилюєтесь, ви завжди можете звернутися до служби підтримки провайдера.</string>
<string name="express_exchange_notification_long_transaction_time_title">Тривалий час транзакції</string>
<string name="express_exchange_notification_refund_text">Сума транзакції була повернута в %1$s на ваш гаманець відповідно до правил OKX або мосту обміну. %2$s</string>
<string name="express_exchange_notification_refund_title">Сума була повернута в %1$s (%2$s мережі)</string>
@ -361,7 +363,7 @@
<string name="express_fetch_best_rates">Шукаємо найвигідніший курс...</string>
<string name="express_floating_rate">Плаваюча ставка</string>
<string name="express_legal_one_placeholder">Використовуючи сервіс обміну, ви погоджуєтеся з його %s</string>
<string name="express_legal_two_placeholders">Використовуючи сервіс обміну, ви погоджуєтеся з його %1$s та %2$s</string>
<string name="express_legal_two_placeholders">Використовуючи сервіс обміну, ви погоджуєтеся з його %1$s та %2$s.</string>
<string name="express_more_providers_soon">Незабаром з\'являться нові провайдери.\nСлідкуйте за новинами!</string>
<string name="express_provider">Провайдер</string>
<string name="express_provider_best_rate">Найкращий курс</string>
@ -910,7 +912,7 @@
<string name="send_sending">Надсилання...</string>
<string name="send_summary_tap_hint">Торкніться будь-якого поля, щоб змінити його</string>
<string name="send_summary_title">Надіслати %s</string>
<string name="send_summary_transaction_description">Ви надсилаєте **%1$s**, включно з комісію мережі %2$s</string>
<string name="send_summary_transaction_description">Ви надсилаєте **%1$s**, включно з комісію мережі %2$s.</string>
<string name="send_summary_transaction_description_no_fiat_fee">Ви надсилаєте **%1$s** і %2$s</string>
<string name="send_summary_transaction_description_prefix">Ви надсилаєте **%1$s**</string>
<string name="send_summary_transaction_description_suffix_fee_covered">комісія мережі буде покрита, використовуючи %1$s енергію</string>

View file

@ -35,6 +35,7 @@
<string name="account_form_title_create">Add account</string>
<string name="account_form_title_edit">Edit account</string>
<string name="account_label_tokens_info">%1$s in %2$s</string>
<string name="account_main_account_title">Main account</string>
<string name="account_recover_success_message">Account recovered</string>
<string name="account_reorder_description">Long tap on an account to reorder accounts</string>
<string name="account_unsaved_dialog_action_first">Keep Editing</string>
@ -182,6 +183,7 @@
<string name="common_allow">Allow</string>
<string name="common_amount">Amount</string>
<string name="common_analytics">Analytics</string>
<string name="common_and">and</string>
<string name="common_apply">Apply</string>
<string name="common_approval">Approval</string>
<string name="common_approve">Approve</string>
@ -255,6 +257,7 @@
<string name="common_import">Import</string>
<string name="common_in_progress">In progress</string>
<string name="common_later">Later</string>
<string name="common_learn_more">Learn more</string>
<string name="common_left">%1$s left</string>
<string name="common_legacy_bitcoin_address">Legacy Bitcoin</string>
<string name="common_locked">Locked</string>
@ -280,7 +283,7 @@
<string name="common_origin_ring">Primary ring</string>
<string name="common_passphrase">Passphrase</string>
<string name="common_paste">Paste</string>
<string name="common_privacy_policy">Privacy Policy</string>
<string name="common_privacy_policy">Privacy Policy</string>
<string name="common_range">%1$s-%2$s</string>
<string name="common_range_with_space">%1$s — %2$s</string>
<string name="common_read_more">Read more</string>
@ -319,7 +322,7 @@
<string name="common_tangem">Tangem</string>
<string name="common_tangem_wallet">Tangem Wallet</string>
<string name="common_terms_and_conditions">terms and conditions</string>
<string name="common_terms_of_use">Terms of Use</string>
<string name="common_terms_of_use">Terms of Use</string>
<string name="common_today">Today</string>
<plurals name="common_tokens_count">
<item quantity="one">%d token</item>
@ -419,7 +422,7 @@
<string name="express_exchange_by">Exchange by %s</string>
<string name="express_exchange_notification_failed_text">Visit providers website to refund your money</string>
<string name="express_exchange_notification_failed_title">Operation failed by provider</string>
<string name="express_exchange_notification_long_transaction_time_text">Your swap is taking longer than expected. Please go to provider support for assistance.</string>
<string name="express_exchange_notification_long_transaction_time_text">Your swap is taking longer than usual, but your funds are completely safe and will be delivered. For any questions, you can contact the providers support team.</string>
<string name="express_exchange_notification_long_transaction_time_title">Long transaction time</string>
<string name="express_exchange_notification_refund_text">The transaction amount was refunded in %1$s to your wallet due to OKX or bridge rules. %2$s</string>
<string name="express_exchange_notification_refund_title">The amount was refunded in %1$s (%2$s network)</string>
@ -453,7 +456,7 @@
<string name="express_fetch_best_rates">Fetching current rates...</string>
<string name="express_floating_rate">Floating rate</string>
<string name="express_legal_one_placeholder">By using swap functionality, you agree with providers %s</string>
<string name="express_legal_two_placeholders">By using swap functionality, you agree with providers %1$s and %2$s</string>
<string name="express_legal_two_placeholders">By using swap functionality, you agree with providers %1$s and %2$s.</string>
<string name="express_more_providers_soon">More providers will be available soon</string>
<string name="express_provider">Provider</string>
<string name="express_provider_best_rate">Best rate</string>
@ -504,6 +507,7 @@
<string name="home_button_create_new_wallet">Create New Wallet</string>
<string name="home_button_order">Order Tangem</string>
<string name="home_button_scan">Scan Tangem</string>
<string name="hot_access_code_set_biometric_ask">Do you want to allow “Tangem” to use biometric authentication? To confirm your identity and open the app</string>
<string name="hot_crypto_add_token_subtitle">to %s</string>
<string name="hot_crypto_token_network">On %s network</string>
<string name="hw_access_code_create_alert_title">Are you sure you want to exit the access code creation process?</string>
@ -800,6 +804,7 @@
<string name="onboarding_linking_error_card_with_wallets">Another wallet has already been created on the card you\'re trying to add. If you have funds in this wallet, please withdraw it and then reset this card and add it as a backup.</string>
<string name="onboarding_navbar_save_wallet">Save your wallet</string>
<string name="onboarding_navbar_title_creating_backup">Creating a backup</string>
<string name="onboarding_navbar_upgrade_wallet_biometrics">Use biometrics</string>
<string name="onboarding_seed_button_read_more">Read more about seed phrase</string>
<plurals name="onboarding_seed_generate_message_words_count">
<item quantity="one"></item>
@ -853,6 +858,7 @@
<string name="onboarding_wallet_info_title_fourth">Access code restore</string>
<string name="onboarding_wallet_info_title_second">Identical cards</string>
<string name="onboarding_wallet_info_title_third">Access code</string>
<string name="onramp_all_offers_button_title">All offers</string>
<string name="onramp_avaiable_with_payment_methods">Available with %s</string>
<string name="onramp_choose_provider_title_hint">Providers facilitate transactions</string>
<string name="onramp_country_search">Search by country</string>
@ -860,13 +866,20 @@
<string name="onramp_currency_other">Other currencies</string>
<string name="onramp_currency_popular">Popular Fiats</string>
<string name="onramp_currency_search">Search by currency</string>
<string name="onramp_instant_status">Instant</string>
<string name="onramp_legal">By using onramp functionality, you agree with providers %1$s and %2$s</string>
<string name="onramp_max_amount_restriction">The purchase amount should be no more than %s</string>
<string name="onramp_min_amount_restriction">The amount to buy must be at least %s</string>
<string name="onramp_no_available_providers">No available providers for this currency</string>
<string name="onramp_offer_type_fastet">Fastest</string>
<string name="onramp_pay_with">Pay with</string>
<string name="onramp_payment_method_subtitle">Payment method</string>
<string name="onramp_provider_max_amount">Available up to %s</string>
<string name="onramp_provider_min_amount">Available from %s</string>
<string name="onramp_providers_count">%d providers</string>
<string name="onramp_providers_subtitle">Providers</string>
<string name="onramp_recently_used_title">Recently used</string>
<string name="onramp_recommended_title">Recommended</string>
<string name="onramp_redirecting_to_provider_subtitle">You will be able to complete your transaction on the third-party provider, %s</string>
<string name="onramp_redirecting_to_provider_title">Redirecting to %s...</string>
<string name="onramp_residency_bottomsheet_country_not_supported">Our services are not available in this country</string>
@ -875,6 +888,12 @@
<string name="onramp_settings_residence_description">Please select the correct country to ensure accurate payment options and services.</string>
<string name="onramp_settings_title">Settings</string>
<string name="onramp_statuses_view_footer">You can close this screen and check the transaction status on the token details screen.</string>
<plurals name="onramp_timing_days">
<item quantity="one">up to %d day</item>
<item quantity="other">up to %d days</item>
</plurals>
<string name="onramp_timing_minutes">%s min</string>
<string name="onramp_title_you_get">You get</string>
<string name="onramp_transaction_status_footer_text">You can close this screen and check the transaction status on the token details screen.</string>
<string name="onramp_via">Via</string>
<string name="onramp_you_will_pay_title">You will pay</string>
@ -1043,7 +1062,7 @@
<string name="send_sending">Sending...</string>
<string name="send_summary_tap_hint">Tap any field to change it</string>
<string name="send_summary_title">Send %s</string>
<string name="send_summary_transaction_description">You are sending **%1$s** including a network fee of %2$s</string>
<string name="send_summary_transaction_description">You are sending **%1$s** including a network fee of %2$s.</string>
<string name="send_summary_transaction_description_no_fiat_fee">You are sending **%1$s** and %2$s</string>
<string name="send_summary_transaction_description_prefix">You are sending **%1$s**</string>
<string name="send_summary_transaction_description_suffix_fee_covered">network fee will be covered by using %1$s energy</string>
@ -1668,4 +1687,68 @@
<string name="xtz_withdrawal_message_ignore">No, send all</string>
<string name="xtz_withdrawal_message_reduce">Reduce by %s XTZ</string>
<string name="xtz_withdrawal_message_warning">To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ</string>
<string name="yield_module_approve_needed_notification_cta">Give Approve</string>
<string name="yield_module_approve_needed_notification_description">Something went wrong with your previous approval, so we need a new one. Choose how youd like to proceed.</string>
<string name="yield_module_approve_needed_notification_title">Approve nedeed</string>
<string name="yield_module_approve_sheet_fee_note">The fee will be taken out, and your assets will be lent again.</string>
<string name="yield_module_approve_sheet_subtitle">To continue earning, approval is required.</string>
<string name="yield_module_approve_sheet_title">Confirm approval</string>
<string name="yield_module_balance_info_sheet_subtitle">Text about your money in balance</string>
<string name="yield_module_balance_info_sheet_title">Your %s is deposited in Aave</string>
<string name="yield_module_earn_badge">Earn %s%</string>
<string name="yield_module_earn_sheet_available_title">Available</string>
<string name="yield_module_earn_sheet_current_apy_title">Current APY</string>
<string name="yield_module_earn_sheet_my_funds_title">My Funds</string>
<string name="yield_module_earn_sheet_provider_description">Your %1$s is now deposited in Aave and earning interest. You hold a%2$s token, which represents your balance and grows over time. When you top up, funds go to Aave to earn interest, minus a transaction fee.</string>
<string name="yield_module_earn_sheet_read_more">Read more</string>
<string name="yield_module_earn_sheet_status_active">Active</string>
<string name="yield_module_earn_sheet_stop_earning_button_title">Stop earning</string>
<string name="yield_module_earn_sheet_title">Earn</string>
<string name="yield_module_earn_sheet_total_earnings_title">Total earnings</string>
<string name="yield_module_earn_sheet_transfers_mode">Automatic</string>
<string name="yield_module_earn_sheet_transfers_title">Transfers to Aave</string>
<string name="yield_module_explore_sheet_description">Text explaining that your savings are located in the protocol</string>
<string name="yield_module_explore_sheet_explore_aave_button_title">Explore Aave</string>
<string name="yield_module_explore_sheet_explore_default_button_title">Explore default</string>
<string name="yield_module_explore_sheet_title">Your %s is deposited in Aave </string>
<string name="yield_module_fee_policy_sheet_current_fee_note">This is the current supply fee on %s. The live cost will be shown on the Receive Screen.</string>
<string name="yield_module_fee_policy_sheet_current_fee_title">Current fee</string>
<string name="yield_module_fee_policy_sheet_description">All future %s top-ups will be supplied to Aave automatically, with the transaction fee deducted.</string>
<string name="yield_module_fee_policy_sheet_max_fee_note">If network fees rise above maximum fee, the transaction wont go through until they decrease. You can change this limit later.</string>
<string name="yield_module_fee_policy_sheet_max_fee_title">Maximum fee</string>
<string name="yield_module_fee_policy_sheet_title">Fee policy</string>
<string name="yield_module_main_view_approve_notification_description">Write description here. In one, two or three lines will be awesome.</string>
<string name="yield_module_main_view_approve_notification_title">Some token approve needed</string>
<string name="yield_module_promo_screen_auto_balance_subtitle">Every top-up of your account will be lended to Aave automatically.</string>
<string name="yield_module_promo_screen_auto_balance_title">Your balance works automatically</string>
<string name="yield_module_promo_screen_cash_out_subtitle">Send, swap, or sell your funds instantly, anytime you want.</string>
<string name="yield_module_promo_screen_cash_out_title">Cash out instantly</string>
<string name="yield_module_promo_screen_how_it_works_button_title">How it works?</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave is trusted by millions worldwide. Total lended value is $10.4B.</string>
<string name="yield_module_promo_screen_self_custodial_title">Decentralized and self-custodial</string>
<string name="yield_module_promo_screen_terms_disclaimer">By using service, you agree with provider</string>
<string name="yield_module_promo_screen_title">Maximize your savings</string>
<string name="yield_module_promo_screen_variable_rate_info">Aave • Variable Interest Rate</string>
<string name="yield_module_provider">Aave</string>
<string name="yield_module_rate_info_sheet_chart_average">Avg %s</string>
<string name="yield_module_rate_info_sheet_chart_title">Last year returns</string>
<string name="yield_module_rate_info_sheet_description">Current interest rate is always variable and automatically computed by AAVE on-chain smart-contract based on real-time supply and demand.</string>
<string name="yield_module_rate_info_sheet_title">Interest rate is variable</string>
<string name="yield_module_receive_sheet_description">When you top up, your funds will be automatically sent to Aave to start earning interest. A small fee equal to %s will be deducted to cover the transaction.</string>
<string name="yield_module_start_earning_sheet_bottom_button_title">Start earning</string>
<string name="yield_module_start_earning_sheet_description">Your %s will be supplied to Aave and will stay instantly available</string>
<string name="yield_module_start_earning_sheet_fee_policy">See fee policy</string>
<string name="yield_module_start_earning_sheet_network_fee_title">Network fee</string>
<string name="yield_module_start_earning_sheet_next_deposits">Your next deposits will be automatically supplied to Aave.</string>
<string name="yield_module_start_earning_sheet_title">Start earning</string>
<string name="yield_module_stop_earning_sheet_description">Turning off will withdraw your funds from Aave, return them to %s in your wallet, and stop earning rewards.</string>
<string name="yield_module_stop_earning_sheet_fee_note">The network fee will be deducted from the amount you withdraw.</string>
<string name="yield_module_stop_earning_sheet_title">Stop earning</string>
<string name="yield_module_token_details_earn_notification_apy">APY</string>
<string name="yield_module_token_details_earn_notification_description">Make your money work — earn interest on your balance.</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_title">Earning on your balance</string>
<string name="yield_module_token_details_earn_notification_processing">Processing your deposit</string>
<string name="yield_module_token_details_earn_notification_title">Earn %s% per year</string>
<string name="yield_module_unable_to_cover_fee_description">Deposit some %1$s %2$s to cover the network fee for transactions</string>
<string name="yield_module_unable_to_cover_fee_title">Unable to cover %s fee</string>
</resources>

View file

@ -29,15 +29,15 @@ internal class DefaultSettingsRepository(
private val userCountryFlow = MutableStateFlow<UserCountry?>(value = null)
override suspend fun shouldShowSaveUserWalletScreen(): Boolean {
override suspend fun shouldShowAskBiometry(): Boolean {
return appPreferencesStore.getSyncOrDefault(
key = PreferencesKeys.SHOULD_SHOW_SAVE_USER_WALLET_SCREEN_KEY,
key = PreferencesKeys.SHOULD_SHOW_ASK_BIOMETRY_KEY,
default = true,
)
}
override suspend fun setShouldShowSaveUserWalletScreen(value: Boolean) {
appPreferencesStore.store(key = PreferencesKeys.SHOULD_SHOW_SAVE_USER_WALLET_SCREEN_KEY, value = value)
override suspend fun setShouldShowAskBiometry(value: Boolean) {
appPreferencesStore.store(key = PreferencesKeys.SHOULD_SHOW_ASK_BIOMETRY_KEY, value = value)
}
override suspend fun isWalletScrollPreviewEnabled(): Boolean {

View file

@ -3,13 +3,13 @@ package com.tangem.domain.settings
import arrow.core.Either
import com.tangem.domain.settings.repositories.SettingsRepository
class SetSaveWalletScreenShownUseCase(
class SetAskBiometryShownUseCase(
private val settingsRepository: SettingsRepository,
) {
suspend operator fun invoke(): Either<Throwable, Unit> {
return Either.catch {
settingsRepository.setShouldShowSaveUserWalletScreen(value = false)
settingsRepository.setShouldShowAskBiometry(value = false)
}
}
}

View file

@ -2,7 +2,7 @@ package com.tangem.domain.settings
import com.tangem.domain.settings.repositories.SettingsRepository
class ShouldShowSaveWalletScreenUseCase(private val settingsRepository: SettingsRepository) {
class ShouldShowAskBiometryUseCase(private val settingsRepository: SettingsRepository) {
suspend operator fun invoke(): Boolean = settingsRepository.shouldShowSaveUserWalletScreen()
suspend operator fun invoke(): Boolean = settingsRepository.shouldShowAskBiometry()
}

View file

@ -7,9 +7,9 @@ import kotlinx.coroutines.flow.StateFlow
@Suppress("TooManyFunctions")
interface SettingsRepository {
suspend fun shouldShowSaveUserWalletScreen(): Boolean
suspend fun shouldShowAskBiometry(): Boolean
suspend fun setShouldShowSaveUserWalletScreen(value: Boolean)
suspend fun setShouldShowAskBiometry(value: Boolean)
suspend fun isWalletScrollPreviewEnabled(): Boolean

View file

@ -15,7 +15,7 @@ import com.tangem.core.ui.message.SnackbarMessage
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.core.wallets.UserWalletsListRepository
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.settings.SetSaveWalletScreenShownUseCase
import com.tangem.domain.settings.SetAskBiometryShownUseCase
import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
@ -39,7 +39,7 @@ import javax.inject.Inject
internal class AskBiometryModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
paramsContainer: ParamsContainer,
private val setSaveWalletScreenShownUseCase: SetSaveWalletScreenShownUseCase,
private val setAskBiometryShownUseCase: SetAskBiometryShownUseCase,
private val settingsRepository: SettingsRepository,
private val tangemSdkManager: TangemSdkManager,
private val getSelectedWalletUseCase: GetSelectedWalletUseCase,
@ -66,7 +66,7 @@ internal class AskBiometryModel @Inject constructor(
init {
modelScope.launch {
setSaveWalletScreenShownUseCase()
setAskBiometryShownUseCase()
}
}

View file

@ -48,7 +48,7 @@ internal class UserWalletListModel @Inject constructor(
private val userWalletsFetcher = userWalletsFetcherFactory.create(
messageSender = messageSender,
onlyMultiCurrency = false,
authMode = false,
isAuthMode = false,
onWalletClick = { userWalletId -> router.push(AppRoute.WalletSettings(userWalletId)) },
)

View file

@ -5,12 +5,20 @@ import arrow.core.getOrElse
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.EventMessageAction
import com.tangem.domain.core.wallets.UserWalletsListRepository
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.settings.CanUseBiometryUseCase
import com.tangem.domain.settings.SetAskBiometryShownUseCase
import com.tangem.domain.settings.ShouldShowAskBiometryUseCase
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.features.hotwallet.accesscode.entity.AccessCodeUM
import com.tangem.features.hotwallet.impl.R
import com.tangem.hot.sdk.TangemHotSdk
import com.tangem.hot.sdk.model.HotAuth
import com.tangem.hot.sdk.model.UnlockHotWallet
@ -19,9 +27,11 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import timber.log.Timber
import javax.inject.Inject
@Suppress("LongParameterList")
@Stable
@ModelScoped
internal class AccessCodeModel @Inject constructor(
@ -31,6 +41,10 @@ internal class AccessCodeModel @Inject constructor(
private val userWalletsListRepository: UserWalletsListRepository,
private val walletsRepository: WalletsRepository,
private val tangemHotSdk: TangemHotSdk,
private val shouldShowAskBiometryUseCase: ShouldShowAskBiometryUseCase,
private val setAskBiometryShownUseCase: SetAskBiometryShownUseCase,
private val canUseBiometryUseCase: CanUseBiometryUseCase,
private val uiMessageSender: UiMessageSender,
) : Model() {
private val params = paramsContainer.require<AccessCodeComponent.Params>()
@ -87,6 +101,8 @@ internal class AccessCodeModel @Inject constructor(
auth = HotAuth.Password(accessCode.toCharArray()),
)
tryToAskForBiometry()
if (walletsRepository.requireAccessCode().not()) {
updatedHotWalletId = tangemHotSdk.changeAuth(
unlockHotWallet = UnlockHotWallet(
@ -127,4 +143,49 @@ internal class AccessCodeModel @Inject constructor(
}
}
}
private suspend fun tryToAskForBiometry() {
if (!shouldAskForBiometry()) return
suspendCancellableCoroutine { continuation ->
uiMessageSender.send(
DialogMessage(
title = resourceReference(R.string.common_attention),
message = resourceReference(R.string.hot_access_code_set_biometric_ask),
firstAction = EventMessageAction(
title = resourceReference(R.string.common_allow),
onClick = {
modelScope.launch {
setAskBiometryShownUseCase()
walletsRepository.setUseBiometricAuthentication(true)
walletsRepository.setRequireAccessCode(false)
continuation.resumeWith(Result.success(Unit))
}
},
),
secondAction = EventMessageAction(
title = resourceReference(R.string.save_user_wallet_agreement_dont_allow),
onClick = {
modelScope.launch {
setAskBiometryShownUseCase()
continuation.resumeWith(Result.success(Unit))
}
},
),
onDismissRequest = {
modelScope.launch {
continuation.resumeWith(Result.success(Unit))
}
},
),
)
}
}
private suspend fun shouldAskForBiometry(): Boolean {
val canUseBiometry = canUseBiometryUseCase()
val shouldShowAskBiometry = shouldShowAskBiometryUseCase()
return canUseBiometry && shouldShowAskBiometry
}
}

View file

@ -149,7 +149,7 @@ internal class OnboardingEntryModel @Inject constructor(
doneMode: OnboardingDoneComponent.Mode = OnboardingDoneComponent.Mode.WalletCreated,
) {
modelScope.launch {
if (tangemSdkManager.checkCanUseBiometry() && settingsRepository.shouldShowSaveUserWalletScreen()) {
if (tangemSdkManager.checkCanUseBiometry() && settingsRepository.shouldShowAskBiometry()) {
doIfVisa {
analyticsEventHandler.send(OnboardingVisaAnalyticsEvent.BiometricScreenOpened)
}

View file

@ -19,8 +19,8 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.requireColdWallet
import com.tangem.domain.onboarding.repository.OnboardingRepository
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import com.tangem.domain.wallets.usecase.UpdateWalletUseCase
import com.tangem.features.onboarding.v2.common.ui.CantLeaveBackupDialog
@ -37,7 +37,10 @@ import com.tangem.sdk.api.TangemSdkManager
import com.tangem.utils.StringsSigns
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject
@ -52,8 +55,8 @@ internal class MultiWalletFinalizeModel @Inject constructor(
private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase,
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory,
private val userWalletsListManager: UserWalletsListManager,
private val saveWalletUseCase: SaveWalletUseCase,
private val getUserWalletsUseCase: GetWalletsUseCase,
private val updateWalletUseCase: UpdateWalletUseCase,
private val cardRepository: CardRepository,
private val onboardingRepository: OnboardingRepository,
@ -79,8 +82,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
// sets proper artwork state for initial step
// (if we start from backup cards, we need to show proper artwork) ([REDACTED_TASK_KEY])
when (getInitialStep()) {
MultiWalletFinalizeUM.Step.Primary -> { /* state is already set */
}
MultiWalletFinalizeUM.Step.Primary -> { /* state is already set */ }
MultiWalletFinalizeUM.Step.BackupDevice1 -> {
onEvent.emit(MultiWalletFinalizeComponent.Event.OneBackupCardAdded)
}
@ -245,7 +247,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
userWalletCreated
}
OnboardingMultiWalletComponent.Mode.AddBackup -> {
val userWallet = userWalletsListManager.userWallets.first()
val userWallet = getUserWalletsUseCase.invokeSync()
.firstOrNull {
it is UserWallet.Cold &&
it.scanResponse.primaryCard?.cardId == scanResponse.primaryCard?.cardId

View file

@ -14,7 +14,7 @@ interface UserWalletsFetcher {
fun create(
messageSender: UiMessageSender,
onlyMultiCurrency: Boolean,
authMode: Boolean,
isAuthMode: Boolean,
onWalletClick: (UserWalletId) -> Unit,
): UserWalletsFetcher
}

View file

@ -10,6 +10,7 @@ import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.core.wallets.UserWalletsListRepository
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.isLocked
@ -35,6 +36,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.*
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
import com.tangem.features.biometry.AskBiometryComponent
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
@ -58,7 +60,7 @@ internal class WalletModel @Inject constructor(
private val walletScreenContentLoader: WalletScreenContentLoader,
private val getSelectedWalletUseCase: GetSelectedWalletUseCase,
private val getWalletsUseCase: GetWalletsUseCase,
private val shouldShowSaveWalletScreenUseCase: ShouldShowSaveWalletScreenUseCase,
private val shouldShowAskBiometryUseCase: ShouldShowAskBiometryUseCase,
private val shouldShowMarketsTooltipUseCase: ShouldShowMarketsTooltipUseCase,
private val setWalletFirstTimeUsageUseCase: SetWalletFirstTimeUsageUseCase,
private val canUseBiometryUseCase: CanUseBiometryUseCase,
@ -80,6 +82,8 @@ internal class WalletModel @Inject constructor(
private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase,
private val shouldSaveUserWalletsSyncUseCase: ShouldSaveUserWalletsSyncUseCase,
private val getIsHuaweiDeviceWithoutGoogleServicesUseCase: GetIsHuaweiDeviceWithoutGoogleServicesUseCase,
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val userWalletsListRepository: UserWalletsListRepository,
val screenLifecycleProvider: ScreenLifecycleProvider,
val innerWalletRouter: InnerWalletRouter,
) : Model() {
@ -137,7 +141,7 @@ internal class WalletModel @Inject constructor(
modelScope.launch(dispatchers.main) {
withContext(dispatchers.io) { delay(timeMillis = 1_800) }
if (isShowSaveWalletScreenEnabled()) {
if (shouldShowAskBiometryBottomSheet()) {
innerWalletRouter.dialogNavigation.activate(
configuration = WalletDialogConfig.AskForBiometry,
)
@ -159,8 +163,15 @@ internal class WalletModel @Inject constructor(
}
}
private suspend fun isShowSaveWalletScreenEnabled(): Boolean {
return innerWalletRouter.isWalletLastScreen() && shouldShowSaveWalletScreenUseCase() && canUseBiometryUseCase()
private suspend fun shouldShowAskBiometryBottomSheet(): Boolean {
return if (hotWalletFeatureToggles.isHotWalletEnabled) {
userWalletsListRepository.userWalletsSync().any { it is UserWallet.Cold } &&
innerWalletRouter.isWalletLastScreen() &&
shouldShowAskBiometryUseCase() &&
canUseBiometryUseCase()
} else {
innerWalletRouter.isWalletLastScreen() && shouldShowAskBiometryUseCase() && canUseBiometryUseCase()
}
}
private fun subscribeToUserWalletsUpdates() = channelFlow<Unit> {

View file

@ -76,18 +76,19 @@ internal class WalletsUpdateActionResolver @Inject constructor(
isAnyWalletNameChanged(state, wallets) -> {
getRenameWalletsAction(state, wallets)
}
isAnyHotWalletBackedUp(state, wallets) -> {
isAnyHotWalletBackedUpChange(state, wallets) -> {
getHotWalletsBackedUpAction(state, wallets)
}
else -> getUpdateSelectedWalletAction(state, wallets, selectedWallet)
}
}
private fun isAnyHotWalletBackedUp(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
private fun isAnyHotWalletBackedUpChange(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
val incompleteActivationWalletIds = state.incompleteActivationWalletIds()
return incompleteActivationWalletIds.mapNotNull { walletId ->
wallets.firstOrNull { it.walletId == walletId && it is UserWallet.Hot && it.backedUp }
}.isNotEmpty()
val walletsToUpdate = wallets.filter {
it is UserWallet.Hot && it.backedUp == incompleteActivationWalletIds.contains(it.walletId)
}
return walletsToUpdate.isNotEmpty()
}
private fun isWalletsCountChanged(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
@ -163,8 +164,7 @@ internal class WalletsUpdateActionResolver @Inject constructor(
val incompleteActivationWalletIds = state.incompleteActivationWalletIds()
val walletsToUpdate = wallets.filter {
it is UserWallet.Hot && it.backedUp &&
incompleteActivationWalletIds.contains(it.walletId)
it is UserWallet.Hot && it.backedUp == incompleteActivationWalletIds.contains(it.walletId)
}
return Action.ReloadWarningsForWallets(walletsToUpdate)

View file

@ -13,6 +13,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.onEach
internal class MultiWalletWarningsSubscriber(
@ -31,6 +32,11 @@ internal class MultiWalletWarningsSubscriber(
.onEach { warnings ->
val displayedState = stateHolder.getWalletState(userWallet.walletId)
// Wait until the wallet appears in the list
stateHolder.uiState.first {
it.wallets.any { walletState -> walletState.walletCardState.id == userWallet.walletId }
}
stateHolder.update(SetWarningsTransformer(userWallet.walletId, warnings))
walletWarningsAnalyticsSender.send(displayedState, warnings)
walletWarningsSingleEventSender.send(

View file

@ -43,7 +43,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
@Assisted private val onWalletClick: (UserWalletId) -> Unit,
@Assisted private val messageSender: UiMessageSender,
@Assisted("onlyMultiCurrency") private val onlyMultiCurrency: Boolean,
@Assisted("authMode") private val authMode: Boolean,
@Assisted("isAuthMode") private val isAuthMode: Boolean,
private val userWalletImageFetcher: UserWalletImageFetcher,
dispatchers: CoroutineDispatcherProvider,
) : UserWalletsFetcher {
@ -55,7 +55,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
override val userWallets: Flow<ImmutableList<UserWalletItemUM>> = walletsFlow.transformLatest { wallets ->
val uiModels = UserWalletItemUMConverter(
onClick = onWalletClick,
authMode = authMode,
isAuthMode = isAuthMode,
).convertList(wallets)
.toImmutableList()
@ -64,7 +64,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
combine(
flow = getSelectedAppCurrencyUseCase().distinctUntilChanged(),
flow2 = getBalanceHidingSettingsUseCase().distinctUntilChanged(),
flow3 = getWalletTotalBalanceUseCase(wallets.map(UserWallet::walletId)).distinctUntilChanged(),
flow3 = getTotalBalanceFlow(wallets),
flow4 = userWalletImageFetcher.walletsImage(wallets, ArtworkSize.SMALL),
) { maybeAppCurrency, balanceHidingSettings, maybeBalances, artworks ->
createUiModels(
@ -88,6 +88,19 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
}
.flowOn(dispatchers.default)
private fun getTotalBalanceFlow(
wallets: List<UserWallet>,
): Flow<Lce<TokenListError, Map<UserWalletId, TotalFiatBalance>>> {
val walletIds = wallets.map(UserWallet::walletId)
return if (isAuthMode) {
// We should not load balances in auth mode
flowOf(Lce.Loading(walletIds.associateWith { TotalFiatBalance.Loading }))
} else {
getWalletTotalBalanceUseCase(walletIds).distinctUntilChanged()
}
}
private fun createUiModels(
wallets: List<UserWallet>,
maybeAppCurrency: Either<SelectedAppCurrencyError, AppCurrency>,
@ -117,7 +130,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
balance = balance,
isBalanceHidden = balanceHidingSettings.isBalanceHidden,
artwork = artworks[userWallet.walletId],
authMode = authMode,
isAuthMode = isAuthMode,
)
.convert(userWallet)
}
@ -136,7 +149,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
override fun create(
messageSender: UiMessageSender,
@Assisted("onlyMultiCurrency") onlyMultiCurrency: Boolean,
@Assisted("authMode") authMode: Boolean,
@Assisted("isAuthMode") isAuthMode: Boolean,
onWalletClick: (UserWalletId) -> Unit,
): DefaultUserWalletsFetcher
}

View file

@ -29,7 +29,7 @@ internal class WcUserWalletsFetcher(
private val userWalletsFetcher = userWalletsFetcherFactory.create(
messageSender = messageSender,
onlyMultiCurrency = true,
authMode = false,
isAuthMode = false,
onWalletClick = { onWalletSelected(it) },
)

View file

@ -55,7 +55,7 @@ internal class WelcomeModel @Inject constructor(
private val walletsFetcher = userWalletsFetcherFactory.create(
messageSender = uiMessageSender,
onlyMultiCurrency = false,
authMode = true,
isAuthMode = true,
onWalletClick = { walletId ->
modelScope.launch {
val userWallets = userWalletsListRepository.userWalletsSync()