Updated on 2026-08-14

This commit is contained in:
Tangem 2024-09-23 11:10:04 +03:00
commit df9318faef
60 changed files with 756 additions and 123 deletions

View file

@ -4,6 +4,7 @@ import com.tangem.blockchain.common.AmountType
import com.tangem.domain.feedback.models.BlockchainErrorInfo
import com.tangem.domain.redux.LegacyAction
import com.tangem.domain.utils.convertToSdkAmount
import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.extensions.inject
import com.tangem.tap.common.extensions.stripZeroPlainString
import com.tangem.tap.common.feedback.FeedbackEmail
@ -11,13 +12,23 @@ import com.tangem.tap.common.feedback.RateCanBeBetterEmail
import com.tangem.tap.common.feedback.SendTransactionFailedEmail
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.features.details.redux.DetailsAction
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.rekotlin.Middleware
internal object LegacyMiddleware {
private val prepareDetailsScreenJobHolder = JobHolder()
val legacyMiddleware: Middleware<AppState> = { _, _ ->
{ next ->
{ action ->
@ -85,6 +96,24 @@ internal object LegacyMiddleware {
}
}
}
is LegacyAction.PrepareDetailsScreen -> {
val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
val walletsRepository = store.inject(DaggerGraphState::walletsRepository)
userWalletsListManager.selectedUserWallet
.distinctUntilChanged()
.onEach { selectedUserWallet ->
store.dispatchWithMain(
DetailsAction.PrepareScreen(
scanResponse = selectedUserWallet.scanResponse,
shouldSaveUserWallets = walletsRepository.shouldSaveUserWalletsSync(),
),
)
}
.flowOn(Dispatchers.IO)
.launchIn(scope)
.saveIn(prepareDetailsScreenJobHolder)
}
}
next(action)
}

View file

@ -2,6 +2,7 @@ package com.tangem.tap.di.domain
import com.tangem.domain.staking.*
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
import dagger.Module
@ -122,6 +123,42 @@ internal object StakingDomainModule {
)
}
@Provides
@Singleton
fun provideSavePendingTransactionUseCase(
stakingPendingTransactionRepository: StakingPendingTransactionRepository,
stakingErrorResolver: StakingErrorResolver,
): SavePendingTransactionUseCase {
return SavePendingTransactionUseCase(
stakingPendingTransactionRepository = stakingPendingTransactionRepository,
stakingErrorResolver = stakingErrorResolver,
)
}
@Provides
@Singleton
fun provideInvalidatePendingTransactionsUseCase(
stakingPendingTransactionRepository: StakingPendingTransactionRepository,
stakingErrorResolver: StakingErrorResolver,
): InvalidatePendingTransactionsUseCase {
return InvalidatePendingTransactionsUseCase(
stakingPendingTransactionRepository = stakingPendingTransactionRepository,
stakingErrorResolver = stakingErrorResolver,
)
}
@Provides
@Singleton
fun provideGetPendingTransactionsUseCase(
stakingPendingTransactionRepository: StakingPendingTransactionRepository,
stakingErrorResolver: StakingErrorResolver,
): GetPendingTransactionsUseCase {
return GetPendingTransactionsUseCase(
stakingPendingTransactionRepository = stakingPendingTransactionRepository,
stakingErrorResolver = stakingErrorResolver,
)
}
@Provides
@Singleton
fun provideSendUnsubmittedHashesUseCase(

View file

@ -224,6 +224,7 @@ internal class MainViewModel @Inject constructor(
override fun onDismissBottomSheet() {
listenToFlipsUseCase.changeUpdateEnabled(true)
router.pop()
stateHolder.updateWithoutModalNotification()
stateHolder.updateWithHiddenBalancesToast(true)
}

View file

@ -6,6 +6,8 @@ import java.math.BigDecimal
@JsonClass(generateAdapter = true)
data class TokenMarketChartResponse(
// There is a bug in the API, it returns null values.
// We need to filter them out.
@Json(name = "prices")
val prices: Map<Long, BigDecimal>,
val prices: Map<Long, BigDecimal?>,
)

View file

@ -39,7 +39,7 @@
<string name="biometric_lockout_warning_title">Zu viele Versuche</string>
<string name="biometric_unavailable_warning">Du hast die biometrische Authentifizierung auf deinem Telefon deaktiviert und kannst keine Wallets in der App speichern. Um Wallets zu speichern, aktiviere bitte die biometrische Authentifizierung in deinen Telefoneinstellungen.</string>
<string name="button_start_backup_process">Backup-Prozess starten</string>
<string name="buy_token_description">Von deiner Fiat-Karte oder deinem Bankkonto</string>
<string name="buy_token_description">Verwende eine Bankkarte oder eine andere Zahlungsmethode</string>
<plurals name="card_label_card_count">
<item quantity="one">%d Karte</item>
<item quantity="other">%d Karten</item>
@ -275,7 +275,7 @@
<string name="express_token_list_empty_search">Keine Token gefunden. Bitte versuche eine andere Anfrage</string>
<string name="express_transaction_id">ID: %s</string>
<string name="express_transaction_id_copied">Transaktions-ID kopiert</string>
<string name="exсhange_token_description">Aus einer anderen Währung in deiner Wallet</string>
<string name="exсhange_token_description">Wechsel eine Ihrer Währungen in eine andere</string>
<string name="feedback_data_collection_message">Die folgenden Angaben sind freiwillig. Du kannst diese löschen, wenn du sie nicht weitergeben möchtest.</string>
<string name="feedback_preface_rate_negative">Teile uns mit, welche Funktionen du vermisst, und wir werden versuchen, dir zu helfen.</string>
<string name="feedback_preface_scan_failed">Bitte sag uns, welche Karte du hast</string>
@ -356,6 +356,7 @@
<string name="markets_loading_error_title">Die Daten konnten nicht geladen werden...</string>
<string name="markets_loading_no_data_title">Keine Daten</string>
<string name="markets_quick_actions">Schnelle Aktionen</string>
<string name="markets_search_header_title">Markt durchsuchen</string>
<string name="markets_search_result_title">Ergebnis</string>
<string name="markets_search_see_tokens_under_100k">Token unter 100k USD Marktkapitalisierung anzeigen</string>
<string name="markets_search_show_tokens">Token anzeigen</string>
@ -386,25 +387,32 @@
<string name="markets_token_details_buy_pressure_full">Kaufdruck</string>
<string name="markets_token_details_circulating_supply">Umlaufmenge</string>
<string name="markets_token_details_circulating_supply_description">Die Gesamtzahl der Coins, die für den Handel verfügbar sind und auf dem Markt zirkulieren</string>
<string name="markets_token_details_circulating_supply_full">Umlaufmenge</string>
<string name="markets_token_details_experienced_buyers">Erfahrene Käufer</string>
<string name="markets_token_details_experienced_buyers_description">Nettokäufer mit der zusätzlichen Anforderung, mindestens 100 ausgehende Transaktionen zu haben</string>
<string name="markets_token_details_experienced_buyers_full">Erfahrene Käufer</string>
<string name="markets_token_details_fully_diluted_valuation">Vollständig verwässerte Bewertung</string>
<string name="markets_token_details_fully_diluted_valuation_description">Der theoretische Gesamtwert einer Kryptowährung, wenn alle Coins, die existieren könnten, im Umlauf sind, einschließlich derjenigen, die derzeit nicht im Umlauf sind</string>
<string name="markets_token_details_fully_diluted_valuation_full">Vollständig verwässerte Bewertung</string>
<string name="markets_token_details_genesis_date">Entstehungsdatum</string>
<string name="markets_token_details_high">Hoch</string>
<string name="markets_token_details_holders">Inhaber/ Halter</string>
<string name="markets_token_details_holders_description">Die Änderung der Anzahl der Token-Inhaber innerhalb eines bestimmten Zeitraums</string>
<string name="markets_token_details_holders_full">Inhaber/ Halter</string>
<string name="markets_token_details_insights">Einblicke</string>
<string name="markets_token_details_links">Links</string>
<string name="markets_token_details_liquidity">Liquidität</string>
<string name="markets_token_details_liquidity_description">Die Änderung der Liquidität, die dem Token während des angegebenen Zeitraums zur Verfügung steht</string>
<string name="markets_token_details_liquidity_full">Liquidität</string>
<string name="markets_token_details_liquidity_index">Liquiditätsindex</string>
<string name="markets_token_details_liquidity_index_description">Leer</string>
<string name="markets_token_details_low">Niedrig</string>
<string name="markets_token_details_market_capitalization">MarketCap</string>
<string name="markets_token_details_market_capitalization_description">Der Gesamtmarktwert einer Kryptowährung, berechnet durch Multiplikation des aktuellen Preises des Coins mit der Gesamtzahl der im Umlauf befindlichen Coins.</string>
<string name="markets_token_details_market_capitalization_description">Der Gesamtmarktwert einer Kryptowährung, berechnet sich durch Multiplikation des aktuellen Preises des Coins mit der Gesamtzahl der im Umlauf befindlichen Coins</string>
<string name="markets_token_details_market_capitalization_full">MarketCap</string>
<string name="markets_token_details_market_rating">Marktbewertung</string>
<string name="markets_token_details_market_rating_description">Position im Krypto-Rating zwischen allen Coins basierend auf der Marktkapitalisierung</string>
<string name="markets_token_details_market_rating_full">Marktbewertung</string>
<string name="markets_token_details_max_supply">Maximale Versorgung</string>
<string name="markets_token_details_max_supply_description">Leer</string>
<string name="markets_token_details_metrics">Metriken</string>
@ -415,8 +423,10 @@
<string name="markets_token_details_social">Soziales</string>
<string name="markets_token_details_total_supply">Gesamtangebot</string>
<string name="markets_token_details_total_supply_description">Die maximale Anzahl von Coins oder Tokens, die jemals für eine bestimmte Kryptowährung existieren können</string>
<string name="markets_token_details_total_supply_full">Gesamtangebot</string>
<string name="markets_token_details_trading_volume">Handelsvolumen (24h)</string>
<string name="markets_token_details_trading_volume_24h_description">Der Gesamtbetrag einer Kryptowährung, der innerhalb der letzten 24 Stunden gehandelt wurde, wobei das Aktivitäts- und Liquiditätsniveau auf dem Markt angegeben wird</string>
<string name="markets_token_details_trading_volume_full">Handelsvolumen (24h)</string>
<string name="markets_tooltip_message">Rufe dies auf oder tippe auf die Suchleiste, um Token direkt vom Markt hinzuzufügen</string>
<string name="markets_tooltip_title">Token hinzufügen</string>
<string name="nfc_error_unavailable">NFC ist auf deinem Gerät nicht verfügbar</string>
@ -520,7 +530,7 @@
<string name="qr_scanner_camera_denied_title">Kamerazugriff verweigert</string>
<string name="receive_bottom_sheet_warning_message">%1$s ( %2$s ) im %3$s Netzwerk</string>
<string name="receive_bottom_sheet_warning_message_full">Sende nur %s an diese Adresse. Der Versand einer anderen Währung führt zu ihrem unwiderruflichen Verlust.</string>
<string name="receive_token_description">QR-Code anzeigen oder Adresse teilen</string>
<string name="receive_token_description">Überweise Geld von einem anderen Wallet oder einer anderen Börse</string>
<string name="referral_button_participate">Teilnehmen</string>
<string name="referral_error_failed_to_load_info">Die Informationen zum Empfehlungsprogramm konnten nicht geladen werden. Bitte versuche es später noch einmal.</string>
<string name="referral_error_failed_to_load_info_with_reason">Die Informationen über das Empfehlungsprogramm konnten nicht geladen werden. Fehlercode: %s. Bitte versuche es später noch einmal.</string>
@ -605,7 +615,7 @@
<string name="send_notification_exceed_balance_title">Gesamtbetrag übersteigt den Saldo</string>
<string name="send_notification_existential_deposit_text">Ein Guthaben von mindestens %s ist erforderlich, um dein Konto in der Blockchain aktiv zu halten und Sicherheitsrisiken zu vermeiden. Dieser Betrag verbleibt auf deinem Guthaben und kann nicht abgehoben werden.</string>
<string name="send_notification_existential_deposit_title">Mindesteinlage</string>
<string name="send_notification_fee_too_high_text">Der Kommissionsbetrag ist %s mal der empfohlene Betrag. Stelle sicher, dass die benutzerdefinierten Einstellungen korrekt sind.</string>
<string name="send_notification_fee_too_high_text">Dein Provisionsbetrag ist %s -mal höher als der empfohlene Betrag. Bitte überprüfe benutzerdefinierten Einstellungen und pass diese an.</string>
<string name="send_notification_fee_too_high_title">Die individuelle Gebühr ist hoch</string>
<string name="send_notification_high_fee_text">Aufgrund der Besonderheiten des Netzes %1$s ist die Gebühr für die Überweisung des gesamten Guthabens höher. Um die Kommission zu reduzieren, Kannst du %2$s verlassen.</string>
<string name="send_notification_high_fee_title">Die Gebühr ist höher</string>
@ -639,7 +649,7 @@
<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>
<string name="send_summary_transaction_description_suffix_fee_reduced">Die Netzwerkgebühr wird durch das Ausgeben von %1$s Energieträgern reduziert.</string>
<string name="send_summary_transaction_description_suffix_fee_reduced">Die Netzwerkgebühr wird durch den Verbrauch von %1$s Energie reduziert</string>
<string name="send_summary_transaction_description_suffix_including">inklusive einer Netzgebühr von %1$s</string>
<string name="send_transaction_success">Die Transaktion wurde erfolgreich signiert und an den Blockchain-Knoten gesendet. Die Walletbilanz wird aktualisiert</string>
<string name="send_tron_account_activation_error">%1$s ist ein Vermögenswert im Tron-Netzwerk. Um die Gebühr zu berechnen und eine Transaktion durchzuführen, musst du etwas Tron (TRX) auf deinem Konto einzahlen.</string>
@ -659,7 +669,7 @@
<string name="staking_details_auto_claiming_rewards_daily_text">Belohnungen sammeln sich täglich automatisch in deinem Staking-Konto an.</string>
<string name="staking_details_available">Verfügbar</string>
<string name="staking_details_average_reward_rate">Durchschnittliche Belohnungsquote</string>
<string name="staking_details_banner_text">Was sit Staking?</string>
<string name="staking_details_banner_text">Was ist Staking?</string>
<string name="staking_details_estimated_profit">%s geschätzter Profit</string>
<string name="staking_details_market_rating">Marktbewertung</string>
<string name="staking_details_metrics_block_header">Metriken</string>
@ -679,7 +689,8 @@
<string name="staking_locked">Gesperrt</string>
<string name="staking_migrate">Migrieren</string>
<string name="staking_native">Natives Staking</string>
<string name="staking_notification_claim_rewards_text">Verdiente Belohnungen werden an deine Wallet gesendet und stehen sofort zur Verwendung zur Verfügung</string>
<string name="staking_notification_claim_rewards_text">Verdiente Belohnungen werden an Deine Wallet gesendet und stehen Dir sofort zur Verfügung</string>
<string name="staking_notification_earn_rewards_text">Stake sicher und verdienen Belohnungen</string>
<string name="staking_notification_earn_rewards_text_daily">Sicher staken und tägliche Belohnungen verdienen.</string>
<string name="staking_notification_earn_rewards_text_hourly">Sicher staken und stündliche Belohnungen verdienen.</string>
<string name="staking_notification_earn_rewards_text_monthly">Sicher staken und monatliche Belohnungen verdienen.</string>

View file

@ -39,7 +39,7 @@
<string name="biometric_lockout_warning_title">Demasiados intentos</string>
<string name="biometric_unavailable_warning">Ha desactivado la autenticación biométrica en su teléfono y no podrá guardar billeteras en la aplicación. Para guardar billeteras, active la función de autenticación biométrica en los ajustes de su teléfono.</string>
<string name="button_start_backup_process">Iniciar proceso de backup</string>
<string name="buy_token_description">Con su tarjeta bancaria o cuenta bancaria</string>
<string name="buy_token_description">Utilice una tarjeta bancaria u otros métodos de pago</string>
<plurals name="card_label_card_count">
<item quantity="one">%d tarjeta</item>
<item quantity="other">%d tarjetas </item>
@ -84,6 +84,7 @@
<string name="common_camera_denied_alert_message">No ha otorgado acceso a su cámara, cambie su configuración de privacidad</string>
<string name="common_cancel">Cancelar</string>
<string name="common_choose_action">Elige una acción</string>
<string name="common_claim">Reclamar</string>
<string name="common_claim_rewards">Reclame recompensas</string>
<string name="common_close">Cerrar</string>
<string name="common_continue">Continuar</string>
@ -274,7 +275,7 @@
<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>
<string name="express_transaction_id_copied">ID de transacción copiado</string>
<string name="exсhange_token_description">Con otra moneda en su billetera</string>
<string name="exсhange_token_description">Convierta una de sus monedas a otra</string>
<string name="feedback_data_collection_message">La siguiente información es opcional. Puede borrarla si no quiere compartirla.</string>
<string name="feedback_preface_rate_negative">Cuéntenos qué funciones echa de menos y trataremos de ayudarle.</string>
<string name="feedback_preface_scan_failed">Por favor, díganos qué tarjeta tiene</string>
@ -355,6 +356,7 @@
<string name="markets_loading_error_title">No se pueden cargar los datos…</string>
<string name="markets_loading_no_data_title">Sin datos</string>
<string name="markets_quick_actions">Acciones rápidas</string>
<string name="markets_search_header_title">Busque en el mercado</string>
<string name="markets_search_result_title">Resultado</string>
<string name="markets_search_see_tokens_under_100k">Ver tokens con una capitalización de mercado de menos de $100,000</string>
<string name="markets_search_show_tokens">Mostrar tokens</string>
@ -385,24 +387,31 @@
<string name="markets_token_details_buy_pressure_full">Presión de compra</string>
<string name="markets_token_details_circulating_supply">Suministro circulante</string>
<string name="markets_token_details_circulating_supply_description">El número total de monedas que están disponibles para el comercio y que circulan en el mercado.</string>
<string name="markets_token_details_circulating_supply_full">Suministro circulante</string>
<string name="markets_token_details_experienced_buyers">Compradores experimentados</string>
<string name="markets_token_details_experienced_buyers_description">Compradores netos con el requisito adicional de tener al menos 100 transacciones salientes</string>
<string name="markets_token_details_experienced_buyers_full">Compradores experimentados</string>
<string name="markets_token_details_fully_diluted_valuation">Valoración totalmente diluida</string>
<string name="markets_token_details_fully_diluted_valuation_description">El valor teórico total de una criptomoneda si todas las monedas que podrían existir estuvieran en circulación, incluidas las que actualmente no circulan.</string>
<string name="markets_token_details_fully_diluted_valuation_full">Valoración totalmente diluida</string>
<string name="markets_token_details_genesis_date">Dato de Genesis</string>
<string name="markets_token_details_high">Alto</string>
<string name="markets_token_details_holders">Titulares</string>
<string name="markets_token_details_holders_description">El cambio en el número de poseedores de tokens dentro de un período de tiempo específico</string>
<string name="markets_token_details_holders_full">Titulares</string>
<string name="markets_token_details_insights">Ideas</string>
<string name="markets_token_details_links">Enlaces</string>
<string name="markets_token_details_liquidity">Liquidez</string>
<string name="markets_token_details_liquidity_description">El cambio en la cantidad de liquidez disponible para el token durante el período de tiempo especificado</string>
<string name="markets_token_details_liquidity_full">Liquidez</string>
<string name="markets_token_details_liquidity_index">Índice de liquidez</string>
<string name="markets_token_details_low">Bajo</string>
<string name="markets_token_details_market_capitalization">Capital. de mercado</string>
<string name="markets_token_details_market_capitalization_description">El valor total de una criptomoneda calculado multiplicando su precio por la cantidad de monedas en circulación</string>
<string name="markets_token_details_market_capitalization_full">Capital. de mercado</string>
<string name="markets_token_details_market_rating">Evaluación de mercado</string>
<string name="markets_token_details_market_rating_description">Posición en la clasificación de criptomonedas entre todas las monedas según la capitalización de mercado</string>
<string name="markets_token_details_market_rating_full">Evaluación de mercado</string>
<string name="markets_token_details_max_supply">Suministro máximo</string>
<string name="markets_token_details_metrics">Métrica</string>
<string name="markets_token_details_official_links">Enlaces oficiales</string>
@ -412,8 +421,10 @@
<string name="markets_token_details_social">Social</string>
<string name="markets_token_details_total_supply">Suministro total</string>
<string name="markets_token_details_total_supply_description">La cantidad máxima de monedas o tokens que pueden existir para una criptomoneda en particular</string>
<string name="markets_token_details_total_supply_full">Suministro total</string>
<string name="markets_token_details_trading_volume">Volumen de operaciones (24 horas)</string>
<string name="markets_token_details_trading_volume_24h_description">La cantidad total de una criptomoneda que se ha negociado en las últimas 24 horas, lo que indica el nivel de actividad y liquidez en el mercado.</string>
<string name="markets_token_details_trading_volume_full">Volumen de operaciones (24 horas)</string>
<string name="markets_tooltip_message">Tire hacia arriba o toque la barra de búsqueda para agregar tokens directamente desde el mercado</string>
<string name="markets_tooltip_title">Agregar tokens</string>
<string name="nfc_error_unavailable">NFC no está disponible en su dispositivo</string>
@ -517,7 +528,7 @@
<string name="qr_scanner_camera_denied_title">Acceso a la cámara denegado</string>
<string name="receive_bottom_sheet_warning_message">%1$s (%2$s) en la red %3$s</string>
<string name="receive_bottom_sheet_warning_message_full">Envíe solo %s a esta dirección. Enviar cualquier otra moneda resultará en su pérdida irreversible.</string>
<string name="receive_token_description">Muestra un código QR o comparte tu dirección</string>
<string name="receive_token_description">Transfiera fondos desde otra billetera o intercambio</string>
<string name="referral_button_participate">Participar</string>
<string name="referral_error_failed_to_load_info">Error al cargar la información sobre el programa de referidos. Por favor, inténtelo de nuevo más tarde.</string>
<string name="referral_error_failed_to_load_info_with_reason">Error al cargar la información sobre el programa de referidos. Código de error: %s. Por favor, inténtelo de nuevo más tarde.</string>
@ -634,6 +645,10 @@
<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_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>
<string name="send_summary_transaction_description_suffix_fee_reduced">La tarifa de red se reducirá al usar %1$s energía</string>
<string name="send_summary_transaction_description_suffix_including">incluida una tarifa de red de %1$s</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="sent_transaction_sent_title">Transacción enviada</string>
@ -644,6 +659,8 @@
<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_claim_unstaked">Unstaking de la reclamación</string>
<string name="staking_details_account_fee">Tarifa de staking de la cuenta </string>
<string name="staking_details_account_fee_info">Una cuenta de staking es una cuenta especial donde se almacenan los tokens SOL de staking. Se crea cuando delegas sus tokens a un validador para participar en la validación de transacciones y ganar recompensas. Se cobra una pequeña tarifa por crear la cuenta de staking, que se devuelve una vez que se completa el staking.</string>
<string name="staking_details_annual_percentage_rate">Porcentaje de rendimiento anual</string>
<string name="staking_details_annual_percentage_rate_info">El porcentaje de rendimiento anual que podrá ganar como participante en el staking.</string>
<string name="staking_details_apr">APR</string>
@ -671,14 +688,25 @@
<string name="staking_migrate">Migrar</string>
<string name="staking_native">Native staking</string>
<string name="staking_notification_claim_rewards_text">Recomp. won se le enviará y estará disponible para su uso inmediato</string>
<string name="staking_notification_earn_rewards_text">Haga staking de forma segura y comience a ganar recompensas</string>
<string name="staking_notification_earn_rewards_text_daily">Haga de forma segura y comience a ganar recompensas diarias</string>
<string name="staking_notification_earn_rewards_text_hourly">Haga staking de forma segura y comience a ganar recompensas por hora</string>
<string name="staking_notification_earn_rewards_text_monthly">Haga staking de forma segura y comience a ganar recompensas mensuales</string>
<string name="staking_notification_earn_rewards_text_period_day">El staking le permite ganar %1$s. Sus recompensas por apostar llegan todos los días.</string>
<string name="staking_notification_earn_rewards_text_period_hour">El staking le permite ganar %1$s. Sus recompensas del staking llegan cada hora.</string>
<string name="staking_notification_earn_rewards_text_period_month">El staking le permite ganar %1$s. Sus recompensas del staking llegan todos los meses.</string>
<string name="staking_notification_earn_rewards_text_period_week">El staking le permite ganar %1$s. Sus recompensas por apostar llegan todas las semanas.</string>
<string name="staking_notification_earn_rewards_text_weekly">Haga staking de forma segura y comience a ganar recompensas semanales</string>
<string name="staking_notification_earn_rewards_title">Gane recompensas por staking</string>
<string name="staking_notification_network_error_text">El staking no está disponible actualmente debido a las condiciones de la red. Inténtelo de nuevo más tarde.</string>
<string name="staking_notification_new_validator_funds_transfer">El staking en la red %1$s con un nuevo validador transferirá automáticamente todos los fondos previamente en staking a este validador.</string>
<string name="staking_notification_restake_rewards_text">Reinvierta las recompensas obtenidas en el monto apostado, aumentando las ganancias potenciales.</string>
<string name="staking_notification_unlock_text">Desbloquee su dinero para retirarlo del proceso de staking. El desbloqueo demora %s minuto.</string>
<string name="staking_notification_unstake_cosmos_text">Sus fondos estarán disponibles para su uso después del período de desvinculación de 21 días. La recompensa se retirará junto con los fondos de desvinculación.</string>
<string name="staking_notification_unstake_text">Sus fondos estarán disponibles para su uso después del período de desvinculación de %s.</string>
<string name="staking_notification_withdraw_text">Ya puede retirar sus fondos, estarán disponibles para usar de inmediato.</string>
<string name="staking_notifications_revote_tron_text">Hacer staking en la red Tron con un nuevo validador transferirá automáticamente todos los fondos de staking a este validador.</string>
<string name="staking_preparing">Preparando</string>
<string name="staking_ready_to_withdraw">Listo para retirar</string>
<string name="staking_rebond">Reunir</string>
<string name="staking_restake">Haga el staking de nuevo</string>
@ -698,6 +726,7 @@
<string name="staking_rewards">Recompensas</string>
<string name="staking_stake_locked">El stake está bloqueado</string>
<string name="staking_stake_more">Hacer más staking</string>
<string name="staking_summary_description_text">Haga staking de %1$s y recibirá %2$s anualmente</string>
<string name="staking_tap_to_unlock">Toque para desbloquear</string>
<string name="staking_tap_to_withdraw">Toque para retirar</string>
<string name="staking_title_stake">Stake %s</string>
@ -705,8 +734,10 @@
<string name="staking_transaction_in_progress_text">¡La transacción se está procesando! La validación está en curso en la cadena de bloques. Esto puede tardar unos minutos.</string>
<string name="staking_unbonding">Desunión</string>
<string name="staking_unlocked_locked">Desbloquear</string>
<string name="staking_unlocking">Desbloqueando</string>
<string name="staking_unstaked">Sin staking</string>
<string name="staking_unstaking">Unstaking</string>
<string name="staking_unstaking_item_name">Detenando el staking de activos %s</string>
<string name="staking_validator">Validador</string>
<string name="staking_validators">Validadores</string>
<string name="staking_vote">Votar</string>
@ -846,6 +877,8 @@
<string name="warning_backup_errors_title">Error de activación</string>
<string name="warning_beacon_chain_retirement_content">Según los desarrolladores de la red BNB, el soporte para el estándar BEP-2\nfinalizará en junio de 2024. Para evitar perder activos con este estándar, por favor conviértalos al estándar BEP-20. Usa nuestro servicio de swap para transferirlos a la red BNB Smart Chain.</string>
<string name="warning_beacon_chain_retirement_title">BNB Beacon Chain se cerrará</string>
<string name="warning_blocked_funds_for_fee_message">Por favor deposite %1$s para cubrir la tarifa de red</string>
<string name="warning_blocked_funds_for_fee_title">Fondos insuficientes para cubrir la tarifa de red</string>
<string name="warning_button_could_be_better">Podría ser mejor</string>
<string name="warning_button_like_it">Me gusta</string>
<string name="warning_button_ok">Entendido</string>

View file

@ -39,7 +39,7 @@
<string name="biometric_lockout_warning_title">Trop de tentatives</string>
<string name="biometric_unavailable_warning">Vous avez désactivé l\'authentification biométrique sur votre téléphone et ne pourrez pas enregistrer de portefeuilles dans l\'application. Pour enregistrer des portefeuilles, veuillez activer la fonction d\'authentification biométrique dans les paramètres de votre téléphone.</string>
<string name="button_start_backup_process">Démarrer le processus de sauvegarde</string>
<string name="buy_token_description">Avec votre carte bancaire ou votre compte bancaire</string>
<string name="buy_token_description">Utilisez une carte bancaire ou d\'autres moyens de paiement</string>
<plurals name="card_label_card_count">
<item quantity="one">%d carte</item>
<item quantity="other">%d cartes</item>
@ -84,6 +84,7 @@
<string name="common_camera_denied_alert_message">Vous n\'avez pas octroyé l\'accès à votre caméra, veuillez modifier vos paramètres de confidentialité</string>
<string name="common_cancel">Annuler</string>
<string name="common_choose_action">Choisissez une action</string>
<string name="common_claim">Réclamer</string>
<string name="common_claim_rewards">Réclamez des récompenses</string>
<string name="common_close">Fermer</string>
<string name="common_continue">Continuer</string>
@ -274,7 +275,7 @@
<string name="express_token_list_empty_search">Aucun jeton trouvé. Veuillez essayer une autre demande</string>
<string name="express_transaction_id">ID : %s</string>
<string name="express_transaction_id_copied">ID de transaction copié</string>
<string name="exсhange_token_description">Avec une autre devise dans votre portefeuille</string>
<string name="exсhange_token_description">Convertissez une de vos devises en une autre</string>
<string name="feedback_data_collection_message">Les informations suivantes sont facultatives. Vous pouvez les effacer si vous ne souhaitez pas les partager.</string>
<string name="feedback_preface_rate_negative">Dites-nous quelles fonctions vous manquent, et nous essaierons de vous aider.</string>
<string name="feedback_preface_scan_failed">Veuillez nous dire quelle carte vous avez</string>
@ -355,6 +356,7 @@
<string name="markets_loading_error_title">Impossible de charger les données…</string>
<string name="markets_loading_no_data_title">Aucune donnée</string>
<string name="markets_quick_actions">Actions rapides</string>
<string name="markets_search_header_title">Rechercher sur le marché</string>
<string name="markets_search_result_title">Résultat</string>
<string name="markets_search_see_tokens_under_100k">Voir les jetons de moins de 100 000 $ de capitalisation boursière</string>
<string name="markets_search_show_tokens">Afficher les jetons</string>
@ -385,24 +387,31 @@
<string name="markets_token_details_buy_pressure_full">Pression d\'achat</string>
<string name="markets_token_details_circulating_supply">Approvisionnement en circulation</string>
<string name="markets_token_details_circulating_supply_description">Le nombre total de pièces disponibles pour le trading et en circulation sur le marché</string>
<string name="markets_token_details_circulating_supply_full">Approvisionnement en circulation</string>
<string name="markets_token_details_experienced_buyers">Acheteurs expérimentés</string>
<string name="markets_token_details_experienced_buyers_description">Acheteurs nets avec l\'exigence supplémentaire d\'avoir au moins 100 transactions sortantes</string>
<string name="markets_token_details_experienced_buyers_full">Acheteurs expérimentés</string>
<string name="markets_token_details_fully_diluted_valuation">Valorisation entièrement diluée</string>
<string name="markets_token_details_fully_diluted_valuation_description">La valeur théorique totale d\'une crypto-monnaie si toutes les pièces qui pourraient exister étaient en circulation, y compris celles qui ne circulent pas actuellement</string>
<string name="markets_token_details_fully_diluted_valuation_full">Valorisation entièrement diluée</string>
<string name="markets_token_details_genesis_date">Date de la Genesis</string>
<string name="markets_token_details_high">Haut</string>
<string name="markets_token_details_holders">Détenteurs</string>
<string name="markets_token_details_holders_description">L\'évolution du nombre de détenteurs de jetons au cours d\'une période donnée</string>
<string name="markets_token_details_holders_full">Détenteurs</string>
<string name="markets_token_details_insights">Idées</string>
<string name="markets_token_details_links">Liens</string>
<string name="markets_token_details_liquidity">Liquidité</string>
<string name="markets_token_details_liquidity_description">Le changement dans la quantité de liquidité disponible pour le jeton pendant la période spécifiée</string>
<string name="markets_token_details_liquidity_full">Liquidité</string>
<string name="markets_token_details_liquidity_index">Indice de liquidité</string>
<string name="markets_token_details_low">Faible</string>
<string name="markets_token_details_market_capitalization">Cap. boursière</string>
<string name="markets_token_details_market_capitalization_description">La valeur d\'une crypto-monnaie est calculée en multipliant son prix par le nombre de pièces en circulation</string>
<string name="markets_token_details_market_capitalization_full">Cap. boursière</string>
<string name="markets_token_details_market_rating">Évaluation du marché</string>
<string name="markets_token_details_market_rating_description">Position dans le classement des crypto-monnaies entre toutes les pièces en fonction de la capitalisation boursière</string>
<string name="markets_token_details_market_rating_full">Évaluation du marché</string>
<string name="markets_token_details_max_supply">Approvisionnement maximal</string>
<string name="markets_token_details_metrics">Métriques</string>
<string name="markets_token_details_official_links">Official links</string>
@ -412,8 +421,10 @@
<string name="markets_token_details_social">Social</string>
<string name="markets_token_details_total_supply">Approvisionnement total</string>
<string name="markets_token_details_total_supply_description">Le nombre maximal de pièces ou de jetons pouvant exister pour une crypto-monnaie particulière</string>
<string name="markets_token_details_total_supply_full">Approvisionnement total</string>
<string name="markets_token_details_trading_volume">Volume des échanges (24h)</string>
<string name="markets_token_details_trading_volume_24h_description">Le montant total d\'une crypto-monnaie qui a été échangé au cours des dernières 24 heures, indiquant le niveau d\'activité et de liquidité du marché</string>
<string name="markets_token_details_trading_volume_full">Volume des échanges (24h)</string>
<string name="markets_tooltip_message">Tirez vers le haut ou appuyez sur la barre de recherche pour ajouter des jetons directement depuis le marché</string>
<string name="markets_tooltip_title">Ajouter des jetons</string>
<string name="nfc_error_unavailable">NFC n\'est pas disponible sur votre appareil</string>
@ -460,12 +471,12 @@
<string name="onboarding_navbar_title_creating_backup">Sauvegarde en cours</string>
<string name="onboarding_seed_button_read_more">En savoir plus sur les seed phrases</string>
<plurals name="onboarding_seed_generate_message_words_count">
<item quantity="one"></item>
<item quantity="one">Vide</item>
<item quantity="other">Écrivez ces %d mots dans l\'ordre indiqué ci-dessous et conservez-les dans un endroit sûr et secret.</item>
</plurals>
<string name="onboarding_seed_generate_title">Votre seed phrase</string>
<plurals name="onboarding_seed_generate_words_count">
<item quantity="one"></item>
<item quantity="one">Vide</item>
<item quantity="other">%d mots</item>
</plurals>
<string name="onboarding_seed_import_message">Pour importer votre portefeuille, entrez votre seed phrase dans le champ ci-dessous</string>
@ -517,7 +528,7 @@
<string name="qr_scanner_camera_denied_title">Accès à la caméra refusé</string>
<string name="receive_bottom_sheet_warning_message">%1$s (%2$s) sur le réseau %3$s</string>
<string name="receive_bottom_sheet_warning_message_full">Envoyez uniquement %s à cette adresse. L\'envoi de toute autre devise entraînera sa perte irréversible.</string>
<string name="receive_token_description">Affichez un code QR ou partagez votre adresse</string>
<string name="receive_token_description">Transférez des fonds depuis un autre portefeuille ou une autre bourse</string>
<string name="referral_button_participate">Participer</string>
<string name="referral_error_failed_to_load_info">Échec du chargement des informations sur le programme de parrainage. Veuillez réessayer plus tard.</string>
<string name="referral_error_failed_to_load_info_with_reason">Échec du chargement des informations sur le programme de parrainage. Code d\'erreur : %s. Veuillez réessayer plus tard.</string>
@ -634,6 +645,10 @@
<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_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>
<string name="send_summary_transaction_description_suffix_fee_reduced">les frais de réseau seront réduits en utilisant %1$s énergie</string>
<string name="send_summary_transaction_description_suffix_including">y compris des frais de réseau de %1$s</string>
<string name="send_transaction_success">La transaction a été signée avec succès et envoyée au nœud de blockchain. Le solde du portefeuille sera mis à jour après un certain temps</string>
<string name="send_tron_account_activation_error">%1$s est un actif du réseau Tron. Pour calculer les frais et effectuer une transaction, déposez du Tron (TRX) sur votre compte.</string>
<string name="sent_transaction_sent_title">Transaction envoyée</string>
@ -644,6 +659,8 @@
<string name="staking_amount_requirement_error">Le montant à staker doit être au moins %s</string>
<string name="staking_amount_tron_integer_error">Le montant du staking sera arrondi à %1$s TRX en raison des règles du réseau.</string>
<string name="staking_claim_unstaked">Réclamation déstakée</string>
<string name="staking_details_account_fee">Frais de staking du compte</string>
<string name="staking_details_account_fee_info">Un compte de staking est un compte spécial où sont stockés les jetons SOL stakés. Il est créé lorsque vous déléguez vos jetons à un validateur pour participer à la validation des transactions et gagner des récompenses. Des frais minimes sont facturés pour la création du compte de staking, qui sont restitués une fois le staking terminé.</string>
<string name="staking_details_annual_percentage_rate">Pourcentage de rendement annuel</string>
<string name="staking_details_annual_percentage_rate_info">Le pourcentage de rendement annuel que vous pouvez gagner en participant au staking.</string>
<string name="staking_details_apr">APR</string>
@ -671,14 +688,25 @@
<string name="staking_migrate">Migrer</string>
<string name="staking_native">Native staking</string>
<string name="staking_notification_claim_rewards_text">Récomp. gagnées vous seront envoyées et dispo pour utilisation immédiate</string>
<string name="staking_notification_earn_rewards_text">Stakez et commencez à gagner vos récompenses</string>
<string name="staking_notification_earn_rewards_text_daily">Stakez en toute sécurité et commencez à gagner des récompenses quotidiennes</string>
<string name="staking_notification_earn_rewards_text_hourly">Stakez en toute sécurité et commencez à gagner des récompenses horaires</string>
<string name="staking_notification_earn_rewards_text_monthly">Stakez en toute sécurité et commencez à gagner des récompenses mensuelles</string>
<string name="staking_notification_earn_rewards_text_period_day">Le staking vous permet de gagner %1$s. Vos récompenses de staking arrivent tous les jours.</string>
<string name="staking_notification_earn_rewards_text_period_hour">Le staking vous permet de gagner %1$s. Vos récompenses de staking arrivent toutes les heures.</string>
<string name="staking_notification_earn_rewards_text_period_month">Le staking vous permet de gagner %1$s. Vos récompenses de staking arrivent tous les mois.</string>
<string name="staking_notification_earn_rewards_text_period_week">Le staking vous permet de gagner %1$s. Vos récompenses de staking arrivent toutes les semaines.</string>
<string name="staking_notification_earn_rewards_text_weekly">Stakez en toute sécurité et commencez à gagner des récompenses hebdomadaires</string>
<string name="staking_notification_earn_rewards_title">Gagnez des récompenses de staking</string>
<string name="staking_notification_network_error_text">L\'option de staking n\'est actuellement pas disponible en raison des conditions du réseau. Veuillez réessayer plus tard.</string>
<string name="staking_notification_new_validator_funds_transfer">Le staking dans le réseau %1$s avec un nouveau validateur transférera automatiquement tous les fonds précédemment stakés vers ce validateur</string>
<string name="staking_notification_restake_rewards_text">Réinvestissez vos récompenses gagnées dans le montant que vous avez staké, augmentant ainsi vos gains potentiels.</string>
<string name="staking_notification_unlock_text">Débloquez votre argent pour le retirer du processus de staking. Le déverrouillage prend %s.</string>
<string name="staking_notification_unstake_cosmos_text">Vos fonds seront disponibles à l\'utilisation après la période de déblocage de 21 jours. La récompense sera retirée en même temps que vos fonds de déblocage.</string>
<string name="staking_notification_unstake_text">Vos fonds seront disponibles pour utilisation après la période de désengagement %s.</string>
<string name="staking_notification_withdraw_text">Vous pouvez désormais retirer vos fonds, ils seront disponibles à l\'utilisation immédiatement</string>
<string name="staking_notifications_revote_tron_text">Le staking dans le réseau Tron avec un nouveau validateur transférera automatiquement tous les fonds précédemment stakés vers ce validateur</string>
<string name="staking_preparing">En cours de préparation</string>
<string name="staking_ready_to_withdraw">Prêt à retirer</string>
<string name="staking_rebond">Réassocier</string>
<string name="staking_restake">Restakez</string>
@ -698,6 +726,7 @@
<string name="staking_rewards">Récompenses</string>
<string name="staking_stake_locked">Stake verrouillé</string>
<string name="staking_stake_more">Staker plus</string>
<string name="staking_summary_description_text">Vous stakez %1$s et recevrez %2$s par an</string>
<string name="staking_tap_to_unlock">Appuyez pour déverrouiller</string>
<string name="staking_tap_to_withdraw">Appuyez pour retirer</string>
<string name="staking_title_stake">Stake %s</string>
@ -705,8 +734,10 @@
<string name="staking_transaction_in_progress_text">La transaction est en cours de traitement ! La validation est actuellement en cours dans la blockchain. Cela peut prendre quelques minutes.</string>
<string name="staking_unbonding">Dissociation</string>
<string name="staking_unlocked_locked">Débloquer</string>
<string name="staking_unlocking">Déverrouillage</string>
<string name="staking_unstaked">Non-staké</string>
<string name="staking_unstaking">Unstaking</string>
<string name="staking_unstaking_item_name">En train de destaker les actifs %s</string>
<string name="staking_validator">Validateur</string>
<string name="staking_validators">Validateurs</string>
<string name="staking_vote">Voter</string>
@ -846,6 +877,8 @@
<string name="warning_backup_errors_title">Erreur d\'activation</string>
<string name="warning_beacon_chain_retirement_content">Selon les développeurs du réseau BNB, le support de la norme BEP-2\nprendra fin en juin 2024. Pour éviter de perdre des actifs avec cette norme, veuillez les convertir à la norme BEP-20. Utilisez notre service de d\'échange pour les transférer sur le réseau BNB Smart Chain.</string>
<string name="warning_beacon_chain_retirement_title">BNB Beacon Chain va s\'arrêter de fonctionner</string>
<string name="warning_blocked_funds_for_fee_message">Veuillez déposer environ %1$s pour couvrir les frais de réseau</string>
<string name="warning_blocked_funds_for_fee_title">Fonds insuffisants pour couvrir les frais de réseau</string>
<string name="warning_button_could_be_better">Pas terrible</string>
<string name="warning_button_like_it">J\'aime</string>
<string name="warning_button_ok">Ok, compris!</string>

View file

@ -383,24 +383,31 @@
<string name="markets_token_details_buy_pressure_full">買い圧力</string>
<string name="markets_token_details_circulating_supply">循環供給量</string>
<string name="markets_token_details_circulating_supply_description">取引可能で市場に流通しているコインの総数</string>
<string name="markets_token_details_circulating_supply_full">循環供給量</string>
<string name="markets_token_details_experienced_buyers">経験豊富な買い手</string>
<string name="markets_token_details_experienced_buyers_description">少なくとも100の発信取引を持つネット・バイヤー</string>
<string name="markets_token_details_experienced_buyers_full">経験豊富な買い手</string>
<string name="markets_token_details_fully_diluted_valuation">完全希薄化後評価額</string>
<string name="markets_token_details_fully_diluted_valuation_description">現在流通していないものも含め、存在する可能性のあるすべてのコインが流通している場合の暗号資産の理論上の合計価値</string>
<string name="markets_token_details_fully_diluted_valuation_full">完全希薄化後評価額</string>
<string name="markets_token_details_genesis_date">ジェネシスの日付</string>
<string name="markets_token_details_high">高い</string>
<string name="markets_token_details_holders">ホルダー</string>
<string name="markets_token_details_holders_description">特定の期間内のトークンホルダー数の変化</string>
<string name="markets_token_details_holders_full">ホルダー</string>
<string name="markets_token_details_insights">インサイト</string>
<string name="markets_token_details_links">リンク</string>
<string name="markets_token_details_liquidity">流動性</string>
<string name="markets_token_details_liquidity_description">指定された期間中のトークンに利用可能な流動性の変化</string>
<string name="markets_token_details_liquidity_full">流動性</string>
<string name="markets_token_details_liquidity_index">流動性指数</string>
<string name="markets_token_details_low">低い</string>
<string name="markets_token_details_market_capitalization">時価総額</string>
<string name="markets_token_details_market_capitalization_description">暗号資産の市場価値の合計。コインの現在の価格と、流通しているコインの総数を掛けて計算されます。</string>
<string name="markets_token_details_market_capitalization_full">時価総額</string>
<string name="markets_token_details_market_rating">市場格付け</string>
<string name="markets_token_details_market_rating_description">時価総額に基づくすべてのコイン間の暗号資産評価における位置</string>
<string name="markets_token_details_market_rating_full">市場格付け</string>
<string name="markets_token_details_max_supply">最大供給量</string>
<string name="markets_token_details_metrics">指標</string>
<string name="markets_token_details_official_links">公式リンク</string>
@ -410,8 +417,10 @@
<string name="markets_token_details_social">ソーシャル</string>
<string name="markets_token_details_total_supply">総供給量</string>
<string name="markets_token_details_total_supply_description">特定の暗号資産に存在しうるコインまたはトークンの最大数</string>
<string name="markets_token_details_total_supply_full">総供給量</string>
<string name="markets_token_details_trading_volume">取引量24時間</string>
<string name="markets_token_details_trading_volume_24h_description">過去24時間以内に取引された暗号資産の合計額。市場の活発さと流動性を示します。</string>
<string name="markets_token_details_trading_volume_full">取引量24時間</string>
<string name="markets_tooltip_message">これをドラッグするか、検索窓をタップして、マーケットから直接トークンを追加します</string>
<string name="markets_tooltip_title">トークンを追加</string>
<string name="nfc_error_unavailable">お使いのデバイスではNFCが使用できません</string>
@ -671,6 +680,7 @@
<string name="staking_migrate">移行</string>
<string name="staking_native">ネイティブステーキング</string>
<string name="staking_notification_claim_rewards_text">獲得した報酬はあなたのアドレスに直接送られ、すぐ使用可能です。</string>
<string name="staking_notification_earn_rewards_text">安全にステーキングして報酬を獲得しましょう</string>
<string name="staking_notification_earn_rewards_text_daily">安全にステーキングして、報酬を毎日獲得しましょう</string>
<string name="staking_notification_earn_rewards_text_hourly">安全にステーキングして、報酬を毎時間獲得しましょう</string>
<string name="staking_notification_earn_rewards_text_monthly">安全にステーキングして、報酬を毎月獲得しましょう</string>

View file

@ -84,6 +84,7 @@
<string name="common_buy_currency">Перейти на %1$s</string>
<string name="common_camera_denied_alert_message">Вы не предоставили доступ к камере, пожалуйста, измените настройки конфиденциальности.</string>
<string name="common_cancel">Отмена</string>
<string name="common_choose_action">Выберите действие</string>
<string name="common_claim">Получить</string>
<string name="common_claim_rewards">Вывести награду</string>
<string name="common_close">Закрыть</string>
@ -276,7 +277,7 @@
<string name="express_token_list_empty_search">Токены не найдены. Пожалуйста, попробуйте другой запрос</string>
<string name="express_transaction_id">ID: %s</string>
<string name="express_transaction_id_copied">ID транзакции скопирован</string>
<string name="exсhange_token_description">Конвертируйте одну из ваших валют в другую</string>
<string name="exсhange_token_description">Обменяйте любой актив в вашем портфеле на этот токен</string>
<string name="feedback_data_collection_message">Информация ниже не является обязательной. Вы можете стереть её, если хотите.</string>
<string name="feedback_preface_rate_negative">Расскажите, каких функций вам не хватает, и мы постараемся вам помочь.</string>
<string name="feedback_preface_scan_failed">Скажите, пожалуйста, какая у вас карта?</string>
@ -344,7 +345,7 @@
<string name="manage_tokens_unavailable_vote">Голосовать</string>
<string name="manage_tokens_wallet_selector_title">Выберите кошелек</string>
<string name="manage_tokens_wallet_support_only_one_network_title">Кошелёк не поддерживает более одной сети</string>
<string name="markets_add_to_my_portfolio_description">Чтобы купить, обменять или получить данный токен вам нужно добавить его к себе в портфель</string>
<string name="markets_add_to_my_portfolio_description">Чтобы купить, обменять или получить данный токен, вам нужно добавить его к себе в портфель</string>
<string name="markets_add_to_my_portfolio_unavailable_description">Этот актив недоступен</string>
<string name="markets_add_to_portfolio_button">Добавить в портфель</string>
<string name="markets_add_token">Добавить</string>
@ -387,27 +388,34 @@
<string name="markets_token_details_blockchain_site">Веб-сайт</string>
<string name="markets_token_details_buy_pressure">Покуп. предпоч.</string>
<string name="markets_token_details_buy_pressure_description">Разница между объемом покупателей и продавцов</string>
<string name="markets_token_details_buy_pressure_full">Покуп. предпоч.</string>
<string name="markets_token_details_buy_pressure_full">Покупательское предпочтение</string>
<string name="markets_token_details_circulating_supply">Циркулир. предл.</string>
<string name="markets_token_details_circulating_supply_description">Общее количество монет, доступных для торговли и находящихся в обращении на рынке</string>
<string name="markets_token_details_circulating_supply_full">Циркулирующее предложение</string>
<string name="markets_token_details_experienced_buyers">Опытные трейдеры</string>
<string name="markets_token_details_experienced_buyers_description">Покупатели, у которых было как минимум 100 исходящих транзакций.</string>
<string name="markets_token_details_experienced_buyers_full">Опытные трейдеры</string>
<string name="markets_token_details_fully_diluted_valuation">Полн. разб. кап.</string>
<string name="markets_token_details_fully_diluted_valuation_description">Общая теоретическая стоимость криптовалюты, если все монеты, которые могут существовать, находятся в обращении, включая те, которые в настоящее время не обращаются</string>
<string name="markets_token_details_fully_diluted_valuation_full">Полностью разбавленная капитализация</string>
<string name="markets_token_details_genesis_date">Дата создания</string>
<string name="markets_token_details_high">Высокий</string>
<string name="markets_token_details_holders">Держатели</string>
<string name="markets_token_details_holders_description">Изменение количества держателей токенов в течение выбранного периода времени</string>
<string name="markets_token_details_holders_full">Держатели</string>
<string name="markets_token_details_insights">Инсайты</string>
<string name="markets_token_details_links">Ссылки</string>
<string name="markets_token_details_liquidity">Ликвидность</string>
<string name="markets_token_details_liquidity_description">Изменение объема ликвидности, доступной для токена в течение указанного периода времени.</string>
<string name="markets_token_details_liquidity_full">Ликвидность</string>
<string name="markets_token_details_liquidity_index">Индекс ликвидности</string>
<string name="markets_token_details_low">Низкий</string>
<string name="markets_token_details_market_capitalization">Рын. кап.</string>
<string name="markets_token_details_market_capitalization_description">Общая рыночная стоимость криптовалюты, рассчитываемая путем умножения текущей цены монеты на общее количество монет в обращении.</string>
<string name="markets_token_details_market_capitalization_full">Рыночная капитализация</string>
<string name="markets_token_details_market_rating">Рейтинг</string>
<string name="markets_token_details_market_rating_description">Позиция в рейтинге криптовалют среди всех монет на основе рыночной капитализации.</string>
<string name="markets_token_details_market_rating_full">Рейтинг</string>
<string name="markets_token_details_max_supply">Максимальный объем</string>
<string name="markets_token_details_metrics">Метрики</string>
<string name="markets_token_details_official_links">Официальные ссылки</string>
@ -415,10 +423,12 @@
<string name="markets_token_details_repository">Репозиторий</string>
<string name="markets_token_details_security_score">Оценка безопасности</string>
<string name="markets_token_details_social">Социальные</string>
<string name="markets_token_details_total_supply">Общее предложение</string>
<string name="markets_token_details_total_supply">Общ. предл.</string>
<string name="markets_token_details_total_supply_description">Максимальное количество монет или токенов, которое может когда-либо существовать для выбранной криптовалюты.</string>
<string name="markets_token_details_total_supply_full">Общее предложение</string>
<string name="markets_token_details_trading_volume">Объем торгов (24ч)</string>
<string name="markets_token_details_trading_volume_24h_description">Общая сумма криптовалюты, которая была продана за последние 24 часа, показывающая уровень активности и ликвидности на рынке.</string>
<string name="markets_token_details_trading_volume_full">Объем торгов (24ч)</string>
<string name="markets_tooltip_message">Потяните вверх или коснитесь поисковой строки, чтобы добавить токены напрямую из маркета</string>
<string name="markets_tooltip_title">Добавить токены</string>
<string name="nfc_error_unavailable">Функция NFC недоступна на вашем устройстве</string>
@ -647,6 +657,8 @@
<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>
<string name="send_summary_transaction_description_suffix_fee_reduced">Комиссия сети будет снижена за счет использования %1$s энергии</string>
<string name="send_summary_transaction_description_suffix_including">включая комиссию сети в размере %1$s</string>
<string name="send_transaction_success">Транзакция успешно подписана и отправлена в блокчейн. Баланс будет обновлен через некоторое время</string>
<string name="send_tron_account_activation_error">%1$s — это монета в сети Tron. Чтобы рассчитать комиссию и совершить транзакцию, вам необходимо внести немного Tron (TRX) на свой адрес.</string>
@ -658,10 +670,12 @@
<string name="staking_amount_requirement_error">Сумма для стейкинга должна быть не менее %s</string>
<string name="staking_amount_tron_integer_error">Согласно правилам сети, сумма стейкинга будет округлена до %1$sTRX.</string>
<string name="staking_claim_unstaked">Забрать средства</string>
<string name="staking_details_account_fee">Комиссия за стейкинг аккаунт</string>
<string name="staking_details_account_fee_info">Стейкинг аккаунт — это специальный счет, на котором хранятся застейканные токены SOL. Он создается при делегировании ваших токенов валидатору для участия в подтверждении транзакций и получении наград. За создание стейкинг аккаунта взимается небольшая комиссия, которая возвращается после завершения стейкинга.</string>
<string name="staking_details_annual_percentage_rate">Процентная ставка</string>
<string name="staking_details_annual_percentage_rate_info">Годовой процентный доход, который вы можете получить от участия в стейкинге.</string>
<string name="staking_details_apr">APR</string>
<string name="staking_details_auto_claiming_rewards_daily_text">Награда автоматически аккумулируется на вашем стейкинг балансе.</string>
<string name="staking_details_available">Доступно</string>
<string name="staking_details_average_reward_rate">Средння ставка вознаграждения</string>
<string name="staking_details_banner_text">Что такое Стейкинг?</string>
@ -685,14 +699,26 @@
<string name="staking_migrate">Переместить</string>
<string name="staking_native">Нативный стейкинг</string>
<string name="staking_notification_claim_rewards_text">Полученная награда отправится на ваш кошелек и сразу станет доступна для использования</string>
<string name="staking_notification_earn_rewards_text">Стейкайте безопасно и начинайте получать ваши награды.</string>
<string name="staking_notification_earn_rewards_text_daily">Стейкайте безопасно и начинайте получать ежедневные награды.</string>
<string name="staking_notification_earn_rewards_text_hourly">Стейкайте безопасно и начинайте получать награды каждый час.</string>
<string name="staking_notification_earn_rewards_text_monthly">Стейкайте безопасно и начинайте получать ежемесячные награды.</string>
<string name="staking_notification_earn_rewards_text_period_day">Стейкинг дает возможность вам получать %1$s. Награда будет зачисляться каждый день.</string>
<string name="staking_notification_earn_rewards_text_period_hour">Стейкинг дает возможность вам получать %1$s. Награда будет зачисляться каждый час.</string>
<string name="staking_notification_earn_rewards_text_period_month">Стейкинг дает возможность вам получать %1$s. Награда будет зачисляться каждый месяц.</string>
<string name="staking_notification_earn_rewards_text_period_week">Стейкинг дает возможность вам получать %1$s. Награда будет зачисляться каждую неделю.</string>
<string name="staking_notification_earn_rewards_text_weekly">Стейкайте безопасно и начинайте получать еженедельные награды.</string>
<string name="staking_notification_earn_rewards_title">Получите награду за стейкинг</string>
<string name="staking_notification_network_error_text">Стейкинг временно недоступен из-за проблем в сети. Пожалуйста, попробуйте позже.</string>
<string name="staking_notification_new_validator_funds_transfer">Стейкинг в сети %1$s с новым валидатором автоматически переведет ваши текущие застейканные средства на него.</string>
<string name="staking_notification_restake_rewards_text">Реинвестируйте свои заработанные награды в вашу застейканную сумму, увеличивая потенциальный доход</string>
<string name="staking_notification_unlock_text">Разблокируйте свои средства, чтобы вывести их из стейкинга. Разблокировка займёт %s.</string>
<string name="staking_notification_unstake_cosmos_text">Ваши средства будут доступны для использования после 21-дневного периода отзыва. Награда будет выведена вместе с вашими выводими средствами.</string>
<string name="staking_notification_unstake_text">Ваши средства будут доступны после %s периода отзыва.</string>
<string name="staking_notification_withdraw_text">Вы можете вывести свои средства из стейкинга, они будут доступны для использования незамедлительно.</string>
<string name="staking_notifications_revote_tron_text">Стейкинг в сети Tron с новым валидатором автоматически переведет ваши текущие застейканные средства на него.</string>
<string name="staking_preparing">Подготовка</string>
<string name="staking_ready_to_withdraw">Доступно для вывода</string>
<string name="staking_restake">Сменить валидатора</string>
<string name="staking_restake_rewards">Застейкать вознаграждения</string>
<string name="staking_revoke">Отозвать</string>
@ -702,7 +728,6 @@
<string name="staking_reward_schedule_block">Блок</string>
<string name="staking_reward_schedule_day">День</string>
<string name="staking_reward_schedule_each_day">Каждый день</string>
<string name="staking_reward_schedule_each_minute">Каждую минуту</string>
<string name="staking_reward_schedule_epoch">Эпоха</string>
<string name="staking_reward_schedule_era">Эра</string>
<string name="staking_reward_schedule_hour">Час</string>
@ -711,12 +736,15 @@
<string name="staking_rewards">Вознаграждения</string>
<string name="staking_stake_locked">Стейкинг закрыт</string>
<string name="staking_stake_more">Застейкать еще</string>
<string name="staking_summary_description_text">Вы стейкаете %1$s и будете получать %2$s ежегодно</string>
<string name="staking_tap_to_unlock">Нажмите для разблокировки</string>
<string name="staking_tap_to_withdraw">Нажмите для вывода</string>
<string name="staking_title_stake">Застейкать %s</string>
<string name="staking_title_unstake">Вывести %s</string>
<string name="staking_transaction_in_progress_text">Транзакция обрабатывается! В настоящее время идет проверка в блокчейне. Это может занять несколько минут.</string>
<string name="staking_unbonding">Отзыв</string>
<string name="staking_unlocked_locked">Разблокировать</string>
<string name="staking_unlocking">Разблокировка</string>
<string name="staking_unstaked">Вывод из стейкинга</string>
<string name="staking_unstaking">Завершение стейкинга</string>
<string name="staking_unstaking_item_name">Завершение стейкинга %s</string>
@ -725,6 +753,7 @@
<string name="staking_vote">Проголосовать</string>
<string name="staking_vote_locked">Голосование заблокировано</string>
<string name="staking_withdraw">Вывод</string>
<string name="staking_your_stakes">Застейканные средства</string>
<string name="story_awe_description">Держите свои криптосбережения в безопасности. Приватные ключи надежно хранятся на карте.</string>
<string name="story_awe_title">Революционный аппаратный кошелек</string>
<string name="story_backup_description">До трех карт с одним кошельком</string>

View file

@ -39,7 +39,7 @@
<string name="biometric_lockout_warning_title">Забагато спроб</string>
<string name="biometric_unavailable_warning">Ви вимкнули біометричну автентифікацію на своєму телефоні і не зможете зберігати гаманці в додатку. Щоб зберегти гаманці, будь ласка, увімкніть функцію біометричної автентифікації в налаштуваннях телефону.</string>
<string name="button_start_backup_process">Почніть процес резервного копіювання</string>
<string name="buy_token_description">За допомогою банківської картки або банківського рахунку</string>
<string name="buy_token_description">Використовуйте банківську картку або інші способи оплати</string>
<plurals name="card_label_card_count">
<item quantity="one">%d картка</item>
<item quantity="few">%d картки</item>
@ -145,7 +145,7 @@
<string name="common_rename">Перейменувати</string>
<string name="common_save">Зберегти</string>
<string name="common_save_changes">Зберегти зміни</string>
<string name="common_search">Шукати</string>
<string name="common_search">Пошук</string>
<string name="common_search_tokens">Пошук токенів</string>
<string name="common_seed_phrase">Seed-фраза</string>
<string name="common_select_action">Оберіть дію</string>
@ -279,7 +279,7 @@
<string name="express_token_list_empty_search">Токенів не знайдено. Будь ласка, спробуйте інший запит</string>
<string name="express_transaction_id">ID: %s</string>
<string name="express_transaction_id_copied">ID транзакції скопійовано</string>
<string name="exсhange_token_description">З іншої валюти у вашому гаманці</string>
<string name="exсhange_token_description">Конвертуйте одну з ваших валют в іншу</string>
<string name="feedback_data_collection_message">Інформація нижче не є обов\'язковою. Ви можете стерти її, якщо бажаєте.</string>
<string name="feedback_preface_rate_negative">Розкажіть, яких функцій вам не вистачає, і ми спробуємо вам допомогти.</string>
<string name="feedback_preface_scan_failed">Розкажіть, будь ласка, яку картку ви маєте?</string>
@ -362,6 +362,7 @@
<string name="markets_loading_error_title">Не вдалося завантажити дані...</string>
<string name="markets_loading_no_data_title">Немає даних</string>
<string name="markets_quick_actions">Швидкі дії</string>
<string name="markets_search_header_title">Шукати на маркеті</string>
<string name="markets_search_result_title">Результат</string>
<string name="markets_search_see_tokens_under_100k">Переглянути токени до 100к USD ринкової капіталізації</string>
<string name="markets_search_show_tokens">Показати токени</string>
@ -394,24 +395,29 @@
<string name="markets_token_details_buy_pressure_full">Давлення покупця</string>
<string name="markets_token_details_circulating_supply">Циркуляційний запас</string>
<string name="markets_token_details_circulating_supply_description">Загальна кількість монет, які доступні для торгівлі та перебувають в обігу на ринку</string>
<string name="markets_token_details_circulating_supply_full">Циркуляційний запас</string>
<string name="markets_token_details_experienced_buyers">Досвідчені покупці</string>
<string name="markets_token_details_experienced_buyers_description">Мережеві покупці з додатковою вимогою мати не менше 100 вихідних транзакцій</string>
<string name="markets_token_details_experienced_buyers_full">Досвідчені покупці</string>
<string name="markets_token_details_fully_diluted_valuation">Повн. розведена кап.</string>
<string name="markets_token_details_fully_diluted_valuation_description">Загальна теоретична вартість криптовалюти, якщо всі монети, які могли б існувати, перебувають в обігу, включаючи ті, що не перебувають в обігу в даний час</string>
<string name="markets_token_details_genesis_date">Дата створення</string>
<string name="markets_token_details_high">Високий</string>
<string name="markets_token_details_holders">Тримачі</string>
<string name="markets_token_details_holders_description">Зміна кількості власників токенів протягом певного періоду часу</string>
<string name="markets_token_details_holders_full">Тримачі</string>
<string name="markets_token_details_insights">Інсайти</string>
<string name="markets_token_details_links">Посилання</string>
<string name="markets_token_details_liquidity">Ліквідність</string>
<string name="markets_token_details_liquidity_description">Зміна того, скільки ліквідності доступно для токена протягом зазначеного періоду часу</string>
<string name="markets_token_details_liquidity_full">Ліквідність</string>
<string name="markets_token_details_liquidity_index">Індекс ліквідності</string>
<string name="markets_token_details_low">Низький</string>
<string name="markets_token_details_market_capitalization">Рин. кап.</string>
<string name="markets_token_details_market_capitalization_description">Загальна ринкова вартість криптовалюти, що розраховується шляхом множення поточної ціни монети на загальну кількість монет в обігу</string>
<string name="markets_token_details_market_rating">Рейтинг</string>
<string name="markets_token_details_market_rating_description">Позиція в крипторейтингу між усіма монетами на основі ринкової капіталізації</string>
<string name="markets_token_details_market_rating_full">Рейтинг</string>
<string name="markets_token_details_max_supply">Максимальна пропозиція</string>
<string name="markets_token_details_metrics">Метрики</string>
<string name="markets_token_details_official_links">Офіційні посилання</string>
@ -419,10 +425,12 @@
<string name="markets_token_details_repository">Репозиторій</string>
<string name="markets_token_details_security_score">Оцінка безпеки</string>
<string name="markets_token_details_social">Соцмережі</string>
<string name="markets_token_details_total_supply">Загальна пропозиція</string>
<string name="markets_token_details_total_supply">Загальна проп.</string>
<string name="markets_token_details_total_supply_description">Максимальна кількість монет або токенів, яка може коли-небудь існувати для певної криптовалюти</string>
<string name="markets_token_details_total_supply_full">Загальна пропозиція</string>
<string name="markets_token_details_trading_volume">Обсяг торгів (24г)</string>
<string name="markets_token_details_trading_volume_24h_description">Загальна сума криптовалюти, якою торгували протягом останніх 24 годин, що вказує на рівень активності та ліквідності на ринку</string>
<string name="markets_token_details_trading_volume_full">Обсяг торгів (24г)</string>
<string name="markets_tooltip_message">Потягніть вгору або торкніться панелі пошуку, щоб додати токени безпосередньо з маркету</string>
<string name="markets_tooltip_title">Додати токени</string>
<string name="nfc_error_unavailable">Функція NFC недоступна на вашому пристрої</string>
@ -530,7 +538,7 @@
<string name="qr_scanner_camera_denied_title">Доступ до камери заборонено</string>
<string name="receive_bottom_sheet_warning_message">%1$s (%2$s) у мережі %3$s</string>
<string name="receive_bottom_sheet_warning_message_full">Надсилайте лише %s на цю адресу. Надсилання будь-якої іншої валюти призведе до її незворотної втрати.</string>
<string name="receive_token_description">Покажіть QR-код або поділіться своєю адресою</string>
<string name="receive_token_description">Перекажіть кошти з іншого гаманця або біржі</string>
<string name="referral_button_participate">Взяти участь</string>
<string name="referral_error_failed_to_load_info">Не вдалося завантажити інформацію по реферальній програмі. Будь ласка, спробуйте пізніше.</string>
<string name="referral_error_failed_to_load_info_with_reason">Не вдалося завантажити інформацію по реферальній програмі. Код помилки: %s. Будь ласка, спробуйте пізніше.</string>
@ -665,6 +673,8 @@
<string name="staking_amount_requirement_error">Сума для стейкінгу має бути не менше %s</string>
<string name="staking_amount_tron_integer_error">Сума стейкінгу буде округлена до %1$s TRX відповідно до правил мережі.</string>
<string name="staking_claim_unstaked">Зняти кошти</string>
<string name="staking_details_account_fee">Комісія за стейкінг-акаунт</string>
<string name="staking_details_account_fee_info">Стейкінг-акаунт - це спеціальний рахунок, на якому зберігаються застейкані SOL токени. Він створюється, коли ви делегуєте свої токени валідатору для участі у перевірці транзакцій та отримання винагород. За створення стейкінг-акаунту стягується невелика комісія, яка повертається після завершення стейкінгу.</string>
<string name="staking_details_annual_percentage_rate">Процентна ставка</string>
<string name="staking_details_annual_percentage_rate_info">Річний відсоток, який ви можете отримати, беручи участь у стейкінгу.</string>
<string name="staking_details_apr">APR</string>
@ -692,6 +702,7 @@
<string name="staking_migrate">Перемістити</string>
<string name="staking_native">Нативний стейкінг</string>
<string name="staking_notification_claim_rewards_text">Зароблені винагороди будуть надіслані на ваш гаманець і доступні для використання відразу</string>
<string name="staking_notification_earn_rewards_text">Стейкайте безпечно та почніть отримувати ваші винагороди</string>
<string name="staking_notification_earn_rewards_text_daily">Стейкайте безпечно та почніть отримувати винагороди щоденно</string>
<string name="staking_notification_earn_rewards_text_hourly">Стейкайте безпечно та почніть отримувати винагороди щогодини</string>
<string name="staking_notification_earn_rewards_text_monthly">Стейкайте безпечно та почніть отримувати винагороди щомісяця</string>

View file

@ -103,7 +103,7 @@
<string name="common_enable">Enable</string>
<string name="common_enabled">Enabled</string>
<string name="common_error">Error</string>
<string name="common_exchange">Exchange</string>
<string name="common_exchange">Swap</string>
<string name="common_explore">Explore</string>
<string name="common_explore_transaction_history">Explore transaction history</string>
<string name="common_explorer">Explorer</string>
@ -275,7 +275,7 @@
<string name="express_token_list_empty_search">No tokens found. Please try another request</string>
<string name="express_transaction_id">ID: %s</string>
<string name="express_transaction_id_copied">Transaction ID copied</string>
<string name="exсhange_token_description">Convert one of your currencies to another</string>
<string name="exсhange_token_description">Swap any asset in your portfolio for this token</string>
<string name="feedback_data_collection_message">The following information is optional. You can erase it if you don\'t want to share it.</string>
<string name="feedback_preface_rate_negative">Tell us what functions you are missing, and we will try to help you.</string>
<string name="feedback_preface_scan_failed">Please tell us what card do you have</string>
@ -387,24 +387,31 @@
<string name="markets_token_details_buy_pressure_full">Buy pressure</string>
<string name="markets_token_details_circulating_supply">Circulating supply</string>
<string name="markets_token_details_circulating_supply_description">The total number of coins that are available for trading and are circulating in the market</string>
<string name="markets_token_details_circulating_supply_full">Circulating supply</string>
<string name="markets_token_details_experienced_buyers">Experienced buyers</string>
<string name="markets_token_details_experienced_buyers_description">Net buyers with the additional requirement of having at least 100 outgoing transactions</string>
<string name="markets_token_details_experienced_buyers_full">Experienced buyers</string>
<string name="markets_token_details_fully_diluted_valuation">Fully diluted valuation</string>
<string name="markets_token_details_fully_diluted_valuation_description">The total theoretical value of a cryptocurrency if all coins that could exist are in circulation, including those not currently circulating</string>
<string name="markets_token_details_fully_diluted_valuation_full">Fully diluted valuation</string>
<string name="markets_token_details_genesis_date">Genesis date</string>
<string name="markets_token_details_high">High</string>
<string name="markets_token_details_holders">Holders</string>
<string name="markets_token_details_holders_description">The change in the number of token holders within a specific timeframe</string>
<string name="markets_token_details_holders_full">Holders</string>
<string name="markets_token_details_insights">Insights</string>
<string name="markets_token_details_links">Links</string>
<string name="markets_token_details_liquidity">Liquidity</string>
<string name="markets_token_details_liquidity_description">The change in how much liquidity is available for the token during the specified timeframe</string>
<string name="markets_token_details_liquidity_full">Liquidity</string>
<string name="markets_token_details_liquidity_index">Liquidity index</string>
<string name="markets_token_details_low">Low</string>
<string name="markets_token_details_market_capitalization">Market cap</string>
<string name="markets_token_details_market_capitalization_description">The total market value of a cryptocurrency, calculated by multiplying the current price of the coin by the total number of coins in circulation</string>
<string name="markets_token_details_market_capitalization_full">Market cap</string>
<string name="markets_token_details_market_rating">Market rating</string>
<string name="markets_token_details_market_rating_description">Position in crypto rating between all coins based on market capitalization</string>
<string name="markets_token_details_market_rating_full">Market rating</string>
<string name="markets_token_details_max_supply">Max supply</string>
<string name="markets_token_details_metrics">Metrics</string>
<string name="markets_token_details_official_links">Official links</string>
@ -414,8 +421,10 @@
<string name="markets_token_details_social">Social</string>
<string name="markets_token_details_total_supply">Total supply</string>
<string name="markets_token_details_total_supply_description">The maximum number of coins or tokens that can ever exist for a particular cryptocurrency</string>
<string name="markets_token_details_total_supply_full">Total supply</string>
<string name="markets_token_details_trading_volume">Trading volume (24h)</string>
<string name="markets_token_details_trading_volume_24h_description">The total amount of a cryptocurrency that has been traded within the last 24 hours, indicating the level of activity and liquidity in the market</string>
<string name="markets_token_details_trading_volume_full">Trading volume (24h)</string>
<string name="markets_tooltip_message">Pull this up or tap the search bar to add tokens directly from the market</string>
<string name="markets_tooltip_title">Add tokens</string>
<string name="nfc_error_unavailable">NFC is not available on your device</string>
@ -689,6 +698,7 @@
<string name="staking_notification_earn_rewards_text_period_week">Staking allows you to earn %1$s. Your staking rewards arrive every week.</string>
<string name="staking_notification_earn_rewards_text_weekly">Stake securely and start earning weekly rewards</string>
<string name="staking_notification_earn_rewards_title">Earn staking rewards</string>
<string name="staking_notification_network_error_text">Staking is currently unavailable due to network conditions. Please try again later.</string>
<string name="staking_notification_new_validator_funds_transfer">Staking in the %1$s network with a new validator will automatically transfer all previously staked funds to this validator</string>
<string name="staking_notification_restake_rewards_text">Reinvests your earned rewards in your staked amount, increasing potential earnings.</string>
<string name="staking_notification_unlock_text">Unlock your money to withdraw it from staking process. Unlocking takes %s.</string>
@ -707,8 +717,7 @@
<string name="staking_reward_claiming_manual">Manual</string>
<string name="staking_reward_schedule_block">Block</string>
<string name="staking_reward_schedule_day">Day</string>
<string name="staking_reward_schedule_each_day">Each day</string>
<string name="staking_reward_schedule_each_minute">Each minute</string>
<string name="staking_reward_schedule_each_day">Daily</string>
<string name="staking_reward_schedule_epoch">Epoch</string>
<string name="staking_reward_schedule_era">Era</string>
<string name="staking_reward_schedule_hour">Hour</string>

View file

@ -20,6 +20,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.tangem.core.ui.components.ResizableText
import com.tangem.core.ui.res.TangemTheme
@ -85,7 +86,9 @@ fun TangemButton(
},
icon = { iconResId ->
Icon(
modifier = Modifier.buttonContentSize(maxContentSize),
modifier = Modifier
.buttonContentSize(maxContentSize)
.padding(vertical = 2.dp),
painter = painterResource(id = iconResId),
tint = colors.contentColor(enabled = enabled).value,
contentDescription = null,

View file

@ -33,9 +33,8 @@ internal fun TangemButtonSize.toHeightDp(): Dp = when (this) {
@Composable
@ReadOnlyComposable
internal fun TangemButtonSize.toShape(): Shape = when (this) {
TangemButtonSize.Default,
TangemButtonSize.WideAction,
-> TangemTheme.shapes.roundedCornersMedium
TangemButtonSize.Default -> TangemTheme.shapes.roundedCornersXMedium
TangemButtonSize.WideAction -> TangemTheme.shapes.roundedCornersMedium
TangemButtonSize.Text -> TangemTheme.shapes.roundedCornersSmall
TangemButtonSize.Selector -> TangemTheme.shapes.roundedCornersSmall
TangemButtonSize.Action -> TangemTheme.shapes.roundedCornersMedium
@ -64,8 +63,8 @@ internal fun TangemButtonSize.toContentPadding(icon: TangemButtonIconPosition):
return when (this) {
TangemButtonSize.Default -> PaddingValues(
top = TangemTheme.dimens.spacing14,
bottom = TangemTheme.dimens.spacing14,
top = TangemTheme.dimens.spacing12,
bottom = TangemTheme.dimens.spacing12,
start = horizontalPadding.first,
end = horizontalPadding.second,
)

View file

@ -24,6 +24,7 @@ import com.tangem.core.ui.components.inputrow.inner.InputRowAsyncImage
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveAnnotatedReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -38,10 +39,12 @@ import com.tangem.core.ui.res.TangemThemePreview
* @param subtitleColor subtitle text color
* @param captionColor caption text color
* @param isGrayscaleImage whether to display grayscale image
* @param subtitleEndIconRes icon to show after subtitle
* @param iconEndRes icon to end of row
* @param onImageError composable to show if image loading failed
* @param extraContent extra content
*/
@Suppress("LongMethod")
@Composable
internal fun InputRowImageBase(
subtitle: TextReference,
@ -53,7 +56,9 @@ internal fun InputRowImageBase(
captionColor: Color = TangemTheme.colors.text.tertiary,
iconTint: Color = TangemTheme.colors.icon.informative,
isGrayscaleImage: Boolean = false,
iconEndRes: Int? = null,
@DrawableRes subtitleEndIconRes: Int? = null,
subtitleEndIconTint: Color = TangemColorPalette.Azure,
@DrawableRes iconEndRes: Int? = null,
onImageError: (@Composable () -> Unit)? = null,
extraContent: (@Composable RowScope.() -> Unit)? = null,
) {
@ -89,11 +94,17 @@ internal fun InputRowImageBase(
SpacerW12()
}
Column {
Text(
text = subtitle.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = subtitleColor,
)
Row {
Text(
text = subtitle.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = subtitleColor,
)
SubtitleEndIconRes(
subtitleEndIconRes = subtitleEndIconRes,
subtitleEndIconTint = subtitleEndIconTint,
)
}
if (caption != null) {
Text(
text = caption.resolveAnnotatedReference(),
@ -113,11 +124,28 @@ internal fun InputRowImageBase(
}
}
@Composable
private fun RowScope.SubtitleEndIconRes(subtitleEndIconRes: Int?, subtitleEndIconTint: Color) {
AnimatedVisibility(
visible = subtitleEndIconRes != null,
label = "Subtitle end icon visibility animation",
modifier = Modifier.align(Alignment.CenterVertically),
) {
val icon = remember(this) { requireNotNull(subtitleEndIconRes) }
Icon(
painter = rememberVectorPainter(image = ImageVector.vectorResource(id = icon)),
tint = subtitleEndIconTint,
contentDescription = null,
modifier = Modifier.padding(start = TangemTheme.dimens.spacing4),
)
}
}
@Composable
private fun RowScope.InputRowEndIcon(iconRes: Int?) {
AnimatedVisibility(
visible = iconRes != null,
label = "Icon visibility animation",
label = "End icon visibility animation",
) {
val icon = remember(this) { requireNotNull(iconRes) }
Icon(

View file

@ -34,6 +34,7 @@ import com.tangem.core.ui.res.TangemThemePreview
* @param subtitleColor subtitle text color
* @param captionColor caption text color
* @param isGrayscaleImage whether to display grayscale image
* @param showPendingIcon whether to show pending icon
* @param iconEndRes icon to end of row
* @param onImageError composable to show if image loading failed
*/
@ -52,6 +53,7 @@ fun InputRowImageInfo(
captionColor: Color = TangemTheme.colors.text.tertiary,
iconTint: Color = TangemTheme.colors.icon.informative,
isGrayscaleImage: Boolean = false,
@DrawableRes subtitleEndIconRes: Int? = null,
@DrawableRes iconEndRes: Int? = null,
onImageError: (@Composable () -> Unit)? = null,
) {
@ -76,6 +78,7 @@ fun InputRowImageInfo(
subtitleColor = subtitleColor,
captionColor = captionColor,
isGrayscaleImage = isGrayscaleImage,
subtitleEndIconRes = subtitleEndIconRes,
iconEndRes = iconEndRes,
onImageError = onImageError,
) {
@ -132,6 +135,7 @@ private fun InputRowImageInfo_Preview(
infoTitle = data.infoTitle,
infoSubtitle = data.infoSubtitle,
imageUrl = "",
subtitleEndIconRes = data.subtitleEndIconRes,
iconEndRes = R.drawable.ic_chevron_right_24,
)
}
@ -162,6 +166,22 @@ private class InputRowImageInfoPreviewDataProvider : PreviewParameterProvider<In
infoTitle = stringReference("5431231231231231231231232 USD"),
infoSubtitle = null,
),
InputRowImageInfoPreviewData(
title = stringReference("Validator"),
subtitle = stringReference("Binance"),
caption = combinedReference(
resourceReference(R.string.staking_details_apr),
annotatedReference(
buildAnnotatedString {
append(" ")
append("3,54%")
},
),
),
infoTitle = stringReference("5431231231231231231231232 USD"),
infoSubtitle = stringReference("5 SOL"),
subtitleEndIconRes = R.drawable.ic_staking_pending_transaction,
),
)
}
@ -171,5 +191,6 @@ private data class InputRowImageInfoPreviewData(
val caption: TextReference?,
val infoTitle: TextReference,
val infoSubtitle: TextReference?,
@DrawableRes val subtitleEndIconRes: Int? = null,
)
// endregion

View file

@ -0,0 +1,19 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="15dp"
android:height="4dp"
android:viewportWidth="15"
android:viewportHeight="4">
<path
android:pathData="M13.5,3.5C12.672,3.5 12,2.828 12,2C12,1.172 12.672,0.5 13.5,0.5C14.328,0.5 15,1.172 15,2C15,2.828 14.328,3.5 13.5,3.5Z"
android:fillColor="#0099FF"/>
<path
android:pathData="M7.5,3.5C6.672,3.5 6,2.828 6,2C6,1.172 6.672,0.5 7.5,0.5C8.328,0.5 9,1.172 9,2C9,2.828 8.328,3.5 7.5,3.5Z"
android:strokeAlpha="0.55"
android:fillColor="#0099FF"
android:fillAlpha="0.55"/>
<path
android:pathData="M1.5,3.5C0.672,3.5 0,2.828 0,2C0,1.172 0.672,0.5 1.5,0.5C2.328,0.5 3,1.172 3,2C3,2.828 2.328,3.5 1.5,3.5Z"
android:strokeAlpha="0.25"
android:fillColor="#0099FF"
android:fillAlpha="0.25"/>
</vector>

View file

@ -103,6 +103,7 @@ internal class DefaultMarketsTokenRepository(
val tokenMarketsUpdateFetcher = MarketsBatchUpdateFetcher(
tangemTechApi = tangemTechApi,
marketsApi = marketsApi,
analyticsEventHandler = analyticsEventHandler,
onApiError = {
analyticsEventHandler.send(MarketsDataAnalyticsEvent.List.Error.toEvent())
},
@ -141,7 +142,19 @@ internal class DefaultMarketsTokenRepository(
response.getOrThrow()
}
return TokenChartConverter.convert(interval, result)
return TokenChartConverter.convert(
interval = interval,
value = result,
// === Analytics ===
onNullPresented = {
analyticsEventHandler.send(
MarketsDataAnalyticsEvent.ChartNullValuesError(
requestPath = "coins/history",
),
)
},
)
}
override suspend fun getChartPreview(
@ -163,7 +176,19 @@ internal class DefaultMarketsTokenRepository(
)
}
return TokenChartConverter.convert(interval, chart)
return TokenChartConverter.convert(
interval = interval,
value = chart,
// === Analytics ===
onNullPresented = {
analyticsEventHandler.send(
MarketsDataAnalyticsEvent.ChartNullValuesError(
requestPath = "coins/history_preview",
),
)
},
)
}
override suspend fun getTokenInfo(

View file

@ -1,6 +1,8 @@
package com.tangem.data.markets
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.data.common.utils.retryOnError
import com.tangem.data.markets.analytics.MarketsDataAnalyticsEvent
import com.tangem.data.markets.converters.TokenMarketChartsConverter
import com.tangem.data.markets.converters.TokenQuotesShortConverter
import com.tangem.data.markets.converters.toRequestParam
@ -22,6 +24,7 @@ import kotlinx.coroutines.launch
internal class MarketsBatchUpdateFetcher(
private val marketsApi: TangemTechMarketsApi,
private val tangemTechApi: TangemTechApi,
private val analyticsEventHandler: AnalyticsEventHandler,
private val onApiError: () -> Unit,
) : BatchUpdateFetcher<Int, List<TokenMarket>, TokenMarketUpdateRequest> {
@ -52,6 +55,7 @@ internal class MarketsBatchUpdateFetcher(
updateTasks.forEachIndexed { index, deferred ->
launch {
val res = deferred.await()
checkForNulls(res)
val batchToUpdate = toUpdate[index]
update {
@ -113,6 +117,22 @@ internal class MarketsBatchUpdateFetcher(
)
}
private fun checkForNulls(response: TokenMarketChartListResponse) {
response.values.forEach { chart ->
chart.prices.forEach { (_, price) ->
if (price == null) {
analyticsEventHandler.send(
MarketsDataAnalyticsEvent.ChartNullValuesError(
requestPath = "coins/history_preview",
),
)
return
}
}
}
}
private inline fun <T> catchApiError(onError: () -> Unit, block: () -> T): T {
return try {
block()

View file

@ -36,7 +36,20 @@ sealed interface MarketsDataAnalyticsEvent {
}
fun toEvent(): AnalyticsEvent = when (this) {
is ChartNullValuesError -> this
is List -> this
is Details -> this
}
data class ChartNullValuesError(
val requestPath: String,
) : AnalyticsEvent(
category = "Markets / Chart",
event = "Data Error",
params = mapOf("Request path" to requestPath),
error = IllegalStateException(
"Chart data contains null values from the API",
),
),
MarketsDataAnalyticsEvent
}

View file

@ -6,11 +6,21 @@ import com.tangem.domain.markets.TokenChart
internal object TokenChartConverter {
fun convert(interval: PriceChangeInterval, value: TokenMarketChartResponse): TokenChart {
fun convert(
interval: PriceChangeInterval,
value: TokenMarketChartResponse,
onNullPresented: () -> Unit = {},
): TokenChart {
val points = value.prices.mapNotNull { p -> p.value?.let { p.key to it } }.toMap()
if (points.size < points.values.size) {
onNullPresented()
}
return TokenChart(
interval = interval,
priceY = value.prices.values.toList(),
timeStamps = value.prices.keys.toList(),
priceY = points.values.toList(),
timeStamps = points.keys.toList(),
)
}
}

View file

@ -0,0 +1,27 @@
package com.tangem.data.staking
import com.tangem.domain.staking.model.PendingTransaction
import com.tangem.domain.staking.model.stakekit.BalanceItem
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
import java.util.concurrent.CopyOnWriteArrayList
internal class DefaultStakingPendingTransactionRepository : StakingPendingTransactionRepository {
private val pendingTransactions = CopyOnWriteArrayList<PendingTransaction>()
override fun saveTransaction(transaction: PendingTransaction) {
pendingTransactions.add(transaction)
}
override fun removeTransactions(transactions: Set<PendingTransaction>) {
pendingTransactions.removeAll(transactions)
}
override fun getTransactionsWithBalanceItems(): List<Pair<PendingTransaction, BalanceItem>> {
return pendingTransactions.mapNotNull { pendingTransaction ->
PendingTransactionItemConverter.convert(pendingTransaction)?.let { balanceItem ->
pendingTransaction to balanceItem
}
}
}
}

View file

@ -0,0 +1,22 @@
package com.tangem.data.staking
import com.tangem.domain.staking.model.PendingTransaction
import com.tangem.domain.staking.model.stakekit.BalanceItem
import com.tangem.utils.converter.Converter
import org.joda.time.DateTime
internal object PendingTransactionItemConverter : Converter<PendingTransaction, BalanceItem?> {
override fun convert(value: PendingTransaction): BalanceItem? {
return BalanceItem(
groupId = value.groupId ?: return null,
type = value.type ?: return null,
amount = value.amount ?: return null,
rawCurrencyId = value.rawCurrencyId,
validatorAddress = value.validator?.address,
date = DateTime.now(),
pendingActions = emptyList(),
isPending = true,
)
}
}

View file

@ -19,12 +19,10 @@ internal class YieldBalanceConverter : Converter<YieldBalanceWrapperDTO, YieldBa
balance = YieldBalanceItem(
items = value.balances.map { item ->
BalanceItem(
id = item.groupId,
groupId = item.groupId,
type = BalanceType.valueOf(item.type.name),
amount = item.amount,
pricePerShare = item.pricePerShare,
rawCurrencyId = item.tokenDTO.coinGeckoId,
rawNetworkId = item.tokenDTO.network.name,
// tron-specific. operates validatorAddresses instead of validatorAddress
validatorAddress = item.validatorAddress ?: item.validatorAddresses?.get(0),
date = item.date?.toDateTime(),
@ -32,6 +30,7 @@ internal class YieldBalanceConverter : Converter<YieldBalanceWrapperDTO, YieldBa
.convertList(item.pendingActions)
// temporarily exclude VOTE_LOCKED, it will be implemented in future iterations
.filterNot { it.type == StakingActionType.VOTE_LOCKED },
isPending = false,
)
},
integrationId = value.integrationId,

View file

@ -3,6 +3,7 @@ package com.tangem.data.staking.di
import com.squareup.moshi.Moshi
import com.tangem.data.common.cache.CacheRegistry
import com.tangem.data.staking.DefaultStakingErrorResolver
import com.tangem.data.staking.DefaultStakingPendingTransactionRepository
import com.tangem.data.staking.DefaultStakingRepository
import com.tangem.data.staking.DefaultStakingTransactionHashRepository
import com.tangem.data.staking.converters.error.StakeKitErrorConverter
@ -13,6 +14,7 @@ import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.token.StakingBalanceStore
import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
@ -57,7 +59,7 @@ internal object StakingDataModule {
@Provides
@Singleton
fun StakingTransactionHashRepository(
fun provideStakingTransactionHashRepository(
stakeKitApi: StakeKitApi,
appPreferencesStore: AppPreferencesStore,
dispatchers: CoroutineDispatcherProvider,
@ -69,6 +71,12 @@ internal object StakingDataModule {
)
}
@Provides
@Singleton
fun provideStakingPendingTransactionRepository(): StakingPendingTransactionRepository {
return DefaultStakingPendingTransactionRepository()
}
@Provides
@Singleton
internal fun provideStakingErrorResolver(@NetworkMoshi moshi: Moshi): StakingErrorResolver {

View file

@ -38,4 +38,6 @@ sealed interface LegacyAction : Action {
val errorMessage: String,
val scanResponse: ScanResponse,
) : LegacyAction
data object PrepareDetailsScreen : LegacyAction
}

View file

@ -0,0 +1,13 @@
package com.tangem.domain.staking.model
import com.tangem.domain.staking.model.stakekit.BalanceType
import com.tangem.domain.staking.model.stakekit.Yield
import java.math.BigDecimal
data class PendingTransaction(
val groupId: String?,
val type: BalanceType?,
val amount: BigDecimal?,
val rawCurrencyId: String?,
val validator: Yield.Validator?,
)

View file

@ -0,0 +1,14 @@
package com.tangem.domain.staking.model
import com.tangem.domain.staking.model.stakekit.BalanceType
import com.tangem.domain.staking.model.stakekit.Yield
import java.math.BigDecimal
data class SubmitHashData(
val transactionHash: String,
val transactionId: String,
val validator: Yield.Validator?,
val amount: BigDecimal?,
val balanceType: BalanceType?,
val rawCurrencyId: String?,
)

View file

@ -45,15 +45,14 @@ data class YieldBalanceItem(
)
data class BalanceItem(
val id: String,
val groupId: String,
val type: BalanceType,
val amount: BigDecimal,
val pricePerShare: BigDecimal,
val rawCurrencyId: String?,
val rawNetworkId: String,
val validatorAddress: String?,
val date: DateTime?,
val pendingActions: List<PendingAction>,
val isPending: Boolean,
)
data class PendingAction(

View file

@ -0,0 +1,24 @@
package com.tangem.domain.staking
import arrow.core.Either
import com.tangem.domain.staking.model.stakekit.BalanceItem
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
/**
* Use case for getting saved staking pending transactions.
*/
class GetPendingTransactionsUseCase(
private val stakingPendingTransactionRepository: StakingPendingTransactionRepository,
private val stakingErrorResolver: StakingErrorResolver,
) {
operator fun invoke(): Either<StakingError, List<BalanceItem>> {
return Either.catch {
stakingPendingTransactionRepository.getTransactionsWithBalanceItems().map { it.second }
}.mapLeft {
stakingErrorResolver.resolve(it)
}
}
}

View file

@ -0,0 +1,54 @@
package com.tangem.domain.staking
import arrow.core.Either
import com.tangem.domain.staking.model.PendingTransaction
import com.tangem.domain.staking.model.stakekit.BalanceItem
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.model.stakekit.YieldBalance
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
class InvalidatePendingTransactionsUseCase(
private val stakingPendingTransactionRepository: StakingPendingTransactionRepository,
private val stakingErrorResolver: StakingErrorResolver,
) {
operator fun invoke(yieldBalance: YieldBalance): Either<StakingError, List<BalanceItem>> {
return Either.catch {
if (yieldBalance is YieldBalance.Data) {
val (balancesToDisplay, transactionsToRemove) = mergeRealAndPendingTransactions(
real = yieldBalance.balance.items,
pending = stakingPendingTransactionRepository.getTransactionsWithBalanceItems(),
)
stakingPendingTransactionRepository.removeTransactions(transactionsToRemove.toSet())
balancesToDisplay
} else {
emptyList()
}
}.mapLeft {
stakingErrorResolver.resolve(it)
}
}
private fun mergeRealAndPendingTransactions(
real: List<BalanceItem>,
pending: List<Pair<PendingTransaction, BalanceItem>>,
): Pair<List<BalanceItem>, List<PendingTransaction>> {
val map = real.associateBy { Triple(it.groupId, it.type, it.amount) }.toMutableMap()
val toRemove = mutableListOf<PendingTransaction>()
pending.forEach { (pendingTransaction, balanceItem) ->
val key = Triple(balanceItem.groupId, balanceItem.type, balanceItem.amount)
if (map.containsKey(key)) {
map[key] = balanceItem
} else {
toRemove.add(pendingTransaction)
}
}
return map.values.toList() to toRemove
}
}

View file

@ -0,0 +1,24 @@
package com.tangem.domain.staking
import arrow.core.Either
import com.tangem.domain.staking.model.PendingTransaction
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
/**
* Use case for saving hash that failed to submit during staking confirmation
*/
class SavePendingTransactionUseCase(
private val stakingPendingTransactionRepository: StakingPendingTransactionRepository,
private val stakingErrorResolver: StakingErrorResolver,
) {
operator fun invoke(pendingTransaction: PendingTransaction): Either<StakingError, Unit> {
return Either.catch {
stakingPendingTransactionRepository.saveTransaction(pendingTransaction)
}.mapLeft {
stakingErrorResolver.resolve(it)
}
}
}

View file

@ -1,6 +1,7 @@
package com.tangem.domain.staking
import arrow.core.Either
import com.tangem.domain.staking.model.SubmitHashData
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
@ -13,12 +14,12 @@ class SubmitHashUseCase(
private val stakingErrorResolver: StakingErrorResolver,
) {
suspend fun submitHash(transactionId: String, transactionHash: String): Either<StakingError, Unit> {
suspend operator fun invoke(submitHashData: SubmitHashData): Either<StakingError, Unit> {
return Either
.catch {
stakingTransactionHashRepository.submitHash(
transactionId = transactionId,
transactionHash = transactionHash,
transactionId = submitHashData.transactionId,
transactionHash = submitHashData.transactionHash,
)
}.mapLeft {
stakingErrorResolver.resolve(it)

View file

@ -0,0 +1,13 @@
package com.tangem.domain.staking.repositories
import com.tangem.domain.staking.model.PendingTransaction
import com.tangem.domain.staking.model.stakekit.BalanceItem
interface StakingPendingTransactionRepository {
fun getTransactionsWithBalanceItems(): List<Pair<PendingTransaction, BalanceItem>>
fun saveTransaction(transaction: PendingTransaction)
fun removeTransactions(transactions: Set<PendingTransaction>)
}

View file

@ -61,7 +61,7 @@ internal class CurrencyStatusOperations(
(yieldBalance as? YieldBalance.Data)?.address == status.address.defaultAddress.value
val currentYieldBalance = yieldBalance.takeIf { isCurrentAddressStaking }
return when {
ignoreQuote || quote == null -> CryptoCurrencyStatus.NoQuote(
ignoreQuote -> CryptoCurrencyStatus.NoQuote(
amount = amount,
hasCurrentNetworkTransactions = hasCurrentNetworkTransactions,
pendingTransactions = currentTransactions,
@ -70,14 +70,15 @@ internal class CurrencyStatusOperations(
)
currency is CryptoCurrency.Token && currency.isCustom -> CryptoCurrencyStatus.Custom(
amount = amount,
fiatAmount = calculateFiatAmountOrNull(amount, quote.fiatRate),
fiatRate = quote.fiatRate,
priceChange = quote.priceChange,
fiatAmount = calculateFiatAmountOrNull(amount, quote?.fiatRate),
fiatRate = quote?.fiatRate,
priceChange = quote?.priceChange,
hasCurrentNetworkTransactions = hasCurrentNetworkTransactions,
pendingTransactions = currentTransactions,
networkAddress = status.address,
yieldBalance = currentYieldBalance,
)
quote == null -> CryptoCurrencyStatus.Loading
else -> CryptoCurrencyStatus.Loaded(
amount = amount,
fiatAmount = calculateFiatAmount(amount, quote.fiatRate),

View file

@ -61,6 +61,9 @@ internal class DetailsModel @Inject constructor(
)
init {
// Use to save compatibility with screens that using Redux states
bootstrapScreenState()
items
.onEach(::updateState)
.launchIn(modelScope)
@ -82,6 +85,10 @@ internal class DetailsModel @Inject constructor(
)
}
private fun bootstrapScreenState() {
appStateHolder.dispatch(LegacyAction.PrepareDetailsScreen)
}
private fun sendFeedback() {
modelScope.launch {
val scanResponse = getSelectedWalletSyncUseCase().getOrNull()?.scanResponse

View file

@ -77,7 +77,7 @@ internal class InsightsConverter(
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_experienced_buyers),
title = resourceReference(R.string.markets_token_details_experienced_buyers_full),
body = resourceReference(R.string.markets_token_details_experienced_buyers_description),
),
)
@ -92,7 +92,7 @@ internal class InsightsConverter(
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_buy_pressure),
title = resourceReference(R.string.markets_token_details_buy_pressure_full),
body = resourceReference(R.string.markets_token_details_buy_pressure_description),
),
)
@ -107,7 +107,7 @@ internal class InsightsConverter(
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_holders),
title = resourceReference(R.string.markets_token_details_holders_full),
body = resourceReference(R.string.markets_token_details_holders_description),
),
)
@ -122,7 +122,7 @@ internal class InsightsConverter(
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_liquidity),
title = resourceReference(R.string.markets_token_details_liquidity_full),
body = resourceReference(R.string.markets_token_details_liquidity_description),
),
)

View file

@ -32,7 +32,9 @@ internal class MetricsConverter(
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_market_capitalization),
title = resourceReference(
R.string.markets_token_details_market_capitalization_full,
),
body = resourceReference(
R.string.markets_token_details_market_capitalization_description,
),
@ -46,7 +48,7 @@ internal class MetricsConverter(
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_market_rating),
title = resourceReference(R.string.markets_token_details_market_rating_full),
body = resourceReference(R.string.markets_token_details_market_rating_description),
),
)
@ -58,7 +60,7 @@ internal class MetricsConverter(
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_trading_volume),
title = resourceReference(R.string.markets_token_details_trading_volume_full),
body = resourceReference(
R.string.markets_token_details_trading_volume_24h_description,
),
@ -72,7 +74,9 @@ internal class MetricsConverter(
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_fully_diluted_valuation),
title = resourceReference(
R.string.markets_token_details_fully_diluted_valuation_full,
),
body = resourceReference(
R.string.markets_token_details_fully_diluted_valuation_description,
),
@ -86,7 +90,7 @@ internal class MetricsConverter(
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_circulating_supply),
title = resourceReference(R.string.markets_token_details_circulating_supply_full),
body = resourceReference(
R.string.markets_token_details_circulating_supply_description,
),
@ -100,7 +104,7 @@ internal class MetricsConverter(
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_total_supply),
title = resourceReference(R.string.markets_token_details_total_supply_full),
body = resourceReference(R.string.markets_token_details_total_supply_description),
),
)

View file

@ -1,8 +1,8 @@
package com.tangem.features.markets.details.impl.ui.components
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text.ClickableText
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -38,17 +38,16 @@ internal fun Description(
}
}
ClickableText(
modifier = modifier,
Text(
modifier = modifier
.clickable(
interactionSource = null,
indication = null,
onClick = onReadMoreClick,
),
text = text,
style = TangemTheme.typography.body2,
) {
text.spanStyles.getOrNull(1)?.let { spanStyle ->
if (it in spanStyle.start..spanStyle.end) {
onReadMoreClick()
}
}
}
)
} else {
Text(
modifier = modifier,

View file

@ -25,7 +25,6 @@ internal fun InfoBottomSheet(config: TangemBottomSheetConfig) {
TangemBottomSheet<InfoBottomSheetContent>(
config = config,
skipPartiallyExpanded = false,
addBottomInsets = false,
title = { TangemBottomSheetTitle(title = it.title) },
content = {

View file

@ -20,7 +20,7 @@ import kotlinx.collections.immutable.toImmutableList
* @property onAddToPortfolioVisibilityChange callback is invoked when add to portfolio visibility is changed
* @property onWalletSelectorVisibilityChange callback is invoked when wallet selector visibility is changed
* @property onNetworkSwitchClick callback is invoked when network switch is clicked
* @property onWalletSelect callback is invoked when wallet is selected
* @property onAnotherWalletSelect callback is invoked when wallet is selected
* @property onContinueClick callback is invoked when continue button is clicked
*
[REDACTED_AUTHOR]
@ -30,7 +30,7 @@ internal class AddToPortfolioBSContentUMFactory(
private val onAddToPortfolioVisibilityChange: (Boolean) -> Unit,
private val onWalletSelectorVisibilityChange: (Boolean) -> Unit,
private val onNetworkSwitchClick: (BlockchainRowUM, Boolean) -> Unit,
private val onWalletSelect: (UserWalletId) -> Unit,
private val onAnotherWalletSelect: (UserWalletId) -> Unit,
private val onContinueClick: (selectedWalletId: UserWalletId, addedNetworks: Set<TokenMarketInfo.Network>) -> Unit,
) {
@ -62,7 +62,7 @@ internal class AddToPortfolioBSContentUMFactory(
onNetworkSwitchClick = onNetworkSwitchClick,
).convert(value = token),
isScanCardNotificationVisible = portfolioUIData.hasMissedDerivations,
continueButtonEnabled = portfolioUIData.addToPortfolioData.isUserChangedNetworks(
continueButtonEnabled = portfolioUIData.addToPortfolioData.isUserAddedNetworks(
userWalletId = selectedWallet.walletId,
),
onContinueButtonClick = {
@ -112,7 +112,12 @@ internal class AddToPortfolioBSContentUMFactory(
val balance = portfolioData.walletsWithBalance[userWallet.walletId]
UserWalletItemUMConverter(
onClick = onWalletSelect,
onClick = {
if (it != selectedWalletId) {
onAnotherWalletSelect(it)
onWalletSelectorVisibilityChange(false)
}
},
appCurrency = portfolioData.appCurrency,
balance = balance?.getOrNull(),
isLoading = balance?.isLoading() == true,

View file

@ -152,6 +152,10 @@ internal class AddToPortfolioManager @Inject constructor() {
.orEmpty()
}
fun isUserAddedNetworks(userWalletId: UserWalletId): Boolean {
return addedNetworks[userWalletId].orEmpty().isNotEmpty()
}
fun isUserChangedNetworks(userWalletId: UserWalletId): Boolean {
return addedNetworks[userWalletId].orEmpty().isNotEmpty() ||
removedNetworks[userWalletId].orEmpty().isNotEmpty()

View file

@ -92,7 +92,7 @@ internal class MarketsPortfolioModel @Inject constructor(
onAddToPortfolioVisibilityChange = ::onAddToPortfolioBSVisibilityChange,
onWalletSelectorVisibilityChange = ::onWalletSelectorVisibilityChange,
onNetworkSwitchClick = ::onNetworkSwitchClick,
onWalletSelect = {
onAnotherWalletSelect = {
onWalletSelect(it)
// === Analytics ===
analyticsEventHandler.send(

View file

@ -127,7 +127,7 @@ private fun AddFirstTokenContent(state: MyPortfolioUM.AddFirstToken, modifier: M
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
) {
Text(
text = "To start buying, exchanging or receiving this asset, add this token to at least 1 network", // FIXME
text = stringResource(R.string.markets_add_to_my_portfolio_description),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.tertiary,
)

View file

@ -22,7 +22,7 @@ internal sealed class InnerYieldBalanceState {
@Immutable
internal data class BalanceState(
val id: String,
val groupId: String,
val title: TextReference,
val type: BalanceType,
val subtitle: TextReference?,
@ -34,4 +34,5 @@ internal data class BalanceState(
val rawCurrencyId: String?,
val validator: Yield.Validator?,
val pendingActions: ImmutableList<PendingAction>,
val isPending: Boolean,
)

View file

@ -98,6 +98,7 @@ internal sealed class StakingStates {
val transactionDoneState: TransactionDoneState,
val isApprovalNeeded: Boolean,
val reduceAmountBy: BigDecimal?,
val balanceState: BalanceState?,
) : ConfirmationState()
data class Empty(

View file

@ -22,6 +22,7 @@ internal class BalanceItemConverter(
private val appCurrencyProvider: Provider<AppCurrency>,
private val yield: Yield,
) : Converter<BalanceItem, BalanceState?> {
override fun convert(value: BalanceItem): BalanceState? {
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val appCurrency = appCurrencyProvider()
@ -37,7 +38,7 @@ internal class BalanceItemConverter(
val title = value.type.getTitle(validator?.name)
return title?.let {
BalanceState(
id = value.id,
groupId = value.groupId,
validator = validator,
title = title,
subtitle = getSubtitle(value),
@ -59,7 +60,8 @@ internal class BalanceItemConverter(
),
rawCurrencyId = value.rawCurrencyId,
pendingActions = value.pendingActions.toPersistentList(),
isClickable = value.type.isClickable(),
isClickable = value.type.isClickable() && !value.isPending,
isPending = value.isPending,
)
}
}

View file

@ -78,7 +78,7 @@ internal class RewardsValidatorStateConverter(
)
return BalanceState(
id = balance.id,
groupId = balance.groupId,
validator = this,
title = stringReference(this.name),
subtitle = null,
@ -90,6 +90,7 @@ internal class RewardsValidatorStateConverter(
pendingActions = balance.pendingActions.toPersistentList(),
isClickable = true,
type = balance.type,
isPending = balance.isPending,
)
}
}

View file

@ -14,6 +14,7 @@ import kotlinx.collections.immutable.toPersistentList
internal class YieldBalancesConverter(
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
private val appCurrencyProvider: Provider<AppCurrency>,
private val balancesToShowProvider: Provider<List<BalanceItem>>,
private val yield: Yield,
) : Converter<Unit, InnerYieldBalanceState> {
@ -32,6 +33,8 @@ internal class YieldBalancesConverter(
val cryptoRewardsValue = yieldBalance.getRewardStakingBalance()
val fiatRewardsValue = cryptoCurrencyStatus.value.fiatRate?.times(cryptoRewardsValue)
val balanceToShowItems = balancesToShowProvider()
InnerYieldBalanceState.Data(
rewardsCrypto = BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = cryptoRewardsValue,
@ -43,7 +46,7 @@ internal class YieldBalancesConverter(
fiatCurrencySymbol = appCurrency.symbol,
),
rewardBlockType = getRewardBlockType(),
balance = yieldBalance.balance.items.mapBalances(),
balance = balanceToShowItems.mapBalances(),
)
} else {
InnerYieldBalanceState.Empty

View file

@ -5,10 +5,10 @@ import com.tangem.blockchain.common.TransactionData
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.domain.staking.GetConstructedStakingTransactionUseCase
import com.tangem.domain.staking.GetStakingTransactionUseCase
import com.tangem.domain.staking.SaveUnsubmittedHashUseCase
import com.tangem.domain.staking.SubmitHashUseCase
import com.tangem.domain.staking.*
import com.tangem.domain.staking.model.PendingTransaction
import com.tangem.domain.staking.model.SubmitHashData
import com.tangem.domain.staking.model.stakekit.BalanceType
import com.tangem.domain.staking.model.stakekit.PendingAction
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.model.stakekit.Yield
@ -45,6 +45,7 @@ internal class StakingTransactionSender @AssistedInject constructor(
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
private val submitHashUseCase: SubmitHashUseCase,
private val saveUnsubmittedHashUseCase: SaveUnsubmittedHashUseCase,
private val savePendingTransactionUseCase: SavePendingTransactionUseCase,
private val analyticsEventHandler: AnalyticsEventHandler,
@Assisted private val cryptoCurrencyStatus: CryptoCurrencyStatus,
@Assisted private val userWallet: UserWallet,
@ -89,6 +90,7 @@ internal class StakingTransactionSender @AssistedInject constructor(
sendStakingTransaction(
fullTransactionsData = fullTransactionsData,
balanceState = confirmationState.balanceState,
onSendSuccess = onSendSuccess,
onSendError = onSendError,
)
@ -191,6 +193,7 @@ internal class StakingTransactionSender @AssistedInject constructor(
private suspend fun sendStakingTransaction(
fullTransactionsData: List<FullTransactionData>,
balanceState: BalanceState?,
onSendSuccess: (txUrl: String) -> Unit,
onSendError: (SendTransactionError?) -> Unit,
) {
@ -206,6 +209,11 @@ internal class StakingTransactionSender @AssistedInject constructor(
submitHash(
transactionIds = fullTransactionsData.map { it.stakeKitTransaction.id },
transactionHashes = transactionHashes,
groupId = balanceState?.groupId,
validator = balanceState?.validator,
amount = balanceState?.cryptoDecimal,
balanceType = balanceState?.type,
rawCurrencyId = balanceState?.rawCurrencyId,
)
val txUrl = getExplorerTransactionUrlUseCase(
txHash = transactionHashes.last(),
@ -218,13 +226,27 @@ internal class StakingTransactionSender @AssistedInject constructor(
)
}
private suspend fun submitHash(transactionIds: List<String>, transactionHashes: List<String>) {
private suspend fun submitHash(
transactionIds: List<String>,
transactionHashes: List<String>,
groupId: String?,
validator: Yield.Validator?,
amount: BigDecimal?,
balanceType: BalanceType?,
rawCurrencyId: String?,
) {
transactionIds
.zip(transactionHashes)
.forEach { (transactionId, transactionHash) ->
submitHashUseCase.submitHash(
transactionId = transactionId,
transactionHash = transactionHash,
submitHashUseCase(
SubmitHashData(
transactionId = transactionId,
transactionHash = transactionHash,
validator = validator,
amount = amount,
balanceType = balanceType,
rawCurrencyId = rawCurrencyId,
),
)
.onLeft {
analyticsEventHandler.send(
@ -236,6 +258,15 @@ internal class StakingTransactionSender @AssistedInject constructor(
)
}.onRight {
Timber.d("Successful hash submission")
savePendingTransactionUseCase.invoke(
PendingTransaction(
groupId = groupId,
type = balanceType,
amount = amount,
rawCurrencyId = rawCurrencyId,
validator = validator,
),
)
}
}
}

View file

@ -93,5 +93,6 @@ internal object ConfirmationStatePreviewData {
isApprovalNeeded = false,
reduceAmountBy = null,
pendingActions = null,
balanceState = null,
)
}

View file

@ -68,7 +68,7 @@ internal object InitialStakingStatePreview {
rewardBlockType = RewardBlockType.RewardUnavailable,
balance = persistentListOf(
BalanceState(
id = "id",
groupId = "groupId",
title = stringReference("Binance"),
cryptoValue = "100",
cryptoAmount = stringReference("100 SOL"),
@ -91,6 +91,7 @@ internal object InitialStakingStatePreview {
isClickable = true,
type = BalanceType.STAKED,
subtitle = null,
isPending = false,
),
),
),

View file

@ -20,8 +20,8 @@ internal object StakingClickIntentsStub : StakingClickIntents {
actionTypeToOverwrite: StakingActionCommonType?,
pendingAction: PendingAction?,
pendingActions: ImmutableList<PendingAction>?,
) {
}
balanceState: BalanceState?,
) { }
override fun onActionClick() {}

View file

@ -0,0 +1,18 @@
package com.tangem.features.staking.impl.presentation.state.transformers
import com.tangem.features.staking.impl.presentation.state.*
import com.tangem.utils.transformer.Transformer
internal class SetBalanceStateTransformer(
private val balanceState: BalanceState? = null,
) : Transformer<StakingUiState> {
override fun transform(prevState: StakingUiState): StakingUiState {
val possibleConfirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data
?: return prevState
return prevState.copy(
confirmationState = possibleConfirmationState.copy(balanceState = balanceState),
)
}
}

View file

@ -41,6 +41,7 @@ internal class SetConfirmationStateLoadingTransformer(
pendingActions = possibleConfirmationState?.pendingActions,
isApprovalNeeded = false,
reduceAmountBy = null,
balanceState = null,
),
)
}

View file

@ -10,6 +10,7 @@ import com.tangem.core.ui.pullToRefresh.PullToRefreshConfig
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.core.serialization.SerializedBigDecimal
import com.tangem.domain.staking.model.stakekit.BalanceItem
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.wallets.models.UserWallet
@ -19,7 +20,6 @@ import com.tangem.features.staking.impl.presentation.state.bottomsheet.InfoType
import com.tangem.features.staking.impl.presentation.state.converters.RewardsValidatorStateConverter
import com.tangem.features.staking.impl.presentation.state.converters.YieldBalancesConverter
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
import com.tangem.lib.crypto.BlockchainUtils.isCosmos
import com.tangem.lib.crypto.BlockchainUtils.isPolkadot
import com.tangem.utils.Provider
import com.tangem.utils.isNullOrZero
@ -38,6 +38,7 @@ internal class SetInitialDataStateTransformer(
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
private val userWalletProvider: Provider<UserWallet>,
private val appCurrencyProvider: Provider<AppCurrency>,
private val balancesToShowProvider: Provider<List<BalanceItem>>,
) : Transformer<StakingUiState> {
private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter)
@ -60,6 +61,7 @@ internal class SetInitialDataStateTransformer(
YieldBalancesConverter(
cryptoCurrencyStatusProvider,
appCurrencyProvider,
balancesToShowProvider,
yield,
)
}
@ -229,6 +231,7 @@ internal class SetInitialDataStateTransformer(
pendingActions = null,
isApprovalNeeded = isApprovalNeeded,
reduceAmountBy = null,
balanceState = null,
)
}
@ -255,13 +258,7 @@ internal class SetInitialDataStateTransformer(
private fun getRewardScheduleText(rewardSchedule: Yield.Metadata.RewardSchedule): TextReference? {
return when (rewardSchedule) {
Yield.Metadata.RewardSchedule.BLOCK -> {
val networkId = cryptoCurrencyStatusProvider().currency.network.id.value
when {
isCosmos(networkId) -> resourceReference(R.string.staking_reward_schedule_each_minute)
else -> resourceReference(R.string.staking_reward_schedule_each_day)
}
}
Yield.Metadata.RewardSchedule.BLOCK -> resourceReference(R.string.staking_reward_schedule_block)
Yield.Metadata.RewardSchedule.WEEK -> resourceReference(R.string.staking_reward_schedule_week)
Yield.Metadata.RewardSchedule.HOUR -> resourceReference(R.string.staking_reward_schedule_hour)
Yield.Metadata.RewardSchedule.DAY -> resourceReference(R.string.staking_reward_schedule_each_day)

View file

@ -89,7 +89,7 @@ internal fun StakingInitialInfoContent(
if (state.showBanner) {
item(key = BANNER_BLOCK_KEY) {
Column(
modifier = Modifier.animateItemPlacement(),
modifier = Modifier.animateItem(),
) {
BannerBlock(onClick = clickIntents::onInitialInfoBannerClick)
SpacerH12()
@ -105,7 +105,7 @@ internal fun StakingInitialInfoContent(
if (state.yieldBalance is InnerYieldBalanceState.Data) {
item(key = STAKING_REWARD_BLOCK_KEY) {
Column(modifier = Modifier.animateItemPlacement()) {
Column(modifier = Modifier.animateItem()) {
StakingRewardBlock(
rewardCrypto = state.yieldBalance.rewardsCrypto,
rewardFiat = state.yieldBalance.rewardsFiat,
@ -138,7 +138,6 @@ internal fun StakingInitialInfoContent(
}
}
@OptIn(ExperimentalFoundationApi::class)
private fun LazyListScope.activeStakingBlock(
state: StakingStates.InitialInfoState.Data,
clickIntents: StakingClickIntents,
@ -175,7 +174,7 @@ private fun LazyListScope.activeStakingBlock(
onClick = clickIntents::onActiveStake,
onAnalytic = clickIntents::onActiveStakeAnalytic,
modifier = Modifier
.animateItemPlacement()
.animateItem()
.then(
if (state.yieldBalance.balance.last() == balance) {
Modifier.clip(CornersToRound.BOTTOM_2.getShape())
@ -279,6 +278,7 @@ private fun ActiveStakingBlock(
imageUrl = balance.getImage(),
iconRes = icon,
iconTint = iconTint,
subtitleEndIconRes = R.drawable.ic_staking_pending_transaction.takeIf { balance.isPending },
onImageError = { ValidatorImagePlaceholder() },
modifier = modifier
.background(TangemTheme.colors.background.action)

View file

@ -20,6 +20,7 @@ internal interface StakingClickIntents : AmountScreenClickIntents {
actionTypeToOverwrite: StakingActionCommonType? = null,
pendingAction: PendingAction? = null,
pendingActions: ImmutableList<PendingAction>? = null,
balanceState: BalanceState? = null,
)
fun onActionClick()

View file

@ -1,10 +1,7 @@
package com.tangem.features.staking.impl.presentation.viewmodel
import android.os.Bundle
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.*
import arrow.core.getOrElse
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.common.routing.AppRoute
@ -23,9 +20,11 @@ import com.tangem.domain.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
import com.tangem.domain.feedback.models.BlockchainErrorInfo
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.staking.InvalidatePendingTransactionsUseCase
import com.tangem.domain.staking.IsAnyTokenStakedUseCase
import com.tangem.domain.staking.IsApproveNeededUseCase
import com.tangem.domain.staking.model.StakingApproval
import com.tangem.domain.staking.model.stakekit.BalanceItem
import com.tangem.domain.staking.model.stakekit.PendingAction
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.staking.model.stakekit.YieldBalance
@ -98,6 +97,7 @@ internal class StakingViewModel @Inject constructor(
private val getCurrencyCheckUseCase: GetCurrencyCheckUseCase,
private val isAmountSubtractAvailableUseCase: IsAmountSubtractAvailableUseCase,
private val isAnyTokenStakedUseCase: IsAnyTokenStakedUseCase,
private val invalidatePendingTransactionsUseCase: InvalidatePendingTransactionsUseCase,
private val stakingTransactionLoader: StakingTransactionSender.Factory,
private val stakingFeeTransactionLoader: StakingFeeTransactionLoader.Factory,
private val stakingBalanceUpdater: StakingBalanceUpdater.Factory,
@ -131,6 +131,13 @@ internal class StakingViewModel @Inject constructor(
private var userWallet: UserWallet by Delegates.notNull()
private var appCurrency: AppCurrency by Delegates.notNull()
private val balancesToShow: List<BalanceItem>
get() {
return cryptoCurrencyStatus.value.yieldBalance?.let {
invalidatePendingTransactionsUseCase(it).getOrElse { emptyList() }
} ?: emptyList()
}
private var isInitialInfoAnalyticSent: Boolean = false
private val balanceUpdater by lazy(LazyThreadSafetyMode.NONE) {
@ -161,7 +168,7 @@ internal class StakingViewModel @Inject constructor(
private val stakingEventFactory: StakingEventFactory
get() = StakingEventFactory(
stateController = stateController,
popBackStack = stakingStateRouter::onBackClick,
popBackStack = ::onBackClick,
onFailedTxEmailClick = ::onFailedTxEmailClick,
)
@ -200,6 +207,7 @@ internal class StakingViewModel @Inject constructor(
actionTypeToOverwrite: StakingActionCommonType?,
pendingAction: PendingAction?,
pendingActions: ImmutableList<PendingAction>?,
balanceState: BalanceState?,
) {
if (actionTypeToOverwrite != null) {
stateController.update(SetActionToExecuteTransformer(actionTypeToOverwrite, pendingAction, pendingActions))
@ -208,10 +216,12 @@ internal class StakingViewModel @Inject constructor(
when {
isInitState() -> {
stateController.update(SetConfirmationStateLoadingTransformer(yield, appCurrency))
stateController.update(SetBalanceStateTransformer(balanceState))
onRefreshSwipe(isRefreshing = false)
}
isAssentState() -> {
getFee(pendingAction, pendingActions)
stateController.update(SetBalanceStateTransformer(balanceState))
val amountState = value.amountState as? AmountState.Data
if (amountState?.amountTextField?.isWarning == true) {
stateController.update(
@ -413,6 +423,7 @@ internal class StakingViewModel @Inject constructor(
onNextClick(
actionTypeToOverwrite = StakingActionCommonType.PENDING_OTHER,
pendingAction = action,
balanceState = activeStake,
)
stateController.update(DismissBottomSheetStateTransformer)
},
@ -428,6 +439,7 @@ internal class StakingViewModel @Inject constructor(
actionTypeToOverwrite = null,
pendingAction = activeStake.pendingActions.firstOrNull(),
pendingActions = activeStake.pendingActions.takeIf { isAllWithdrawActions },
balanceState = activeStake,
)
}
}
@ -749,6 +761,7 @@ internal class StakingViewModel @Inject constructor(
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
userWalletProvider = Provider { userWallet },
appCurrencyProvider = Provider { appCurrency },
balancesToShowProvider = Provider { balancesToShow },
),
)
},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Before After
Before After