Updated on 2026-08-14

This commit is contained in:
Tangem 2024-10-23 20:28:37 +03:00
commit c120acae62
84 changed files with 1269 additions and 747 deletions

@ -1 +1 @@
Subproject commit d52c8382e9e94b2b44ceecd7cb7bd897e091073c
Subproject commit cf01c91626bf58bdf6895c59a706b83c37a9e345

View file

@ -19,8 +19,8 @@ import com.tangem.domain.models.scan.CardDTO.Companion.RING_BATCH_IDS
import com.tangem.domain.models.scan.CardDTO.Companion.RING_BATCH_PREFIX
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.builder.UserWalletIdBuilder
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.models.Artwork
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
@ -641,6 +641,8 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
)
}
} else {
delay(HIDE_PROGRESS_DELAY)
readCard { newScanResponse ->
scanResponse = newScanResponse
userWallet = createUserWallet(newScanResponse, backupState)
@ -658,7 +660,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
// All cardIds may already be activated if the backup was skipped before.
if (notActivatedCardIds.isEmpty()) {
delay(1000)
store.dispatch(BackupAction.BackupFinished(userWallet?.walletId))
store.dispatchWithMain(BackupAction.BackupFinished(userWallet?.walletId))
return@launch
}
@ -667,7 +669,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
store.state.globalState.onboardingState.onboardingManager?.finishActivation(notActivatedCardIds)
handleFinishBackup(requireNotNull(scanResponse))
delay(1000)
store.dispatch(BackupAction.BackupFinished(userWalletId = userWallet?.walletId))
store.dispatchWithMain(BackupAction.BackupFinished(userWalletId = userWallet?.walletId))
}
}

View file

@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import androidx.core.view.MenuProvider
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.transition.TransitionManager
import by.kirich1409.viewbindingdelegate.viewBinding
@ -574,22 +575,28 @@ class OnboardingWalletFragment :
}
animator.showSuccess {
flCardsContainer.hide()
imvCardBackground.hide()
showConfetti(true)
imvSuccess.alpha = 0f
imvSuccess.show()
imvSuccess.animate()?.alpha(1f)?.duration = 400
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
flCardsContainer.hide()
imvCardBackground.hide()
showConfetti(true)
imvSuccess.alpha = 0f
imvSuccess.show()
imvSuccess.animate()?.alpha(1f)?.duration = 400
}
}
}
internal fun showConfetti(show: Boolean) = with(binding.vConfetti) {
lavConfetti.show(show)
internal fun showConfetti(show: Boolean) {
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
with(binding.vConfetti) {
lavConfetti.show(show)
if (show) {
lavConfetti.playAnimation()
} else {
lavConfetti.cancelAnimation()
if (show) {
lavConfetti.playAnimation()
} else {
lavConfetti.cancelAnimation()
}
}
}
}

View file

@ -23,9 +23,9 @@
android:id="@+id/tv_body"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="64dp"
android:layout_marginStart="32dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="64dp"
android:layout_marginEnd="32dp"
android:textColor="@color/text_secondary"
android:textAlignment="center"
tools:text="Body"

View file

@ -130,7 +130,7 @@ private fun ApprovalBottomSheetInfo(data: GiveTxPermissionState.ReadyForRequest)
}
SpacerH16()
FooterContainer(
footer = stringResource(id = R.string.give_permission_fee_footer),
footer = data.footerText.resolveReference(),
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16),
) {
FeeItem(fee = data.fee)
@ -321,6 +321,7 @@ private val previewData = GiveTxPermissionBottomSheetConfig(
onChangeApproveType = { ApproveType.LIMITED },
subtitle = resourceReference(R.string.give_permission_staking_subtitle, wrappedList("1")),
dialogText = resourceReference(R.string.give_permission_staking_footer),
footerText = resourceReference(R.string.swap_give_permission_fee_footer),
),
onCancel = {},
)

View file

@ -15,6 +15,7 @@ sealed class GiveTxPermissionState {
data class ReadyForRequest(
val subtitle: TextReference,
val dialogText: TextReference,
val footerText: TextReference,
val currency: String,
val amount: String,
val walletAddress: String,

View file

@ -178,6 +178,7 @@ sealed class AnalyticsParam {
const val ERROR_DESCRIPTION = "Error Description"
const val ERROR_CODE = "Error Code"
const val ERROR_KEY = "Error Key"
const val ERROR_TYPE = "Error Type"
const val CREATION_TYPE = "Creation type"
const val DAPP_NAME = "DApp Name"
const val DAPP_URL = "DApp Url"

View file

@ -50,7 +50,6 @@ dependencies {
implementation(deps.okHttp.prettyLogging)
implementation(deps.retrofit)
implementation(deps.retrofit.moshi)
implementation(deps.reactive.network)
/** Time */
implementation(deps.jodatime)

View file

@ -64,6 +64,9 @@ enum class ExchangeStatus {
@Json(name = "tx-failed")
TxFailed,
@Json(name = "paused")
Paused,
@Json(name = "unknown")
Unknown,
}

View file

@ -0,0 +1,26 @@
package com.tangem.datasource.connection
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import androidx.core.content.ContextCompat
internal class AndroidNetworkConnectionManager(
private val applicationContext: Context,
) : NetworkConnectionManager {
override val isOnline: Boolean
get() = isNetworkAvailable()
private fun isNetworkAvailable(): Boolean {
val connectivityManager = ContextCompat.getSystemService(applicationContext, ConnectivityManager::class.java)
// Network that is currently in use (several networks can be presented at the same time)
val defaultNetwork: Network = connectivityManager?.activeNetwork ?: return false
val networkCapabilities: NetworkCapabilities =
connectivityManager.getNetworkCapabilities(defaultNetwork) ?: return false
return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}
}

View file

@ -1,13 +1,8 @@
package com.tangem.datasource.connection
import kotlinx.coroutines.flow.StateFlow
/** Network connection manager */
interface NetworkConnectionManager {
/** Connection status */
val isOnline: Boolean
/** Connection status flow */
val isOnlineFlow: StateFlow<Boolean>
}

View file

@ -1,53 +0,0 @@
package com.tangem.datasource.connection
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler
import io.reactivex.BackpressureStrategy
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.reactive.asFlow
private const val PING_SERVER = "https://clients3.google.com/generate_204"
private const val PING_INTERVAL = 5_000
internal class RealInternetConnectionManager : NetworkConnectionManager {
private val scope =
CoroutineScope(
SupervisorJob() + Dispatchers.IO + FeatureCoroutineExceptionHandler.create("RealInternetConnectionManager"),
)
private val initialNetworkResult: Boolean by lazy {
ReactiveNetwork
.checkInternetConnectivity(
InternetObservingSettings.builder()
.host(PING_SERVER)
.port(443)
.build(),
)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.blockingGet()
}
override val isOnlineFlow: StateFlow<Boolean> = ReactiveNetwork
.observeInternetConnectivity(
InternetObservingSettings.builder()
.host(PING_SERVER)
.port(443)
.interval(PING_INTERVAL)
.build(),
)
.toFlowable(BackpressureStrategy.LATEST)
.asFlow()
.stateIn(scope, SharingStarted.Lazily, initialValue = initialNetworkResult)
override val isOnline: Boolean
get() = isOnlineFlow.value
}

View file

@ -1,10 +1,12 @@
package com.tangem.datasource.di
import android.content.Context
import com.tangem.datasource.connection.AndroidNetworkConnectionManager
import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.datasource.connection.RealInternetConnectionManager
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@ -14,7 +16,7 @@ internal class NetworkConnectionModule {
@Provides
@Singleton
fun provideNetworkConnectionManager(): NetworkConnectionManager {
return RealInternetConnectionManager()
fun provideNetworkConnectionManager(@ApplicationContext applicationContext: Context): NetworkConnectionManager {
return AndroidNetworkConnectionManager(applicationContext = applicationContext)
}
}

View file

@ -20,7 +20,7 @@
<string name="app_settings_enable_biometrics_description">Gehe zu den Einstellungen, um die biometrische Authentifizierung in der Tangem-App zu aktivieren</string>
<string name="app_settings_enable_biometrics_title">Biometrische Authentifizierung aktivieren</string>
<string name="app_settings_off_saved_access_code_alert_message">Dadurch werden alle gespeicherten Zugangscodes für die Wallet gelöscht. Jede weitere Operation mit der Wallet erfordert die Übermittlung des Zugangscodes.</string>
<string name="app_settings_off_saved_wallet_alert_message">Durch das Entfernen der gespeicherten Karte oder Ring werden alle gespeicherten Wallets und deren Zugangscodes aus der App gelöscht.</string>
<string name="app_settings_off_saved_wallet_alert_message">Durch das Entfernen der gespeicherten Geräte werden alle gespeicherten Wallets und deren Zugangscodes aus der App gelöscht.</string>
<string name="app_settings_saved_access_codes">Zugangscode speichern</string>
<string name="app_settings_saved_access_codes_footer">Bei Interaktionen mit deiner Karte oder Ring wird anstelle des Zugangscodes eine biometrische Authentifizierung abgefragt.</string>
<string name="app_settings_saved_wallet">Behalte die Wallet in der App</string>
@ -35,14 +35,14 @@
<string name="balance_hidden_got_it_button">Verstanden</string>
<string name="balance_hidden_title">Guthaben sind ausgeblendet</string>
<string name="biometric_lockout_permanent_warning_description">Bitte Karte oder Ring scannen</string>
<string name="biometric_lockout_warning_description">Bitte versuche es in 30 Sekunden erneut oder scanne die Karte</string>
<string name="biometric_lockout_warning_description">Bitte versuche es in 30 Sekunden erneut oder scanne die Karte oder Ring</string>
<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">Verwende eine Bankkarte oder eine andere Zahlungsmethode</string>
<plurals name="card_label_card_count">
<item quantity="one">%d Karte oder Ring</item>
<item quantity="other">%d Karten oder Ringe</item>
<item quantity="one">%d Gerät</item>
<item quantity="other">%d Geräte</item>
</plurals>
<string name="card_settings_access_code_recovery_disabled_description">Deaktiviere diese Option, wenn du nicht möchtest, dass diese Karte oder Ring zum Zurücksetzen von Zugangscodes auf anderen Karten oder Ringe in dieser Wallets verwendet wird. Bitte beachte, dass du dann auch den Zugangscode auf dieser Karte oder Ring nicht zurücksetzen kannst.</string>
<string name="card_settings_access_code_recovery_enabled_description">Ermöglicht die Verwendung dieser Karte oder Ring zum Zurücksetzen des Zugangscodes auf anderen Karten oder Ringe in dieser Brieftasche</string>
@ -51,15 +51,15 @@
<string name="card_settings_action_sheet_title">Möchtest du das wirklich tun?</string>
<string name="card_settings_change_access_code">Zugangscode ändern</string>
<string name="card_settings_change_access_code_footer">Der Zugangscode wird nur auf dieser Karte oder Ring geändert</string>
<string name="card_settings_completed_reset_alert_message">Alle Karten oder Ringe der ausgewählten Wallet wurden auf die Werkseinstellungen zurückgesetzt. Du kannst nun eine neue Wallet aufsetzen.</string>
<string name="card_settings_completed_reset_alert_message">Alle Tangem Geräte der ausgewählten Wallet wurden auf die Werkseinstellungen zurückgesetzt. Du kannst nun eine neue Wallet aufsetzen.</string>
<string name="card_settings_completed_reset_alert_title">Komplett zurücksetzen</string>
<string name="card_settings_continue_reset_alert_message">Möchtest du die nächste Karte oder Ring in dieser Wallet zurücksetzen?</string>
<string name="card_settings_continue_reset_alert_message">Möchtest du die nächsten geräte in dieser Wallet zurücksetzen?</string>
<string name="card_settings_continue_reset_alert_title">Karte oder Ring zurücksetzen</string>
<string name="card_settings_interrupted_reset_alert_message">Wir empfehlen dir, den Zurücksetzungsprozess für alle Karten oder Ringe in dieser Wallet abzuschließen</string>
<string name="card_settings_interrupted_reset_alert_title">Du hast nicht alle deine Karten oder Ringe zurückgesetzt</string>
<string name="card_settings_interrupted_reset_alert_message">Wir empfehlen dir, den Zurücksetzungsprozess für aller Geräte in dieser Wallet abzuschließen</string>
<string name="card_settings_interrupted_reset_alert_title">Du hast nicht alle deine Geräte zurückgesetzt</string>
<string name="card_settings_reset_card_to_factory">Auf Werkseinstellungen zurücksetzen</string>
<string name="card_settings_security_mode">Sicherheitsmodus</string>
<string name="card_settings_title">Karteneinstellungen</string>
<string name="card_settings_title">Geräteeinstellungen</string>
<string name="cardano_coin_will_be_send_with_token_description">Zusätzlich zu den Netzwerkgebühren erhebt das Cardano-Netzwerk %1$s ADA bei Transaktionen mit dem Token %2$s </string>
<string name="cardano_coin_will_be_send_with_token_title">Cardano-Transaktionsanforderungen</string>
<string name="cardano_insufficient_balance_to_send_token_description">Um eine %1$s Transaktion durchzuführen, musst du einen gewissen ADA-Betrag einzahlen, um die Netzwerkgebühr und den ADA-Mindestwert zu decken (5 ADA werden empfohlen).</string>
@ -83,10 +83,12 @@
<string name="common_buy_currency">Gehe zu %1$s</string>
<string name="common_camera_denied_alert_message">D hast keinen Zugang zur Kamera erteilt, bitte passe deine Datenschutzeinstellungen an</string>
<string name="common_cancel">Abbrechen</string>
<string name="common_change">Ändern</string>
<string name="common_choose_action">Aktion wählen</string>
<string name="common_claim">Beanspruchen</string>
<string name="common_claim_rewards">Stakingbelohnungen beanstpruchen</string>
<string name="common_close">Schließen</string>
<string name="common_confirm">Bestätigen</string>
<string name="common_continue">Weiter</string>
<string name="common_copy">Kopieren</string>
<string name="common_copy_address">Adresse kopieren</string>
@ -119,14 +121,14 @@
<string name="common_generate_addresses">Adressen abrufen</string>
<string name="common_go_to_provider">Zum Anbieter gehen</string>
<string name="common_go_to_token">Zum Token</string>
<string name="common_hour">Stunde</string>
<string name="common_hour">stunde</string>
<string name="common_import">Importieren</string>
<string name="common_in_progress">In Arbeit</string>
<string name="common_later">Später</string>
<string name="common_left">%1$s übrig</string>
<string name="common_locked">Gesperrt</string>
<string name="common_main_network">Hauptnetz</string>
<string name="common_month">Monat</string>
<string name="common_month">monat</string>
<string name="common_network_fee_title">Netzgebühr</string>
<string name="common_network_fee_warning_content">Der überwiesene Betrag wird um %1$s (%2$s) gekürzt, um die gewählte Gebührenhöhe zu decken.</string>
<string name="common_next">Weiter</string>
@ -176,7 +178,7 @@
<string name="common_unknown_error">Es ist ein Fehler aufgetreten. Bitte versuche es erneut.</string>
<string name="common_unreachable">Nicht erreichbar</string>
<string name="common_unstake">staking beenden</string>
<string name="common_week">Woche</string>
<string name="common_week">woche</string>
<string name="common_yes">Ja</string>
<string name="contract_address_copied_message">Vertragsadresse kopiert!</string>
<string name="currency_subtitle_expanded">Verfügbare Netzwerke</string>
@ -213,13 +215,13 @@
<string name="details_manage_security_access_code">Zugangscode</string>
<string name="details_manage_security_access_code_description">Du musst den richtigen Zugangscode eingeben, bevor du die Karte oder Ring scannst.</string>
<string name="details_manage_security_long_tap">Langes Tippen</string>
<string name="details_manage_security_long_tap_description">Dieser Mechanismus schützt vor Annäherungsangriffen auf eine Karte oder Ring. Es wird eine Verzögerung zwischen dem Empfang und der Ausführung eines Befehls erzwungen. Nach der ersten signierten Transaktion wird dieses Telefon mit der Karte oder Ring verknüpft und die Transaktionen werden sofort signiert.</string>
<string name="details_manage_security_long_tap_description">Dieser Mechanismus schützt vor Annäherungsangriffen auf eine Karte oder einen Ring. Er erzwingt eine Verzögerung zwischen dem Empfang und der Ausführung eines Befehls.</string>
<string name="details_manage_security_passcode">Passcode</string>
<string name="details_manage_security_passcode_description">Bevor du einen Befehl ausführst, der eine Änderung des Kartenstatus zur Folge hat, musst du den Passcode eingeben.</string>
<string name="details_referral_title">Empfehlungsprogramm</string>
<string name="details_row_description_flip_to_hide">Flippe den Bildschirm deines Geräts nach unten, um Salden schnell ein- und auszublenden</string>
<string name="details_row_subtitle_signed_hashes_format">%s Hasch</string>
<string name="details_row_title_cid">Karten- oder Ring-ID</string>
<string name="details_row_title_cid">Geräte-ID</string>
<string name="details_row_title_contact_to_support">Kontakt zum Support</string>
<string name="details_row_title_create_backup">Weitere Karten oder Ringe verknüpfen</string>
<string name="details_row_title_currency">App Währung</string>
@ -257,6 +259,7 @@
<string name="express_exchange_status_exchanging">Tauschen läuft</string>
<string name="express_exchange_status_exchanging_active">Austauschen...</string>
<string name="express_exchange_status_failed">Fehlgeschlagen</string>
<string name="express_exchange_status_paused">Pausiert</string>
<string name="express_exchange_status_received">Einzahlung empfangen</string>
<string name="express_exchange_status_receiving">Einzahlung wird erwartet</string>
<string name="express_exchange_status_receiving_active">Warten auf Einzahlung...</string>
@ -297,17 +300,16 @@
<string name="feedback_subject_tx_failed">Eine Transaktion kann nicht gesendet werden</string>
<string name="feedback_token_description_error">Fehler in der Coinbeschreibung</string>
<string name="give_permission_current_transaction">Nur diese</string>
<string name="give_permission_fee_footer">Das Netzwerk erhebt eine Token-Genehmigungsgebühr, um zu überprüfen, ob Sie die Verwendung Ihres Tokens für den Swap genehmigen.</string>
<string name="give_permission_policy_type_footer">Gib das Genehmigungslimit für das ausgewählte Token an</string>
<string name="give_permission_rows_amount">Betrag %s</string>
<string name="give_permission_staking_footer">Die Genehmigungsfunktion ist erforderlich, um einer anderen Adresse die Berechtigung zur Verwendung einer bestimmten Menge Ihrer Token zu erteilen. Standardmäßig können Smart Contracts nicht auf deine Token zugreifen, es sei denn, du stimmen zu. Indem du deine Token \"freischaltest\", autorisierst du den StakeKit Smart Contract, sie zu verwenden. Die Miner des Netzwerks erhalten eine Gasgebühr (von dir bezahlt), um diese Aktion in der Blockchain aufzuzeichnen. Du kannst deine Token einsetzen, nachdem du die Genehmigung erteilt hast.</string>
<string name="give_permission_staking_subtitle">Um fortzufahren, musst du StakeKit Smart Contract erlauben, deine %s zu verwenden</string>
<string name="give_permission_staking_subtitle">Um fortzufahren, musst du Polygon Smart Contract erlauben, deine %s zu verwenden</string>
<string name="give_permission_swap_subtitle" formatted="false">Um fortzufahren, erteile %1s Smart Contracts die Berechtigung, dein zu %2s verwenden.</string>
<string name="give_permission_title">Erlaubnis erteilen</string>
<string name="give_permission_unlimited">Unbegrenzt</string>
<string name="home_button_order">Karte oder Ring bestellen</string>
<string name="home_button_scan">Karte oder Ring scannen</string>
<string name="information_generated_with_ai">Diese Information ist KI generiert</string>
<string name="information_generated_with_ai">Diese Informationen wurden mithilfe von KI generiert.\nTippe hier, wenn Du Fehler finden.</string>
<string name="initial_message_change_access_code_body">Um den Zugangscode zu ändern, halte die Karte oder Ring wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs.</string>
<string name="initial_message_change_passcode_body">Um den Passcode zu ändern, halte die Karte oder Ring wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs.</string>
<string name="initial_message_create_wallet_body">Um die Wallet zu erstellen, halte die Karte oder Ring wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs.</string>
@ -390,8 +392,8 @@
<string name="markets_sort_by_trending_title">Beliebt</string>
<string name="markets_token_details_about_token_title">Über %s</string>
<plurals name="markets_token_details_amount_exchanges">
<item quantity="one">%d Börse</item>
<item quantity="other">%d Börsen</item>
<item quantity="one">%d börse</item>
<item quantity="other">%d börsen</item>
</plurals>
<plurals name="markets_token_details_based_on_ratings">
<item quantity="one">Bewertung, basierend auf %d</item>
@ -427,7 +429,6 @@
<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_listed_on">Gelistet auf</string>
<string name="markets_token_details_low">Niedrig</string>
<string name="markets_token_details_market_capitalization">MarketCap</string>
@ -455,11 +456,11 @@
<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>
<string name="onboarding_access_code_feature_1_description">Du musst einen einzigen Zugangscode einrichten, um alle deine Karten oder Ringe zu schützen</string>
<string name="onboarding_access_code_feature_1_description">Du musst einen einzigen Zugangscode einrichten, um alle deine Geräte zu schützen</string>
<string name="onboarding_access_code_feature_1_title">Schützen</string>
<string name="onboarding_access_code_feature_2_description">Du kannst später auf jeder Karte oder Ring einen individuellen Zugangscode einrichten</string>
<string name="onboarding_access_code_feature_2_title">Personalisieren</string>
<string name="onboarding_access_code_feature_3_description">Der Zugangscode kann mit einer verbundenen Karte oder Ring wiederhergestellt werden. Bewahre nicht alle Karten oder Ringe an einem Ort auf.</string>
<string name="onboarding_access_code_feature_3_description">Stelle den Zugangscode mit einem verknüpften Gerät wieder her. Bewahre nicht alle Deine Geräte an einem Ort auf.</string>
<string name="onboarding_access_code_feature_3_title">Wiederherstellen</string>
<string name="onboarding_access_code_hint">Wähle ein beliebiges Wort, eine Phrase oder eine Zahl als Zugangscode</string>
<string name="onboarding_access_code_intro_title">Zugangscode erstellen</string>
@ -470,7 +471,7 @@
<string name="onboarding_activation_error_message">Bitte wiederhole den Vorgang. Die Karte oder Ring wird auf Werkseinstellungen zurückgesetzt.</string>
<string name="onboarding_activation_error_title">Aktivierungsfehler</string>
<string name="onboarding_add_tokens">Token hinzufügen</string>
<string name="onboarding_alert_message_not_max_backup_cards_added">Du hast eine Backup-Karte oder Ring hinzugefügt. Wenn der Backup-Prozess abgeschlossen ist, kannst du keine weiteren Backup-Karten oder Ringe hinzufügen. Wenn du noch eine Karte oder Ring hast, füge diese zum Backup hinzu. Möchtest du den Backup-Prozess fortsetzen?</string>
<string name="onboarding_alert_message_not_max_backup_cards_added">Du hast einee Backup-Karte oder einen Backup-Ring hinzugefügt. Wenn der Backup-Prozess abgeschlossen ist, kannst Du keine weiteren Backup-Geräte hinzufügen. Wenn Du noch eine Karte oder einen Ring hast, fügen diese(n) zum Backup hinzu. Möchtest Du den Backup-Prozess fortsetzen?</string>
<string name="onboarding_backup_exit_warning">Der Sicherungsvorgang ist teilweise abgeschlossen. Du kannst ihn jetzt nicht beenden.</string>
<string name="onboarding_bottom_sheet_passphrase_description">Die Passphrase ist eine fortschrittliche Sicherheitsfunktion, die von Krypto-Wallets verwendet wird. Sie fügt ein zusätzliches Wort oder eine Phrase deiner Wahl zu der bereits bestehenden Wiederherstellungsphrase hinzu, um einen brandneuen Satz von Adressen zu erzeugen.</string>
<string name="onboarding_button_add_backup_card">Hinzufügen einer Sicherungskarte oder Ring</string>
@ -525,16 +526,16 @@
<string name="onboarding_subtitle_scan_primary_card_format">Bereite die primäre Karte oder Ring mit der Nummer %s vor.</string>
<string name="onboarding_subtitle_scan_ring">Bereite den Ring vor und drücke unten die Scan-Taste</string>
<string name="onboarding_subtitle_success_tangem_wallet_onboarding">Deine Tangem-Karte oder Ring ist konfiguriert und einsatzbereit.</string>
<string name="onboarding_subtitle_two_backup_cards">Maximale Anzahl an Karten oder Ringe hinzugefügt. Schließe den Sicherungsvorgang ab.</string>
<string name="onboarding_subtitle_two_backup_cards">Maximale Anzahl an Geräten hinzugefügt. Schließe den Sicherungsvorgang ab.</string>
<string name="onboarding_title">Karte oder Ring aktivieren</string>
<string name="onboarding_title_backup_card">Sicherungs-Karte oder Ring</string>
<string name="onboarding_title_backup_card_format">Sicherungskarte oder Ring Nr. %d</string>
<string name="onboarding_title_backup_ring">Sicherungs-Ring</string>
<string name="onboarding_title_no_backup_cards">Keine Sicherungskarten oder Sicherungsring</string>
<string name="onboarding_title_no_backup_cards">Keine Sicherungsgeräte</string>
<string name="onboarding_title_notifications">Benachrichtigungen</string>
<string name="onboarding_title_one_backup_card">Eine Backup-Karte oder Ring hinzugefügt</string>
<string name="onboarding_title_one_backup_card">Eine Backupgerät hinzugefügt</string>
<string name="onboarding_title_scan_origin_card">Bereite deine Karte oder Ring vor</string>
<string name="onboarding_title_two_backup_cards">Zwei Backup-Karten oder Ring hinzugefügt</string>
<string name="onboarding_title_two_backup_cards">Zweis Backupgerät hinzugefügt</string>
<string name="onboarding_top_up_body">Um zu beginnen, lade einfach die wallet mit einem beliebigen Betrag auf</string>
<string name="onboarding_top_up_body_no_account_error">Um zu beginnen, lade die Wallet einfach mit mehr als %1$s %2$s auf.</string>
<string name="onboarding_top_up_button_but_crypto">Krypto kaufen</string>
@ -550,6 +551,9 @@
<string name="onboarding_wallet_info_title_fourth">Zugangscode wiederherstellen</string>
<string name="onboarding_wallet_info_title_second">Identische Karten oder Ring</string>
<string name="onboarding_wallet_info_title_third">Zugangscode</string>
<string name="onramp_residency_bottomsheet_country_not_supported">Unsere Dienstleistungen sind in diesem Land nicht verfügbar</string>
<string name="onramp_residency_bottomsheet_country_subtitle">Änder oder bestätige bitte</string>
<string name="onramp_residency_bottomsheet_title">Dein Wohnsitz wurde identifiziert als</string>
<string name="organize_tokens_group">Gruppe erstellen</string>
<string name="organize_tokens_sort_by_balance">Nach Guthaben</string>
<string name="organize_tokens_title">Token organisieren</string>
@ -609,8 +613,8 @@
<string name="save_user_wallet_agreement_header_biometrics">Möchtest du Biometrie nutzen?</string>
<string name="save_user_wallet_agreement_notice">Beachte, dass für Transaktionen mit deinem Guthaben weiterhin deine Karte oder Ring erforderlich ist</string>
<string name="scan_card_settings_button">Karte oder Ring scannen</string>
<string name="scan_card_settings_message">Scanne die Karte oder Ring, um ihre Einstellungen zu ändern. Die Änderungen wirken sich nur auf die von dir gescannte Karte oder Ring aus und haben keine Auswirkungen auf andere mit deiner Wallet verknüpften Karten oder Ringe.</string>
<string name="scan_card_settings_title">Halte deine Karte bereit!</string>
<string name="scan_card_settings_message">Scanne die Karte oder Ring, um ihre Einstellungen zu ändern. Die Änderungen wirken sich nur auf die von dir gescannte Karte oder Ring aus und haben keine Auswirkungen auf andere mit deiner Wallet verknüpften Geräte.</string>
<string name="scan_card_settings_title">Halte deine Karte oder Ring bereit!</string>
<string name="send_additional_field_already_included">Bereits in der eingegebenen Adresse enthalten</string>
<string name="send_alert_fee_too_high_text">Der Provisionsbetrag ist %s mal der empfohlene Betrag. Stelle sicher, dass die benutzerdefinierten Einstellungen korrekt sind.</string>
<string name="send_alert_fee_too_low_text">Du hast eine Kommission angegeben, die unter dem empfohlenen Betrag liegt, was zu einer Verzögerung Ihrer Transaktion führen könnte. Weiter?</string>
@ -710,13 +714,14 @@
<string name="staking_details_reward_claiming">Belohnungen beanspruchen</string>
<string name="staking_details_reward_claiming_info">Eine Möglichkeit, Staking-Belohnungen zu erhalten. Es kann automatisch oder manuell beansprucht werden.</string>
<string name="staking_details_reward_schedule">Belohnungszeitplan</string>
<string name="staking_details_reward_schedule_info">Dabei handelt es sich um einen Zeitplan, der festlegt, wann die Teilnehmer am Staking ihre Belohnungen erhalten.</string>
<string name="staking_details_reward_schedule_info">Dies ist ein Zeitplan, der bestimmt, wann Teilnehmer am Staking ihre Belohnungen erhalten. Der Zeitpunkt der Belohnungsverteilung kann je nach Validator und Netzwerklast leicht variieren.</string>
<string name="staking_details_rewards_to_claim">Belohnungen %s</string>
<string name="staking_details_title">Staking %s</string>
<string name="staking_details_unbonding_period">Entbindungsdauer</string>
<string name="staking_details_unbonding_period_info">Der Zeitraum, den du nach der Beantragung der Abhebung von Geldern aus dem Staking warten musst, bevor die Token verfügbar werden.</string>
<string name="staking_details_warmup_period">Aufwärmphase</string>
<string name="staking_details_warmup_period_info">Die zugewiesene Zeit für die Aktivierung der Teilnahme am Staking.</string>
<string name="staking_give_permission_fee_footer">Das Netzwerk erhebt eine Token-Genehmigungsgebühr, um zu überprüfen, ob Du die Verwendung Deines Tokens für das Staking genehmigst.</string>
<string name="staking_legal">Indem Du die Staking-Funktionalität nutzt, stimmst Du den %1$s und %2$s des Anbieters zu.</string>
<string name="staking_locked">Gesperrt</string>
<string name="staking_migrate">Migrieren</string>
@ -736,6 +741,7 @@
<string name="staking_notification_network_error_text">Aufgrund von Netzwerkproblemen ist Staking derzeit nicht verfügbar. Bitte versuche es später erneut.</string>
<string name="staking_notification_new_validator_funds_transfer">Beim Staking im %1$s -Netzwerk mit einem neuen Validator werden alle zuvor eingesetzten Kryptos automatisch an diesen Validator übertragen</string>
<string name="staking_notification_restake_rewards_text">Reinvestiert Deine verdienten Prämien in Deinen Einsatzbetrag und erhöht so den potenziellen Gewinn.</string>
<string name="staking_notification_restake_text">Mit Restake kannst Du Dein Guthaben von einem Validator zu einem anderen verschieben, ohne dass Du den Stake aufheben musst.</string>
<string name="staking_notification_unlock_text">Entsperre dein Geld, um es aus dem Staking-Prozess abzuheben. Das Freischalten nimmt %s.</string>
<string name="staking_notification_unstake_cosmos_text">Nach Ablauf der 21-tägigen Bindungsfrist kannst Du über Dein Guthaben verfügen. Die Prämie wird zusammen mit dem ungestaketen Guthaben abgehoben.</string>
<string name="staking_notification_unstake_text">Deine Assets steht Dir nach Ablauf der Frist für die Aufhebung der Bindung %s zur Verfügung.</string>
@ -754,6 +760,8 @@
<string name="staking_reward_schedule_day">Täglich</string>
<string name="staking_reward_schedule_each">Alle %s</string>
<string name="staking_reward_schedule_each_day">Täglich</string>
<string name="staking_reward_schedule_each_days">Alle %s</string>
<string name="staking_reward_schedule_each_plural">Jeder</string>
<string name="staking_reward_schedule_epoch">Pro Epoche</string>
<string name="staking_reward_schedule_era">Pro Ära</string>
<string name="staking_reward_schedule_hour">Stündlich</string>
@ -762,7 +770,7 @@
<string name="staking_rewards">Belohnungen</string>
<string name="staking_stake_locked">Stake gesperrt</string>
<string name="staking_stake_more">Mehr staken</string>
<string name="staking_summary_description_text">Du setzt %1$s ein und erhältst jährlich %2$s</string>
<string name="staking_summary_description_text">Du setzt %1$s ein und ethältst Deine Belohnung %2$s</string>
<string name="staking_tap_to_unlock">Zum Entsperren antippen</string>
<string name="staking_tap_to_unlock_or_vote">Tippe zum Entsperren oder Abstimmen</string>
<string name="staking_tap_to_withdraw">Zum abheben antippen</string>
@ -772,6 +780,7 @@
<string name="staking_unbonding">Lösen der Bindungen</string>
<string name="staking_unlocked_locked">Gelocktes unlocken</string>
<string name="staking_unlocking">Entsperren</string>
<string name="staking_unstake_amount_validation_error">Der Betrag übersteigt das eingesetzte Guthaben</string>
<string name="staking_unstaked">Unstaken</string>
<string name="staking_unstaking">Staking beenden</string>
<string name="staking_unstaking_item_name">Unstake Assets %s</string>
@ -793,6 +802,7 @@
<string name="story_meet_title">Lerne Tangem kennen</string>
<string name="story_web3_description">Tausche, kaufen Sie NFTs, vergebe Kredite und tätige Einlagen bei mehr als 100 verschiedenen dezentralen Diensten</string>
<string name="story_web3_title">Web 3.0-kompatibel</string>
<string name="swap_give_permission_fee_footer">Das Netzwerk erhebt eine Token-Genehmigungsgebühr, um zu überprüfen, ob Sie die Verwendung Ihres Tokens für den Swap genehmigen.</string>
<string name="swap_promo_text">Tausche mehr Token zu besseren Kursen direkt in deiner Brieftasche.</string>
<string name="swap_promo_title">Neuer Swap-Anbieter verfügbar!</string>
<string name="swapping_alert_cex_description">Der Betrag umfasst:\n- Gebühr des Dienstanbieters\n- Netzgebühr für die Rücksendung von %s von der Vermittlungsstelle an die Adresse des Nutzers.</string>
@ -879,6 +889,7 @@
<string name="wallet_connect_create_tx_message">Antrag auf Erstellung einer Transaktion für %1$s\n%2$s\n\nBetrag: %3$s\nGebühr: %4$s\nGesamt: %5$s\nSaldo: %6$s</string>
<string name="wallet_connect_create_tx_not_enough_funds">Die Transaktion kann nicht gesendet werden. Nicht genügend Guthaben.</string>
<string name="wallet_connect_error_failed_to_connect">WalletConnect Sitzung konnte nicht aufgebaut werden. Bitte versuche es später noch einmal.</string>
<string name="wallet_connect_error_missing_blockchains">Nicht alle Token wurden zu Deiner Liste hinzugefügt. Bitte füge sie zuerst hinzu und versuche es erneut. Fehlende Token: \n</string>
<string name="wallet_connect_error_sing_failed">Nachricht konnte nicht signiert werden.\nBitte, versuche es erneut</string>
<string name="wallet_connect_error_timeout">WalletConnect-Sitzung konnte nicht aufgebaut werden: Timeout-Fehler. Bitte versuche es später noch einmal.</string>
<string name="wallet_connect_error_unsupported_blockchains">Sitzungsanfrage enthält nicht unterstützte Blockchains für WalletConnect-Verbindung. Nicht unterstützte Blockchains:\n</string>
@ -955,7 +966,7 @@
<string name="warning_low_signatures_message">Auf dieser Karte oder Ring sind nur noch %s Unterschriften übrig. Du musst dein gesamtes Guthaben abheben.</string>
<string name="warning_low_signatures_title">Geringe Anzahl von Unterschriften</string>
<string name="warning_manage_tokens_legacy_derivation_message">Token in verschiedenen Netzwerken können unterschiedliche Adressen haben. Überprüfe bei der Überweisung noch einmal, ob deine Adresse mit der des Netzwerks übereinstimmt.</string>
<string name="warning_matic_migration_message">MATIC wird auf POL migriert. Es gibt jedoch keine Frist, und MATIC wird noch nicht abgeschafft. Du kannst MATIC-Token weiterhin verwenden oder sie über eien Exchange gegen POL tauschen.</string>
<string name="warning_matic_migration_message">MATIC wird zu POL migriert. Es gibt jedoch keine festgelegte Frist und MATIC wird noch nicht abgeschafft. Du kannst den MATIC-Token weiterhin bedenkenlos verwenden oder es gegen POL austauschen.</string>
<string name="warning_matic_migration_title">Migration von MATIC zu POL</string>
<plurals name="warning_missing_derivation_message">
<item quantity="one">Verwende deine Karte oder Ring, um eine Adresse für das %d-Netz zu erhalten</item>
@ -986,7 +997,7 @@
<string name="welcome_interrupted_backup_alert_message">Du hast eine unterbrochene Sicherung. Möchtest du diese fortsetzen?</string>
<string name="welcome_interrupted_backup_alert_resume">Ja, fortsetzen</string>
<string name="welcome_interrupted_backup_discard_discard">Verwerfen</string>
<string name="welcome_interrupted_backup_discard_message">Wenn du das Backup jetzt abbrichst, musst du die Karten oder Ringe auf die Werkseinstellungen zurücksetzen, um von vorne zu beginnen</string>
<string name="welcome_interrupted_backup_discard_message">Wenn du das Backup jetzt abbrichst, musst du die Geräte auf die Werkseinstellungen zurücksetzen, um von vorne zu beginnen</string>
<string name="welcome_interrupted_backup_discard_resume">Sicherung fortsetzen</string>
<string name="welcome_interrupted_backup_discard_title">Dies ist eine unwiderrufliche Aktion</string>
<string name="welcome_unlock">Anmelden mit %s</string>

View file

@ -83,10 +83,12 @@
<string name="common_buy_currency">Ir a %1$s</string>
<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_change">Cambie</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_confirm">confirme</string>
<string name="common_continue">Continuar</string>
<string name="common_copy">Copiar</string>
<string name="common_copy_address">Copiar la dirección</string>
@ -97,6 +99,10 @@
<item quantity="one">%d día</item>
<item quantity="other">%d días</item>
</plurals>
<plurals name="common_days_no_param">
<item quantity="one">día</item>
<item quantity="other">días</item>
</plurals>
<string name="common_delete">Suprimir</string>
<string name="common_disabled">Desactivado</string>
<string name="common_done">Listo</string>
@ -115,12 +121,14 @@
<string name="common_generate_addresses">Obtener direcciones</string>
<string name="common_go_to_provider">Ir al proveedor</string>
<string name="common_go_to_token">Ir al token</string>
<string name="common_hour">hora</string>
<string name="common_import">Importe</string>
<string name="common_in_progress">En progreso</string>
<string name="common_later">Más tarde</string>
<string name="common_left">%1$s quedan</string>
<string name="common_locked">Bloqueado</string>
<string name="common_main_network">Red principal</string>
<string name="common_month">mes</string>
<string name="common_network_fee_title">Tarifa de la red</string>
<string name="common_network_fee_warning_content">La cantidad enviada se reducirá en %1$s (%2$s) para cubrir el nivel de tarifa seleccionado</string>
<string name="common_next">Siguiente</string>
@ -142,8 +150,9 @@
<string name="common_rename">Renombrar</string>
<string name="common_save">Guarde</string>
<string name="common_save_changes">Guardar cambios</string>
<string name="common_search">Buscar en el mercado</string>
<string name="common_search">Buscar</string>
<string name="common_search_tokens">Buscar tokens</string>
<string name="common_second_no_param">sec</string>
<string name="common_seed_phrase">Seed phrase</string>
<string name="common_select_action">Seleccione una acción</string>
<string name="common_sell">Vender</string>
@ -169,6 +178,7 @@
<string name="common_unknown_error">Hubo un error. Por favor inténtelo de nuevo.</string>
<string name="common_unreachable">Inaccesible</string>
<string name="common_unstake">Termine el staking</string>
<string name="common_week">semana</string>
<string name="common_yes"></string>
<string name="contract_address_copied_message">Dirección del contract copiada</string>
<string name="currency_subtitle_expanded">Redes disponibles</string>
@ -249,6 +259,7 @@
<string name="express_exchange_status_exchanging">En intercambio</string>
<string name="express_exchange_status_exchanging_active">En intercambio</string>
<string name="express_exchange_status_failed">Fallido</string>
<string name="express_exchange_status_paused">En pausa</string>
<string name="express_exchange_status_received">Depósito recibido</string>
<string name="express_exchange_status_receiving">Esperando depósito</string>
<string name="express_exchange_status_receiving_active">Esperando depósito</string>
@ -287,18 +298,18 @@
<string name="feedback_subject_support">Comentarios</string>
<string name="feedback_subject_support_tangem">Comentarios en Tangem</string>
<string name="feedback_subject_tx_failed">No se puede completar una transacción</string>
<string name="feedback_token_description_error">Error de descripción de moneda</string>
<string name="give_permission_current_transaction">Esta transacción</string>
<string name="give_permission_fee_footer">La red cobrará una tarifa de aprobación de token para verificar que está autorizando el uso de su token para el swap.</string>
<string name="give_permission_policy_type_footer">Especifique el límite aprobado para el token seleccionado.</string>
<string name="give_permission_rows_amount">Montante %s</string>
<string name="give_permission_staking_footer">La función Aprobar es necesaria para otorgar permiso a otra dirección para usar una cantidad específica de sus tokens. Por diseño, los contratos inteligentes no pueden acceder a sus tokens sin su aprobación. Al \"desbloquear\" sus tokens, autoriza al contrato inteligente de StakeKit a usarlos. Los mineros de la red reciben una tarifa de gas (pagada por usted) por registrar esta acción en la cadena de bloques. Puede apostar su token después de dar su aprobación.</string>
<string name="give_permission_staking_subtitle">Para continuar, debe autorizar el contrato inteligente de StakeKit para utilizar su %s</string>
<string name="give_permission_staking_subtitle">Para continuar, debe autorizar el contrato inteligente de Polygon para utilizar su %s</string>
<string name="give_permission_swap_subtitle" formatted="false">Para continuar, de autorización a los smart contracts de %1s para usar su %2s</string>
<string name="give_permission_title">Dar autorización</string>
<string name="give_permission_unlimited">Ilimitado</string>
<string name="home_button_order">Ordenar </string>
<string name="home_button_scan">Escanee</string>
<string name="information_generated_with_ai">Esta información fue generada con IA</string>
<string name="information_generated_with_ai">Esta información fue generada con IA.\nPulse aquí si encuentra algún error.</string>
<string name="initial_message_change_access_code_body">Toque para cambiar la contraseña</string>
<string name="initial_message_change_passcode_body">Toque para cambiar la contraseña</string>
<string name="initial_message_create_wallet_body">Para crear la billetera, toque la tarjeta como se muestra arriba y no la retire hasta el final de la operación</string>
@ -347,6 +358,7 @@
<string name="manage_tokens_wallet_support_only_one_network_title">La billetera no admite más de una red</string>
<string name="markets_add_to_my_portfolio_description">Para comprar, intercambiar o recibir este activo, agréguelo a su portafolio</string>
<string name="markets_add_to_my_portfolio_unavailable_description">Este activo no está disponible en la billetera</string>
<string name="markets_add_to_my_portfolio_unavailable_for_wallet_description">Este activo no está disponible para esta billetera</string>
<string name="markets_add_to_portfolio_button">Añadir al portafolio</string>
<string name="markets_add_token">Agregue un token</string>
<string name="markets_available_networks">Redes disponibles</string>
@ -379,6 +391,10 @@
<string name="markets_sort_by_top_losers_title">Top Perdedores</string>
<string name="markets_sort_by_trending_title">Tendencias</string>
<string name="markets_token_details_about_token_title">Acerca de %s</string>
<plurals name="markets_token_details_amount_exchanges">
<item quantity="one">%d intercambio</item>
<item quantity="other">%d intercambios</item>
</plurals>
<plurals name="markets_token_details_based_on_ratings">
<item quantity="one">Basado en %d evaluación </item>
<item quantity="other">Basado en %d evaluaciónes</item>
@ -390,6 +406,12 @@
<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_empty_exchanges">No se encontraron intercambios</string>
<string name="markets_token_details_exchange">Intercambio</string>
<string name="markets_token_details_exchange_trust_score_caution">Precaución</string>
<string name="markets_token_details_exchange_trust_score_risky">Arriesgado</string>
<string name="markets_token_details_exchange_trust_score_trusted">Confiable</string>
<string name="markets_token_details_exchanges_title">Intercambios</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>
@ -407,6 +429,7 @@
<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_listed_on">Listado en</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>
@ -429,6 +452,7 @@
<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_token_details_volume">Volumen</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>
@ -477,12 +501,12 @@
<string name="onboarding_navbar_title_creating_backup">Creando un backup</string>
<string name="onboarding_seed_button_read_more">Leer más sobre seed phrase</string>
<plurals name="onboarding_seed_generate_message_words_count">
<item quantity="one">Vacío</item>
<item quantity="one"></item>
<item quantity="other">Escriba estas %d palabras en el orden que se indica a continuación y guárdelas en un lugar seguro y secreto.</item>
</plurals>
<string name="onboarding_seed_generate_title">Su seed phrase</string>
<plurals name="onboarding_seed_generate_words_count">
<item quantity="one">Vacío</item>
<item quantity="one"></item>
<item quantity="other">%d palabras</item>
</plurals>
<string name="onboarding_seed_import_message">Para importar su billetera, ingrese su seed phrase en el campo de abajo</string>
@ -527,6 +551,9 @@
<string name="onboarding_wallet_info_title_fourth">Restaurar código de acceso</string>
<string name="onboarding_wallet_info_title_second">Tarjetas idénticas</string>
<string name="onboarding_wallet_info_title_third">Código de acceso</string>
<string name="onramp_residency_bottomsheet_country_not_supported">Nuestros servicios no están disponibles en este país</string>
<string name="onramp_residency_bottomsheet_country_subtitle">Cámbielo o confírmelo</string>
<string name="onramp_residency_bottomsheet_title">Su residencia ha sido identificada como</string>
<string name="organize_tokens_group">Agrupar</string>
<string name="organize_tokens_sort_by_balance">Por saldo</string>
<string name="organize_tokens_title">Organizar tokens</string>
@ -687,13 +714,14 @@
<string name="staking_details_reward_claiming">Reclamo de recompensa</string>
<string name="staking_details_reward_claiming_info">Método para recibir recompensas por apuesta.\nPuede ser automático, donde la recompensa se acredita en tu dirección, o manual, donde debes retirar la recompensa creando una transacción para recibirla.</string>
<string name="staking_details_reward_schedule">Calendario de recompensas</string>
<string name="staking_details_reward_schedule_info">Este es un cronograma que determina cuándo los participantes reciben sus recompensas.</string>
<string name="staking_details_reward_schedule_info">Este es un cronograma que determina cuándo los participantes reciben sus recompensas. La duración de la distribución de recompensas puede variar ligeramente según el validador y la carga de la red.</string>
<string name="staking_details_rewards_to_claim">Recompensas para reclamar: %s</string>
<string name="staking_details_title">Staking %s</string>
<string name="staking_details_unbonding_period">Periodo de disociación</string>
<string name="staking_details_unbonding_period_info">El período que debes esperar después de solicitar el retiro de fondos del staking antes de que los tokens estén disponibles.</string>
<string name="staking_details_warmup_period">Periodo de calentamiento</string>
<string name="staking_details_warmup_period_info">El tiempo permitido para activar la participación en la apuesta.</string>
<string name="staking_give_permission_fee_footer">La red cobrará una tarifa de aprobación de token para verificar que usted está autorizando el uso de su token para el staking.</string>
<string name="staking_legal">Al utilizar la función de staking, usted acepta %1$s y %2$s del proveedor</string>
<string name="staking_locked">Bloqueado</string>
<string name="staking_migrate">Migrar</string>
@ -713,6 +741,7 @@
<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_restake_text">La opción de volver a staking le permite mover sus fondos de un validador a otro sin necesidad de retirarlos.</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>
@ -729,7 +758,10 @@
<string name="staking_reward_claiming_manual">Manual</string>
<string name="staking_reward_schedule_block">Bloquear</string>
<string name="staking_reward_schedule_day">Día</string>
<string name="staking_reward_schedule_each">Cada %s</string>
<string name="staking_reward_schedule_each_day">Cada día</string>
<string name="staking_reward_schedule_each_days">Cada %s</string>
<string name="staking_reward_schedule_each_plural">Cada</string>
<string name="staking_reward_schedule_epoch">Época</string>
<string name="staking_reward_schedule_era">Era</string>
<string name="staking_reward_schedule_hour">Hora</string>
@ -738,8 +770,9 @@
<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_summary_description_text">Ud hace el staking de %1$s y recibirá %2$s</string>
<string name="staking_tap_to_unlock">Toque para desbloquear</string>
<string name="staking_tap_to_unlock_or_vote">Pulse para desbloquear o votar</string>
<string name="staking_tap_to_withdraw">Toque para retirar</string>
<string name="staking_title_stake">Stake %s</string>
<string name="staking_title_unstake">El unstaking de %s</string>
@ -747,6 +780,7 @@
<string name="staking_unbonding">Desunión</string>
<string name="staking_unlocked_locked">Desbloquear</string>
<string name="staking_unlocking">Desbloqueando</string>
<string name="staking_unstake_amount_validation_error">El monto excede el saldo apostado</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>
@ -768,6 +802,7 @@
<string name="story_meet_title">Descubra Tangem</string>
<string name="story_web3_description">Intercambie, compre NFT, haga préstamos y depósitos en más de 100 servicios descentralizados diferentes</string>
<string name="story_web3_title">Compatible con Web 3.0</string>
<string name="swap_give_permission_fee_footer">La red cobrará una tarifa de aprobación de token para verificar que está autorizando el uso de su token para el swap.</string>
<string name="swap_promo_text">Intercambie más tokens a mejores tasas directamente en su billetera.</string>
<string name="swap_promo_title">¡Nuevo proveedor de intercambio disponible!</string>
<string name="swapping_alert_cex_description">El monto incluye:\n• Tarifas del proveedor de servicios\n• Tarifas de red por enviar %s desde el intercambio a la dirección del usuario.</string>
@ -818,6 +853,7 @@
<string name="transaction_history_operation">Operación</string>
<string name="transaction_history_transaction_from_address">desde: %s</string>
<string name="transaction_history_transaction_to_address">a: %s</string>
<string name="transaction_history_transaction_validator">validador: %s</string>
<string name="try_to_load_data_again_button_title">Inténtelo de nuevo</string>
<string name="twin_error_same_card">Ha escaneado la misma tarjeta. Para crear una billetera gemela, necesite escanear la tarjeta con no. %d</string>
<string name="twin_error_wrong_twin">Ha escaneado la tarjeta gemela incorrecta. Por favor, intente con otra</string>
@ -853,6 +889,7 @@
<string name="wallet_connect_create_tx_message">Solicitud para crear una transacción para %1$s\n%2$s\n\nMontante: %3$s\nComisión: %4$s\nTotal: %5$s\nSaldo: %6$s</string>
<string name="wallet_connect_create_tx_not_enough_funds">No se puede completar la transacción. Fondos insuficientes.</string>
<string name="wallet_connect_error_failed_to_connect">Error al establecer la sesión de WalletConnect. Por favor, inténtelo más tarde.</string>
<string name="wallet_connect_error_missing_blockchains">No todos los tokens se han agregado a su lista. Añádelos primero y vuelve a intentarlo. Tokens faltantes :\n</string>
<string name="wallet_connect_error_sing_failed">Error al firmar el mensaje.\nPor favor, inténtalo de nuevo</string>
<string name="wallet_connect_error_timeout">Error al establecer la sesión de WalletConnect: error de tiempo de espera. Por favor, inténtelo más tarde.</string>
<string name="wallet_connect_error_unsupported_blockchains">La solicitud de sesión contiene blockchains no compatibles para la conexión WalletConnect. Blockchains no compatibles:\n</string>

View file

@ -83,10 +83,12 @@
<string name="common_buy_currency">Aller à %1$s</string>
<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_change">Changez</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_confirm">Confirmez</string>
<string name="common_continue">Continuer</string>
<string name="common_copy">Copier</string>
<string name="common_copy_address">Copier l\'adresse</string>
@ -97,6 +99,10 @@
<item quantity="one">%d jour</item>
<item quantity="other">%d jours </item>
</plurals>
<plurals name="common_days_no_param">
<item quantity="one">jour</item>
<item quantity="other">jours</item>
</plurals>
<string name="common_delete">Supprimer</string>
<string name="common_disabled">Désactivé</string>
<string name="common_done">Exécuté</string>
@ -115,12 +121,14 @@
<string name="common_generate_addresses">Obtenir des adresses</string>
<string name="common_go_to_provider">Aller au fournisseur</string>
<string name="common_go_to_token">Aller au jeton</string>
<string name="common_hour">heure</string>
<string name="common_import">Importez</string>
<string name="common_in_progress">En cours</string>
<string name="common_later">Plus tard</string>
<string name="common_left">Il reste %1$s</string>
<string name="common_locked">Verrouillé</string>
<string name="common_main_network">Réseau principal</string>
<string name="common_month">mois</string>
<string name="common_network_fee_title">Commissions du réseau</string>
<string name="common_network_fee_warning_content">Le montant envoyé sera réduit de %1$s(%2$s) pour couvrir le niveau de frais sélectionné</string>
<string name="common_next">Suivant</string>
@ -144,6 +152,7 @@
<string name="common_save_changes">Sauvegarder les modifications</string>
<string name="common_search">Rechercher</string>
<string name="common_search_tokens">Rechercher des jetons</string>
<string name="common_second_no_param">sec</string>
<string name="common_seed_phrase">Seed phrase</string>
<string name="common_select_action">Sélectionnez une action</string>
<string name="common_sell">Vendre</string>
@ -169,6 +178,7 @@
<string name="common_unknown_error">Il y avait une erreur. Veuillez réessayer.</string>
<string name="common_unreachable">Inaccessible</string>
<string name="common_unstake">Unstakez</string>
<string name="common_week">semaine</string>
<string name="common_yes">Oui</string>
<string name="contract_address_copied_message">Adresse du contrat copiée !</string>
<string name="currency_subtitle_expanded">Réseaux disponibles</string>
@ -249,6 +259,7 @@
<string name="express_exchange_status_exchanging">En cours d\'échange</string>
<string name="express_exchange_status_exchanging_active">En cours d\'échange</string>
<string name="express_exchange_status_failed">Échoué</string>
<string name="express_exchange_status_paused">En pause</string>
<string name="express_exchange_status_received">Dépôt reçu</string>
<string name="express_exchange_status_receiving">En attente du dépôt</string>
<string name="express_exchange_status_receiving_active">En attente du dépôt</string>
@ -287,18 +298,18 @@
<string name="feedback_subject_support">Commentaires</string>
<string name="feedback_subject_support_tangem">Commentaires sur Tangem</string>
<string name="feedback_subject_tx_failed">Impossible d\'effectuer une transaction</string>
<string name="feedback_token_description_error">Erreur de description de la pièce</string>
<string name="give_permission_current_transaction">Cette transaction</string>
<string name="give_permission_fee_footer">Le réseau facturera des frais d\'approbation de jeton pour vérifier que vous autorisez l\'utilisation de votre jeton pour l\'échange.</string>
<string name="give_permission_policy_type_footer">Spécifiez la limite approuvée pour le jeton sélectionné</string>
<string name="give_permission_rows_amount">Montant %s</string>
<string name="give_permission_staking_footer">La fonction Approuver est nécessaire pour accorder la permission à une autre adresse d\'utiliser une quantité spécifique de vos jetons. De par leur conception, les contrats intelligents ne peuvent pas accéder à vos jetons sans votre approbation. En « déverrouillant » vos jetons, vous autorisez le contrat intelligent StakeKit à les utiliser. Les mineurs du réseau reçoivent des frais de gaz (payés par vous) pour enregistrer cette action sur la blockchain. Vous pouvez staker votre jeton après avoir donné votre approbation.</string>
<string name="give_permission_staking_subtitle">Pour continuer, vous devez autoriser le contrat intelligent StakeKit à utiliser votre %s</string>
<string name="give_permission_staking_subtitle">Pour continuer, vous devez autoriser le contrat intelligent Polygon à utiliser votre %s</string>
<string name="give_permission_swap_subtitle" formatted="false">Pour continuer, accordez aux smart contracts de %1s l\'autorisation d\'utiliser votre %2s</string>
<string name="give_permission_title">Donner l\'autorisation</string>
<string name="give_permission_unlimited">Illimité</string>
<string name="home_button_order">Commandez</string>
<string name="home_button_scan">Scannez</string>
<string name="information_generated_with_ai">Ces informations ont été générées avec l\'IA</string>
<string name="information_generated_with_ai">Ces informations ont été générées avec l\'IA.\nAppuyez ici si vous trouvez des erreurs.</string>
<string name="initial_message_change_access_code_body">Touchez, pour modifier le code d\'accès</string>
<string name="initial_message_change_passcode_body">Touchez, pour modifier le mot de passe</string>
<string name="initial_message_create_wallet_body">Pour créer le portefeuille, appuyez sur la carte comme indiqué ci-dessus et ne la retirez pas jusqu\'à la fin de l\'opération</string>
@ -347,6 +358,7 @@
<string name="manage_tokens_wallet_support_only_one_network_title">Le portefeuille ne prend pas en charge plus d\'un réseau</string>
<string name="markets_add_to_my_portfolio_description">Pour acheter, échanger ou recevoir cet actif, ajoutez-le à votre portefeuille</string>
<string name="markets_add_to_my_portfolio_unavailable_description">Cet actif n\'est plus pris en charge dans le portefeuille</string>
<string name="markets_add_to_my_portfolio_unavailable_for_wallet_description">Cet actif n\'est pas disponible pour ce portefeuille</string>
<string name="markets_add_to_portfolio_button">Ajouter au portfolio</string>
<string name="markets_add_token">Ajoutez un jeton</string>
<string name="markets_available_networks">Réseaux disponibles</string>
@ -379,6 +391,10 @@
<string name="markets_sort_by_top_losers_title">Top Perdants</string>
<string name="markets_sort_by_trending_title">Tendances</string>
<string name="markets_token_details_about_token_title">À propos de %s</string>
<plurals name="markets_token_details_amount_exchanges">
<item quantity="one">%d échange</item>
<item quantity="other">%d échanges</item>
</plurals>
<plurals name="markets_token_details_based_on_ratings">
<item quantity="one">Basé sur %d évaluation</item>
<item quantity="other">Basé sur %d évaluations</item>
@ -390,6 +406,12 @@
<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_empty_exchanges">Aucun échange trouvé</string>
<string name="markets_token_details_exchange">Échange</string>
<string name="markets_token_details_exchange_trust_score_caution">Précaution</string>
<string name="markets_token_details_exchange_trust_score_risky">Risqué</string>
<string name="markets_token_details_exchange_trust_score_trusted">Fiable</string>
<string name="markets_token_details_exchanges_title">Échanges</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>
@ -407,6 +429,7 @@
<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_listed_on">Listé sur</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>
@ -429,6 +452,7 @@
<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_token_details_volume">Volume</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>
@ -477,12 +501,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">Vide</item>
<item quantity="one"></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">Vide</item>
<item quantity="one"></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>
@ -527,6 +551,9 @@
<string name="onboarding_wallet_info_title_fourth">Restauration du code d\'accès</string>
<string name="onboarding_wallet_info_title_second">Cartes identiques</string>
<string name="onboarding_wallet_info_title_third">Code d\'accès</string>
<string name="onramp_residency_bottomsheet_country_not_supported">Nos services ne sont pas disponibles dans ce pays</string>
<string name="onramp_residency_bottomsheet_country_subtitle">Modifiez-le ou confirmez-le</string>
<string name="onramp_residency_bottomsheet_title">Votre résidence a été identifiée comme</string>
<string name="organize_tokens_group">Grouper</string>
<string name="organize_tokens_sort_by_balance">Par solde</string>
<string name="organize_tokens_title">Organiser les jetons</string>
@ -687,13 +714,14 @@
<string name="staking_details_reward_claiming">Réclamation de récompense</string>
<string name="staking_details_reward_claiming_info">Méthode de réception des récompenses de staking.\nElle peut être automatique, où la récompense est créditée sur votre adresse, ou manuelle, où vous devez retirer la récompense en créant une transaction pour la recevoir.</string>
<string name="staking_details_reward_schedule">Calendrier de récompenses</string>
<string name="staking_details_reward_schedule_info">Il s\'agit d\'un calendrier qui détermine le moment où les participants au staking reçoivent leurs récompenses.</string>
<string name="staking_details_reward_schedule_info">Il s\'agit d\'un calendrier qui détermine le moment où les participants au staking reçoivent leurs récompenses. La durée de distribution des récompenses peut varier légèrement en fonction du validateur et de la charge du réseau.</string>
<string name="staking_details_rewards_to_claim">Récompenses à réclamer: %s</string>
<string name="staking_details_title">Staking %s</string>
<string name="staking_details_unbonding_period">Période de dissociation</string>
<string name="staking_details_unbonding_period_info">La période que vous devez attendre après avoir demandé le retrait des fonds du staking avant que les jetons ne soient disponibles.</string>
<string name="staking_details_warmup_period">Période d\'échauffement</string>
<string name="staking_details_warmup_period_info">Le temps imparti pour activer la participation au staking.</string>
<string name="staking_give_permission_fee_footer">Le réseau facturera des frais dapprobation de jeton pour vérifier que vous autorisez lutilisation de votre jeton pour le jalonnement.</string>
<string name="staking_legal">En utilisant la fonctionnalité de staking, vous acceptez les %1$s et %2$s du fournisseur</string>
<string name="staking_locked">Bloqué</string>
<string name="staking_migrate">Migrer</string>
@ -713,6 +741,7 @@
<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_restake_text">L\'option de restaker vous permet de déplacer vos fonds d\'un validateur à un autre sans avoir besoin de les déstaker.</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>
@ -729,7 +758,10 @@
<string name="staking_reward_claiming_manual">Manuel</string>
<string name="staking_reward_schedule_block">Bloquer</string>
<string name="staking_reward_schedule_day">Jour</string>
<string name="staking_reward_schedule_each">Chaque %s</string>
<string name="staking_reward_schedule_each_day">Chaque jour</string>
<string name="staking_reward_schedule_each_days">Chaque %s</string>
<string name="staking_reward_schedule_each_plural">Chaque</string>
<string name="staking_reward_schedule_epoch">Époque</string>
<string name="staking_reward_schedule_era">Ère</string>
<string name="staking_reward_schedule_hour">Heure</string>
@ -738,8 +770,9 @@
<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_summary_description_text">Vous stakez %1$s et recevrez %2$s</string>
<string name="staking_tap_to_unlock">Appuyez pour déverrouiller</string>
<string name="staking_tap_to_unlock_or_vote">Appuyez pour déverrouiller ou voter</string>
<string name="staking_tap_to_withdraw">Appuyez pour retirer</string>
<string name="staking_title_stake">Stake %s</string>
<string name="staking_title_unstake">déstaker %s</string>
@ -747,6 +780,7 @@
<string name="staking_unbonding">Dissociation</string>
<string name="staking_unlocked_locked">Débloquer</string>
<string name="staking_unlocking">Déverrouillage</string>
<string name="staking_unstake_amount_validation_error">Le montant dépasse le solde misé</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>
@ -768,6 +802,7 @@
<string name="story_meet_title">Découvrez Tangem</string>
<string name="story_web3_description">Échangez, achetez des NFT, faites des prêts et des dépôts dans plus de 100 services décentralisés différents</string>
<string name="story_web3_title">Compatible avec Web 3.0</string>
<string name="swap_give_permission_fee_footer">Le réseau facturera des frais d\'approbation de jeton pour vérifier que vous autorisez l\'utilisation de votre jeton pour l\'échange.</string>
<string name="swap_promo_text">Échangez plus de jetons à de meilleurs taux directement dans votre portefeuille.</string>
<string name="swap_promo_title">Nouveau fournisseur d\'échange disponible !</string>
<string name="swapping_alert_cex_description">Le montant comprend :\n• les frais du fournisseur de services\n• les frais de réseau pour l\'envoi de %s depuis l\'échange vers l\'adresse de l\'utilisateur.</string>
@ -818,6 +853,7 @@
<string name="transaction_history_operation">Opération</string>
<string name="transaction_history_transaction_from_address">de : %s</string>
<string name="transaction_history_transaction_to_address">à : %s</string>
<string name="transaction_history_transaction_validator">validateur : %s</string>
<string name="try_to_load_data_again_button_title">Réessayez</string>
<string name="twin_error_same_card">Vous avez scanné la même carte. Pour créer un portefeuille jumeau, vous devez scanner la carte portant le numéro %d</string>
<string name="twin_error_wrong_twin">Vous avez scanné une mauvaise carte jumelle. S\'il vous plaît, essayez-en un autre</string>
@ -853,6 +889,7 @@
<string name="wallet_connect_create_tx_message">Demande de création d\'une transaction pour %1$s\n%2$s\n\nMontant : %3$s\nFrais : %4$s\nTotal : %5$s\nSolde : %6$s</string>
<string name="wallet_connect_create_tx_not_enough_funds">Impossible d\'effectuer la transaction. Fonds insuffisants.</string>
<string name="wallet_connect_error_failed_to_connect">Échec de l\'établissement de la session WalletConnect. Veuillez réessayer plus tard.</string>
<string name="wallet_connect_error_missing_blockchains">Tous les jetons n\'ont pas été ajoutés à votre liste. Veuillez d\'abord les ajouter et essayez à nouveau. Jetons manquants :\n</string>
<string name="wallet_connect_error_sing_failed">Échec de la signature du message. Veuillez réessayer</string>
<string name="wallet_connect_error_timeout">Échec de l\'établissement de la session WalletConnect : erreur de délai d\'attente. Veuillez réessayer plus tard.</string>
<string name="wallet_connect_error_unsupported_blockchains">La demande de session contient des blockchains non prises en charge pour la connexion WalletConnect. Blockchains non prises en charge :\n</string>

View file

@ -58,7 +58,7 @@
<string name="card_settings_interrupted_reset_alert_title">すべてのTangemデバイスのリセットが完了していません</string>
<string name="card_settings_reset_card_to_factory">工場出荷時の設定にリセット</string>
<string name="card_settings_security_mode">セキュリティ・モード</string>
<string name="card_settings_title">カード設定</string>
<string name="card_settings_title">デバイス設定</string>
<string name="cardano_coin_will_be_send_with_token_description">ネットワーク手数料に加えて、Cardanoネットワークは%2$sトークンで取引する際に%1$s ADAを請求します。</string>
<string name="cardano_coin_will_be_send_with_token_title">Cardanoの取引要件</string>
<string name="cardano_insufficient_balance_to_send_token_description">%1$s 取引を行うには、いくらかのADAを入金し、ネットワーク手数料と最小ADA (5ADAを推奨) をカバーする必要があります。</string>
@ -82,10 +82,12 @@
<string name="common_buy_currency">%1$sへ移動</string>
<string name="common_camera_denied_alert_message">カメラへのアクセスを許可していません。プライバシー設定を調整してください。</string>
<string name="common_cancel">キャンセル</string>
<string name="common_change">変更</string>
<string name="common_choose_action">アクションを選択</string>
<string name="common_claim">請求</string>
<string name="common_claim_rewards">報酬を受け取る</string>
<string name="common_close">閉じる</string>
<string name="common_confirm">確認</string>
<string name="common_continue">続ける</string>
<string name="common_copy">コピー</string>
<string name="common_copy_address">アドレスをコピー</string>
@ -216,7 +218,7 @@
<string name="details_referral_title">紹介プログラム</string>
<string name="details_row_description_flip_to_hide">デバイスの画面を下に向けると、残高をすばやく非表示にしたり表示したりできます。</string>
<string name="details_row_subtitle_signed_hashes_format">%sハッシュ</string>
<string name="details_row_title_cid">カードID</string>
<string name="details_row_title_cid">デバイスID</string>
<string name="details_row_title_contact_to_support">サポートへのお問い合わせ</string>
<string name="details_row_title_create_backup">他のカードをリンクする</string>
<string name="details_row_title_currency">アプリ通貨</string>
@ -254,6 +256,7 @@
<string name="express_exchange_status_exchanging">交換中</string>
<string name="express_exchange_status_exchanging_active">交換中...</string>
<string name="express_exchange_status_failed">失敗しました</string>
<string name="express_exchange_status_paused">停止中</string>
<string name="express_exchange_status_received">入金済み</string>
<string name="express_exchange_status_receiving">入金待ち</string>
<string name="express_exchange_status_receiving_active">入金待ち...</string>
@ -294,17 +297,16 @@
<string name="feedback_subject_tx_failed">取引を送信できません</string>
<string name="feedback_token_description_error">コインの説明エラー</string>
<string name="give_permission_current_transaction">取引</string>
<string name="give_permission_fee_footer">ネットワークは、あなたがトークンのスワップを承認していることを確認するために、トークン承認手数料を請求します。</string>
<string name="give_permission_policy_type_footer">選択したトークンの承認制限を指定します</string>
<string name="give_permission_rows_amount">金額%s</string>
<string name="give_permission_staking_footer">承認機能は、別のアドレスに特定の量のトークンを使用する許可を与えるために必要です。設計上スマートコントラクトは、承認しない限りトークンにアクセスできません。トークンを「ロック解除」すると、StakeKitスマート コントラクトがトークンを使用する権限が与えられます。ネットワークのマイナーは、このアクションをブロックチェーンに記録するためにガス料金(あなたが支払う)を受け取ります。承認後、トークンをステーキングできます。</string>
<string name="give_permission_staking_subtitle">続行するには、StakeKitスマートコントラクトが%sを使用することを許可する必要があります</string>
<string name="give_permission_staking_subtitle">続行するには、Polygonスマートコントラクトが%sを使用することを許可する必要があります</string>
<string name="give_permission_swap_subtitle" formatted="false">続行するには、%1sスマートコントラクトに%2sを使用する権限を付与してください</string>
<string name="give_permission_title">許可を与える</string>
<string name="give_permission_unlimited">無制限</string>
<string name="home_button_order">Tangemを注文</string>
<string name="home_button_scan">Tangemをスキャン</string>
<string name="information_generated_with_ai">この情報はAIによって生成されました</string>
<string name="information_generated_with_ai">この情報はAIで生成されました。 \nエラーが見つかった場合は、ここをタップしてください。</string>
<string name="initial_message_change_access_code_body">アクセスコードを変更するには、上図のようにカードまたはリングをタップし、操作が終了するまで取り外さないでください。</string>
<string name="initial_message_change_passcode_body">パスコードを変更するには、上記のようにカードをタップし、操作が終了するまで取り外さないでください。</string>
<string name="initial_message_create_wallet_body">ウォレットを作成するには、上記のようにカードをタップし、操作が終了するまで取り外さないでください。</string>
@ -452,7 +454,7 @@
<string name="onboarding_access_code_feature_1_title">保護する</string>
<string name="onboarding_access_code_feature_2_description">後で各カードおよびリングに個別のアクセスコードを設定できます。</string>
<string name="onboarding_access_code_feature_2_title">パーソナライズする</string>
<string name="onboarding_access_code_feature_3_description">アクセスコードはリンクされたカードおよびリング1つで復元できます。すべてのデバイスを1か所に保管しないでください。</string>
<string name="onboarding_access_code_feature_3_description">アクセスコードはリンクされたカードおよびリング1つで復元できます。すべてのデバイスを1か所に保管しないでください。</string>
<string name="onboarding_access_code_feature_3_title">復元する</string>
<string name="onboarding_access_code_hint">アクセスコードとして任意の単語、フレーズ、または数字を選択してください</string>
<string name="onboarding_access_code_intro_title">アクセスコードの作成</string>
@ -482,7 +484,7 @@
<string name="onboarding_create_wallet_button_create_wallet">ウォレットを作成する</string>
<string name="onboarding_create_wallet_header">ウォレットを作成する</string>
<string name="onboarding_create_wallet_options_button_options">その他のオプション</string>
<string name="onboarding_create_wallet_options_message">秘密鍵はカードまたはリング内で安全に生成されます。シードフレーズは存在しないので、誰もエクスポートしたり盗んだりすることはできません。</string>
<string name="onboarding_create_wallet_options_message">秘密鍵はチップ内で安全に生成されます。シードフレーズは存在しないので、誰もエクスポートしたり盗んだりすることはできません。</string>
<string name="onboarding_create_wallet_options_title">秘密鍵を非公開で生成する</string>
<string name="onboarding_done_body">カードは有効化され、使用可能になりました</string>
<string name="onboarding_done_header">成功!</string>
@ -521,7 +523,7 @@
<string name="onboarding_title_backup_card">バックアップカード</string>
<string name="onboarding_title_backup_card_format">バックアップカード # %d</string>
<string name="onboarding_title_backup_ring">バックアップリング</string>
<string name="onboarding_title_no_backup_cards">バックアップカードまたはリングなし</string>
<string name="onboarding_title_no_backup_cards">バックアップデバイスなし</string>
<string name="onboarding_title_notifications">通知</string>
<string name="onboarding_title_one_backup_card">バックアップデバイスが1つ追加されました</string>
<string name="onboarding_title_scan_origin_card">カードを準備してください</string>
@ -541,6 +543,9 @@
<string name="onboarding_wallet_info_title_fourth">アクセスコードの復元</string>
<string name="onboarding_wallet_info_title_second">同一のカード</string>
<string name="onboarding_wallet_info_title_third">アクセスコード</string>
<string name="onramp_residency_bottomsheet_country_not_supported">この国では当社のサービスはご利用いただけません</string>
<string name="onramp_residency_bottomsheet_country_subtitle">変更または確認</string>
<string name="onramp_residency_bottomsheet_title">あなたの住居は次のように識別されています</string>
<string name="organize_tokens_group">グループ</string>
<string name="organize_tokens_sort_by_balance">残高順</string>
<string name="organize_tokens_title">トークンを整理する</string>
@ -695,7 +700,7 @@
<string name="staking_details_market_rating">市場評価</string>
<string name="staking_details_metrics_block_header">指標</string>
<string name="staking_details_minimum_requirement">最低要件</string>
<string name="staking_details_no_rewards_to_claim">報酬なし</string>
<string name="staking_details_no_rewards_to_claim">報酬はありません</string>
<string name="staking_details_reward_claiming">請求中の報酬</string>
<string name="staking_details_reward_claiming_info">ステーキング報酬の受け取り方法。\n自動であなたのアドレスに報酬が入金される方法と、手動で取引を生成して報酬を引き出す方法があります。</string>
<string name="staking_details_reward_schedule">報酬スケジュール</string>
@ -706,6 +711,7 @@
<string name="staking_details_unbonding_period_info">ステーキングから資金の引き出しを要求した後、トークンが利用可能になるまでの待機期間。</string>
<string name="staking_details_warmup_period">ウォームアップ期間</string>
<string name="staking_details_warmup_period_info">ステーキングへの参加を有効にするために割り当てられた時間。</string>
<string name="staking_give_permission_fee_footer">ネットワークは、ステーキングのためにトークンの使用を承認していることを確認するために、トークン承認手数料を請求します。</string>
<string name="staking_legal">ステーキング機能を使用すると、プロバイダーの%1$sと%2$sに同意したことになります</string>
<string name="staking_locked">ロック中</string>
<string name="staking_migrate">移行</string>
@ -725,6 +731,7 @@
<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_restake_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>
@ -743,6 +750,8 @@
<string name="staking_reward_schedule_day">毎日</string>
<string name="staking_reward_schedule_each">%sごと</string>
<string name="staking_reward_schedule_each_day">毎日</string>
<string name="staking_reward_schedule_each_days">%s日ごと</string>
<string name="staking_reward_schedule_each_plural"></string>
<string name="staking_reward_schedule_epoch">エポック毎</string>
<string name="staking_reward_schedule_era">時代毎</string>
<string name="staking_reward_schedule_hour">毎時間</string>
@ -751,7 +760,7 @@
<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_summary_description_text">%1$sをステーキングし、報酬%2$sを受け取ります</string>
<string name="staking_tap_to_unlock">タップしてロック解除</string>
<string name="staking_tap_to_unlock_or_vote">タップしてロック解除もしくは投票</string>
<string name="staking_tap_to_withdraw">タップして引き出す</string>
@ -761,6 +770,7 @@
<string name="staking_unbonding">ステーキング解約中</string>
<string name="staking_unlocked_locked">ロック解除</string>
<string name="staking_unlocking">ロック解除中</string>
<string name="staking_unstake_amount_validation_error">金額がステーキング残高を超えています</string>
<string name="staking_unstaked">ステーキングされていない</string>
<string name="staking_unstaking">ステーキング解除</string>
<string name="staking_unstaking_item_name">ステーキング解除中の資産%s</string>
@ -782,6 +792,7 @@
<string name="story_meet_title">Tangemのご紹介</string>
<string name="story_web3_description">100種類以上の分散型サービスで、NFTの交換・購入や、借入・預金を行うことができます。</string>
<string name="story_web3_title">Web3.0対応</string>
<string name="swap_give_permission_fee_footer">ネットワークは、あなたがトークンのスワップを承認していることを確認するために、トークン承認手数料を請求します。</string>
<string name="swap_promo_text">より多くのトークンをより良いレートで、ウォレット内にて直接交換します。</string>
<string name="swap_promo_title">新しいスワッププロバイダーが利用可能になりました!</string>
<string name="swapping_alert_cex_description">この金額には以下が含まれます:\n- サービスプロバイダーの手数料\n- 取引所からユーザーのアドレスに%s を送り返すためのネットワーク手数料。</string>
@ -868,6 +879,7 @@
<string name="wallet_connect_create_tx_message">%1$sの取引を作成するリクエスト\n%2$s\n\n金額: %3$s\n手数料: %4$s\n合計: %5$s\n残高: %6$s</string>
<string name="wallet_connect_create_tx_not_enough_funds">取引を送信できません。資金が足りません。</string>
<string name="wallet_connect_error_failed_to_connect">WalletConnect セッションを確立できませんでした。しばらくしてからもう一度お試しください。</string>
<string name="wallet_connect_error_missing_blockchains">すべてのトークンがリストには追加されませんでした。まず追加してから、もう一度お試しください。不足しているトークン: \n</string>
<string name="wallet_connect_error_sing_failed">メッセージの署名に失敗しました。\nもう一度お試しください。</string>
<string name="wallet_connect_error_timeout">WalletConnectセッションの確立に失敗しましたタイムアウトエラー。しばらくしてもう一度お試しください。</string>
<string name="wallet_connect_error_unsupported_blockchains">セッションリクエストには、WalletConnect接続でサポートされていないブロックチェーンが含まれています。サポートされていないブロックチェーン: \n</string>
@ -944,7 +956,7 @@
<string name="warning_low_signatures_message">このカードには%sの署名のみが残っています。資金をすべて引き出す必要があります。</string>
<string name="warning_low_signatures_title">署名数が少ないです</string>
<string name="warning_manage_tokens_legacy_derivation_message">異なるネットワーク上のトークンは、異なるアドレスを持つ場合があります。資金を送金する際には、アドレスがネットワークと一致していることを再確認してください。</string>
<string name="warning_matic_migration_message">MATICはPOLに移行中です。ただし、期限は設定されておらず、MATICはまだ廃止されていません。MATICトークンを引き続き安全に使用することも、取引所でPOLに交換することもできます。</string>
<string name="warning_matic_migration_message">MATICはPOLに移行中です。ただし、期限は設定されておらず、MATICはまだ廃止されていません。MATICトークンを引き続き安全に使用することも、POLに交換することもできます。</string>
<string name="warning_matic_migration_title">MATICからPOLへの移行</string>
<plurals name="warning_missing_derivation_message">
<item quantity="other">%d ネットワークのアドレスを取得するために、カードまたはリングを利用してください</item>

View file

@ -85,10 +85,12 @@
<string name="common_buy_currency">Перейти на %1$s</string>
<string name="common_camera_denied_alert_message">Вы не предоставили доступ к камере, пожалуйста, измените настройки конфиденциальности.</string>
<string name="common_cancel">Отмена</string>
<string name="common_change">Изменить</string>
<string name="common_choose_action">Выберите действие</string>
<string name="common_claim">Получить</string>
<string name="common_claim_rewards">Вывести награду</string>
<string name="common_close">Закрыть</string>
<string name="common_confirm">Подтвердить</string>
<string name="common_continue">Продолжить</string>
<string name="common_copy">Копировать</string>
<string name="common_copy_address">Скопировать адрес</string>
@ -125,6 +127,7 @@
<string name="common_generate_addresses">Получить ваши адреса</string>
<string name="common_go_to_provider">К провайдеру</string>
<string name="common_go_to_token">Перейти в токен</string>
<string name="common_hour">час</string>
<string name="common_import">Импортировать</string>
<string name="common_in_progress">В процессе</string>
<string name="common_later">Позже</string>
@ -181,6 +184,7 @@
<string name="common_unknown_error">Произошла ошибка. Пожалуйста, попробуйте снова.</string>
<string name="common_unreachable">Недоступно</string>
<string name="common_unstake">Завершить стейкинг</string>
<string name="common_week">неделю</string>
<string name="common_yes">Да</string>
<string name="contract_address_copied_message">Адрес контракта скопирован!</string>
<string name="currency_subtitle_expanded">Доступные сети</string>
@ -261,6 +265,7 @@
<string name="express_exchange_status_exchanging">Обмен</string>
<string name="express_exchange_status_exchanging_active">Обмен...</string>
<string name="express_exchange_status_failed">Неудачно</string>
<string name="express_exchange_status_paused">Приостановлен</string>
<string name="express_exchange_status_received">Депозит получен</string>
<string name="express_exchange_status_receiving">Ожидание депозита</string>
<string name="express_exchange_status_receiving_active">Ожидаем пополнения...</string>
@ -301,11 +306,10 @@
<string name="feedback_subject_tx_failed">Не могу отправить транзакцию</string>
<string name="feedback_token_description_error">Ошибка в описании монеты</string>
<string name="give_permission_current_transaction">Транзакция</string>
<string name="give_permission_fee_footer">Комиссия сети за одобрение токена будет взиматься за подтверждение того, что именно вы разрешаете использовать ваш токен для обмена.</string>
<string name="give_permission_policy_type_footer">Укажите лимит доступа к выбранному токену</string>
<string name="give_permission_rows_amount">Количество %s</string>
<string name="give_permission_staking_footer">Функция подтверждения необходима для предоставления другому адресу разрешения на использование определенного количества ваших токенов.По замыслу смарт-контракты не могут получить доступ к вашим токенам, если вы не одобрите доступ со своей стороны. «Разблокируя» свои токены, вы даете смарт-контракту StakeKit разрешение использовать ваши активы. Майнеры сети получают компенсацию за газ (оплачиваемый вами) за запись этого действия в блокчейне. Как только разрешение будет предоставлено, вы сможете осуществить стейкинг токена.</string>
<string name="give_permission_staking_subtitle">Чтобы продолжить, вам необходимо разрешить смарт контракту StakeKit использовать ваш %s</string>
<string name="give_permission_staking_subtitle">Чтобы продолжить, вам необходимо разрешить смарт контракту Polygon использовать ваш %s</string>
<string name="give_permission_swap_subtitle" formatted="false">Чтобы продолжить, вам нужно разрешить смарт-контракту %1s использовать ваш %2s</string>
<string name="give_permission_title">Дать разрешение</string>
<string name="give_permission_unlimited">Безлимитно</string>
@ -515,7 +519,7 @@
</plurals>
<string name="onboarding_seed_generate_title">Ваша seed-фраза</string>
<plurals name="onboarding_seed_generate_words_count">
<item quantity="one">%d слово</item>
<item quantity="one"></item>
<item quantity="few">%d слова</item>
<item quantity="many">%d слов</item>
<item quantity="other">%d слов</item>
@ -726,13 +730,14 @@
<string name="staking_details_reward_claiming">Способ вознаграждения</string>
<string name="staking_details_reward_claiming_info">Способ получения вознаграждений за стейкинг. Оно может зачисляться автоматически на ваш адрес или вручную, когда вознаграждение нужно вывести, создав транзакцию на её получение.</string>
<string name="staking_details_reward_schedule">Период вознагражения</string>
<string name="staking_details_reward_schedule_info">Это период, определяющий, когда участники стейкинга получат свои вознаграждения.</string>
<string name="staking_details_reward_schedule_info">Это график, который определяет, когда участники стейкинга получают свои награды. Время распределения наград может немного варьироваться в зависимости от валидатора и нагрузки сети.</string>
<string name="staking_details_rewards_to_claim">Вознаграждение для получения: %s</string>
<string name="staking_details_title">Стейкинг %s</string>
<string name="staking_details_unbonding_period">Период отзыва</string>
<string name="staking_details_unbonding_period_info">Период, который необходимо подождать после запроса на вывод средств из стейкинга, прежде чем токены станут доступны.</string>
<string name="staking_details_warmup_period">Период прогрева</string>
<string name="staking_details_warmup_period_info">Время, необходимое для начала процесса стейкинга и активации процесса начисления наград</string>
<string name="staking_give_permission_fee_footer">Комиссия сети за одобрение токена будет взиматься за подтверждение того, что именно вы разрешаете использовать ваш токен для стейкинга.</string>
<string name="staking_legal">Пользуясь стейкинг сервисом, вы соглашаетесь с %1$s и %2$s</string>
<string name="staking_locked">Заблокировано</string>
<string name="staking_migrate">Переместить</string>
@ -752,6 +757,7 @@
<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_restake_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>
@ -767,7 +773,10 @@
<string name="staking_reward_claiming_manual">Вручную</string>
<string name="staking_reward_schedule_block">За блок</string>
<string name="staking_reward_schedule_day">Ежедневно</string>
<string name="staking_reward_schedule_each">Каждый %s</string>
<string name="staking_reward_schedule_each_day">Каждый день</string>
<string name="staking_reward_schedule_each_days">Каждые %s дня</string>
<string name="staking_reward_schedule_each_plural">Каждые</string>
<string name="staking_reward_schedule_epoch">За эпоху</string>
<string name="staking_reward_schedule_era">За эру</string>
<string name="staking_reward_schedule_hour">Ежечасно</string>
@ -776,7 +785,7 @@
<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_summary_description_text">Вы стейкаете %1$s и будете получать награду %2$s</string>
<string name="staking_tap_to_unlock">Нажмите для разблокировки</string>
<string name="staking_tap_to_unlock_or_vote">Нажмите для разблокировки</string>
<string name="staking_tap_to_withdraw">Нажмите для вывода</string>
@ -786,6 +795,7 @@
<string name="staking_unbonding">Отзыв</string>
<string name="staking_unlocked_locked">Разблокировать</string>
<string name="staking_unlocking">Разблокировка</string>
<string name="staking_unstake_amount_validation_error">Сумма превышает застейканный баланс</string>
<string name="staking_unstaked">Вывод из стейкинга</string>
<string name="staking_unstaking">Завершение стейкинга</string>
<string name="staking_unstaking_item_name">Завершение стейкинга %s</string>
@ -807,6 +817,7 @@
<string name="story_meet_title">Встречайте Tangem</string>
<string name="story_web3_description">Обменивайте, покупайте NFT, получайте займы и делайте вклады в более чем 100 различных децентрализованных сервисах</string>
<string name="story_web3_title">Поддержка Web 3.0</string>
<string name="swap_give_permission_fee_footer">Комиссия сети за одобрение токена будет взиматься за подтверждение того, что именно вы разрешаете использовать ваш токен для обмена.</string>
<string name="swap_promo_text">Обменивайте больше токенов по лучшим курсам прямо в вашем кошельке.</string>
<string name="swap_promo_title">Новый провайдер обмена!</string>
<string name="swapping_alert_cex_description">В сумму включено: \n• комиссия провайдера сервиса\n• комиссия сети за отправку %s от биржи обратно на адрес пользователя.</string>

View file

@ -12,19 +12,19 @@
<string name="alert_failed_to_send_transaction_title">Не вдається відправити транзакцію</string>
<string name="alert_manage_tokens_unsupported_blockchain_by_card_message">Обраний гаманець не підтримує мережу %1$s</string>
<string name="alert_manage_tokens_unsupported_curve_message">Щоб активувати криптографічне шифрування блокчейну %1$s, вам потрібно скинути налаштування гаманця до заводських. Зніміть свої кошти перед цим, щоб переконатися, що ви їх не втратите, а потім завершіть процес скидання. Вхід до поточного гаманця буде неможливий після скидання.</string>
<string name="alert_manage_tokens_unsupported_message">Токени в мережі %1$s не підтримуються цією карткою через обмеження прошивки.</string>
<string name="alert_troubleshooting_scan_card_title">У вас виникли труднощі зі скануванням картки?</string>
<string name="alert_manage_tokens_unsupported_message">Токени в мережі %1$s не підтримуються цією карткою або кільцем через обмеження прошивки.</string>
<string name="alert_troubleshooting_scan_card_title">У вас виникли труднощі зі скануванням картки або кільця?</string>
<string name="alert_unsupported_card">Ця картка не призначена для роботи з цим додатком</string>
<string name="app_settings_default_fee">Комісія за замовчуванням</string>
<string name="app_settings_default_fee_footer">Увімкніть комісію за замовчуванням, щоб автоматично встановлювати комісію за транзакцію і пропускати сторінку комісій під час відправлення коштів. Ви завжди можете повернутися до цієї сторінки за необхідності.</string>
<string name="app_settings_enable_biometrics_description">Перейдіть до налаштувань, щоб увімкнути біометричну автентифікацію в додатку Tangem</string>
<string name="app_settings_enable_biometrics_title">Увімкнути біометричну автентифікацію</string>
<string name="app_settings_off_saved_access_code_alert_message">Усі збережені коди доступу будуть видалені. Вам доведеться вводити код доступу при роботі з гаманцем.</string>
<string name="app_settings_off_saved_wallet_alert_message">При відключенні функції збереження гаманця всі збережені до цього гаманці будуть видалені зі застосунку.</string>
<string name="app_settings_off_saved_wallet_alert_message">При відключенні функції збереження гаманця всі до цього збережені гаманці будуть видалені зі застосунку.</string>
<string name="app_settings_saved_access_codes">Зберегти код доступу</string>
<string name="app_settings_saved_access_codes_footer">Підключіть функцію збереження кодів доступу від карток на телефоні у зашифрованому виді, і при роботі з карткою замість коду доступу буде запитуватися біометрична автентифікація.</string>
<string name="app_settings_saved_access_codes_footer">Підключіть функцію збереження кодів доступу від карток на телефоні у зашифрованому виді, і при роботі з карткою або кільцем замість коду доступу буде запитуватися біометрична автентифікація.</string>
<string name="app_settings_saved_wallet">Зберігати гаманець у додатку</string>
<string name="app_settings_saved_wallet_footer">Увімкніть функцію привʼязки карток у застосунку, а також можливість біометричної автентифікації. Підпис транзакції й надалі буде потребувати картку.</string>
<string name="app_settings_saved_wallet_footer">Увімкніть функцію привʼязки карток у застосунку, а також можливість біометричної автентифікації. Підпис транзакції й надалі буде потребувати картку або кільце.</string>
<string name="app_settings_theme_mode_dark">Темна</string>
<string name="app_settings_theme_mode_light">Світла</string>
<string name="app_settings_theme_mode_system">Системна</string>
@ -34,34 +34,34 @@
<string name="balance_hidden_do_not_show_button">Більше не показувати</string>
<string name="balance_hidden_got_it_button">Зрозуміло</string>
<string name="balance_hidden_title">Баланси приховані</string>
<string name="biometric_lockout_permanent_warning_description">Будь ласка, відскануйте картку</string>
<string name="biometric_lockout_warning_description">Будь ласка, повторіть спробу через 30 секунд або відскануйте картку</string>
<string name="biometric_lockout_permanent_warning_description">Будь ласка, відскануйте картку або кільце</string>
<string name="biometric_lockout_warning_description">Будь ласка, спробуйте знову через 30 секунд або відскануйте картку або кільце</string>
<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>
<plurals name="card_label_card_count">
<item quantity="one">%d картка</item>
<item quantity="few">%d картки</item>
<item quantity="many">%d карток</item>
<item quantity="other">%d карток</item>
<item quantity="one">%d пристрій</item>
<item quantity="few">%d пристрої</item>
<item quantity="many">%d пристроїв</item>
<item quantity="other">%d пристроїв</item>
</plurals>
<string name="card_settings_access_code_recovery_disabled_description">Вимкніть цю опцію, якщо ви не хочете, щоб ця картка використовувалася для скидання кодів доступу до інших карток у цьому гаманці. Зверніть увагу, що це також унеможливить скидання коду доступу на цій картці.</string>
<string name="card_settings_access_code_recovery_disabled_description">Вимкніть цю опцію, якщо не хочете, щоб ця картка використовувалася для скидання кодів доступу на інших картках у цьому гаманці. Зверніть увагу, скидання коду доступу також не буде доступним на цій картці.</string>
<string name="card_settings_access_code_recovery_enabled_description">Дозволяє використовувати цю картку для скидання коду доступу на інших картках у цьому гаманці</string>
<string name="card_settings_access_code_recovery_title">Відновлення коду доступу</string>
<string name="card_settings_action_sheet_reset">Скинути</string>
<string name="card_settings_action_sheet_title">Ви впевнені, що хочете це зробити?</string>
<string name="card_settings_change_access_code">Зміна коду доступу</string>
<string name="card_settings_change_access_code_footer">Код доступу буде змінено лише на цій картці</string>
<string name="card_settings_completed_reset_alert_message">Усі картки у вибраному гаманці було скинуто до заводських налаштувань. Тепер ви можете створити новий гаманець.</string>
<string name="card_settings_change_access_code_footer">Код доступу буде змінений лише на цій картці або кільцю</string>
<string name="card_settings_completed_reset_alert_message">Усі пристрої Tangem у вибраному гаманці було скинуто до заводських налаштувань. Тепер ви можете створити новий гаманець.</string>
<string name="card_settings_completed_reset_alert_title">Скидання завершено</string>
<string name="card_settings_continue_reset_alert_message">Ви хочете скинути наступну картку в цьому гаманці?</string>
<string name="card_settings_continue_reset_alert_title">Скидання картки</string>
<string name="card_settings_interrupted_reset_alert_message">Рекомендуємо завершити процес скидання для всіх карток у цьому гаманці</string>
<string name="card_settings_interrupted_reset_alert_title">Ви скинули не всі картки</string>
<string name="card_settings_continue_reset_alert_message">Бажаєте скинути наступний пристрій від цього гаманця?</string>
<string name="card_settings_continue_reset_alert_title">Скидання гаманця</string>
<string name="card_settings_interrupted_reset_alert_message">Рекомендуємо завершити процес скидання для всіх пристроїв Tangem гаманця</string>
<string name="card_settings_interrupted_reset_alert_title">Ви скинули не всі Tangem пристрої</string>
<string name="card_settings_reset_card_to_factory">Скинути до заводських налаштувань</string>
<string name="card_settings_security_mode">Тип безпеки</string>
<string name="card_settings_title">Налаштування картки</string>
<string name="card_settings_title">Налаштування пристрою</string>
<string name="cardano_coin_will_be_send_with_token_description">Крім мережевих комісій, мережа Cardano стягує %1$s ADA при транзакції з токеном %2$s</string>
<string name="cardano_coin_will_be_send_with_token_title">Вимоги до транзакції Cardano</string>
<string name="cardano_insufficient_balance_to_send_token_description">Щоб здійснити транзакцію %1$s, внесіть певну суму ADA для покриття мережевої комісії та мінімальне значення ADA (рекомендовано 5 ADA)</string>
@ -85,10 +85,12 @@
<string name="common_buy_currency">Перейдіть до %1$s</string>
<string name="common_camera_denied_alert_message">Ви не надали доступ до камери, будь ласка, змініть налаштування конфіденційності</string>
<string name="common_cancel">Скасувати</string>
<string name="common_change">Змінити</string>
<string name="common_choose_action">Виберіть дію</string>
<string name="common_claim">Отримати</string>
<string name="common_claim_rewards">Отримати винагороди</string>
<string name="common_close">Закрити</string>
<string name="common_confirm">Підтвердити</string>
<string name="common_continue">Продовжити</string>
<string name="common_copy">Копіювати</string>
<string name="common_copy_address">Скопіювати адресу</string>
@ -122,7 +124,7 @@
<string name="common_fee_selector_option_market">За ринком</string>
<string name="common_fee_selector_option_slow">Повільно</string>
<string name="common_fee_selector_title">Швидкість та комісія</string>
<string name="common_generate_addresses">Отримати адреси</string>
<string name="common_generate_addresses">Отримати ваші адреси</string>
<string name="common_go_to_provider">Перейти до провайдера</string>
<string name="common_go_to_token">Перейти до токену</string>
<string name="common_hour">година</string>
@ -141,6 +143,7 @@
<string name="common_now">Зараз</string>
<string name="common_ok">ОК</string>
<string name="common_origin_card">Основна картка</string>
<string name="common_origin_ring">Основне кільце</string>
<string name="common_passphrase">Парольна фраза</string>
<string name="common_paste">Вставити</string>
<string name="common_privacy_policy">Політикою конфіденційності</string>
@ -218,13 +221,13 @@
<string name="details_manage_security_access_code">Код доступу</string>
<string name="details_manage_security_access_code_description">Перед скануванням картки вам потрібно буде ввести правильний код доступу</string>
<string name="details_manage_security_long_tap">Затримка сканування</string>
<string name="details_manage_security_long_tap_description">Цей механізм захищає картку від безконтактних атак. Між скануванням картки та виконанням команди буде додана затримка.</string>
<string name="details_manage_security_long_tap_description">Цей механізм захищає картку або кільце від безконтактних атак. Між скануванням картки та виконанням команди буде додана затримка.</string>
<string name="details_manage_security_passcode">Пароль</string>
<string name="details_manage_security_passcode_description">Перед виконанням будь-якої команди, що тягне за собою зміну стану картки, вам необхідно буде ввести пароль.</string>
<string name="details_referral_title">Реферальна програма</string>
<string name="details_row_description_flip_to_hide">Переверніть екран пристрою вниз, щоб швидко приховати та відобразити баланси</string>
<string name="details_row_subtitle_signed_hashes_format">%s хешів</string>
<string name="details_row_title_cid">Номер картки</string>
<string name="details_row_title_cid">Номер пристрою</string>
<string name="details_row_title_contact_to_support">Звернутися у підтримку</string>
<string name="details_row_title_create_backup">Додати більше карток</string>
<string name="details_row_title_currency">Валюта застосунку</string>
@ -235,7 +238,7 @@
<string name="details_title">Деталі</string>
<string name="disclaimer_error_loading">Перевірте підключення до інтернету або змініть мережу</string>
<string name="disclaimer_title">Умови використання</string>
<string name="error_wrong_wallet_tapped">Ви використали картку від іншого гаманця. Прикладіть картку, пов\'язану з цим гаманцем.</string>
<string name="error_wrong_wallet_tapped">Ви використали картку або кільце від іншого гаманця. Прикладіть картку або кільце, пов\'язану з цим гаманцем.</string>
<string name="exchange_tokens_available_tokens_header">Мої токени</string>
<string name="exchange_tokens_empty_tokens">У вас немає доданих токенів. Додайте токени для обміну</string>
<string name="exchange_tokens_unavailable_tokens_header">Недоступний для обміну з %s</string>
@ -262,6 +265,7 @@
<string name="express_exchange_status_exchanging">Обмін</string>
<string name="express_exchange_status_exchanging_active">Обмін...</string>
<string name="express_exchange_status_failed">Не вдалося</string>
<string name="express_exchange_status_paused">Призупинено</string>
<string name="express_exchange_status_received">Депозит отримано</string>
<string name="express_exchange_status_receiving">Очікуємо на депозит</string>
<string name="express_exchange_status_receiving_active">Очікуємо на депозит...</string>
@ -289,38 +293,38 @@
<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>
<string name="feedback_preface_scan_failed">Розкажіть, будь ласка, яку картку або кільце ви маєте?</string>
<string name="feedback_preface_support">Привіт, команда підтримки,</string>
<string name="feedback_preface_tx_failed">Будь ласка, розкажіть нам більше про вашу проблему. Кожна дрібниця може допомогти.</string>
<string name="feedback_subject_rate_negative">Мої пропозиції</string>
<string name="feedback_subject_scan_failed">Не вдається відсканувати картку</string>
<string name="feedback_subject_scan_failed">Не вдається відсканувати картку/кільце</string>
<string name="feedback_subject_support">Звернення в підтримку</string>
<string name="feedback_subject_support_tangem">Звернення в підтримку Tangem</string>
<string name="feedback_subject_tx_failed">Не вдається відправити транзакцію</string>
<string name="feedback_token_description_error">Помилка в описі монети</string>
<string name="give_permission_current_transaction">Транзакція</string>
<string name="give_permission_fee_footer">Мережа стягує комісію за схвалення токену за підтвердження, що саме ви дозволяєте використовувати ваш токен для обміну.</string>
<string name="give_permission_policy_type_footer">Вкажіть ліміт доступу для обраного токена</string>
<string name="give_permission_rows_amount">Кількість %s</string>
<string name="give_permission_staking_footer">Функція підтвердження необхідна для надання дозволу іншій адресі на використання певної кількості ваших токенів. За задумом, смарт-контракти не можуть отримати доступ до ваших токенів без вашого схвалення. \"Розблоковуючи\" свої токени, ви дозволяєте смарт-контракту StakeKit використовувати їх. Майнери мережі отримують плату за газ (сплачену вами), щоб зафіксувати цю дію в блокчейні. Ви зможете застейкати свій токен після того, як дасте дозвіл.</string>
<string name="give_permission_staking_subtitle">Щоб продовжити, вам потрібно дозволити смарт-контракту StakeKit використовувати ваш %s</string>
<string name="give_permission_swap_subtitle" formatted="false">Щоб продовжити, вам потрібно надати дозвіл смарт-контракту %1s використовувати ваш %2s</string>
<string name="give_permission_staking_subtitle">Щоб продовжити, вам потрібно дозволити смарт-контракту Polygon використовувати ваш %s</string>
<string name="give_permission_swap_subtitle" formatted="false">Щоб продовжити, вам потрібно дозволити смарт-контракту %1s використовувати ваш %2s</string>
<string name="give_permission_title">Надати дозвіл</string>
<string name="give_permission_unlimited">Необмежено</string>
<string name="home_button_order">Купити</string>
<string name="home_button_scan">Сканувати</string>
<string name="information_generated_with_ai">Ця інформація була створена за допомогою ШІ</string>
<string name="initial_message_change_access_code_body">Щоб змінити код доступу, прикладіть картку, як показано вище, і не прибирайте її до закінчення операції</string>
<string name="information_generated_with_ai">Ця інформація була створена за допомогою ШІ.\nНатисніть тут, якщо знайшли помилку.</string>
<string name="initial_message_change_access_code_body">Щоб змінити код доступу, прикладіть картку або кільце, як показано вище, і не прибирайте її до закінчення операції</string>
<string name="initial_message_change_passcode_body">Щоб змінити пароль, прикладіть картку, як показано вище, і не прибирайте її до закінчення операції</string>
<string name="initial_message_create_wallet_body">Щоб створити гаманець, прикладіть картку, як показано вище, і не прибирайте її до завершення операції</string>
<string name="initial_message_create_wallet_body_ring">Щоб створити гаманець, торкніться кільця, як показано вище, і не прибирайте до кінця операції</string>
<string name="initial_message_reset_backup_card_header">Прикладіть картку #%s для скидання</string>
<string name="initial_message_scan_header">Прикладіть, щоб відсканувати</string>
<string name="initial_message_sign_header">Прикладіть, щоб підписати</string>
<string name="initial_message_tap_header">Прикладіть картку</string>
<string name="key_invalidated_warning_description">Ви оновили біометричні дані, відскануйте свою картку для входу</string>
<string name="initial_message_tap_header">Прикладіть картку або кільце</string>
<string name="key_invalidated_warning_description">Ви оновили дані біометрії, відскануйте свою картку або кільце для входу</string>
<string name="koinos_insufficient_balance_to_send_koin_description">Ваш баланс повинен перевищувати суму комісії для здійснення переказу</string>
<string name="koinos_insufficient_balance_to_send_koin_title">Недостатньо балансу</string>
<string name="koinos_insufficient_mana_to_send_koin_description">У вас недостатньо Mana для цієї транзакції. Будь ласка, зачекайте, поки Mana буде поповнена. Ваш баланс Mana становить %1$s/%2$s</string>
@ -332,7 +336,7 @@
<string name="main_empty_tokens_list_message">Щоб почати відстежувати свої криптоактиви та транзакції, додайте токени</string>
<string name="main_manage_tokens">Керування токенами</string>
<string name="main_scan_card_warning_view_subtitle">Для доступу до всіх мереж необхідно відсканувати картку</string>
<string name="main_scan_card_warning_view_title">Відскануйте картку</string>
<string name="main_scan_card_warning_view_title">Відскануйте картку або кільце</string>
<string name="main_swap_changelly_promotion_message">Насолоджуйтесь %1$s комісією за обслуговування на свопах через Changelly з %2$s по %3$s лютого.</string>
<string name="main_swap_changelly_promotion_title">Обмін із Changelly, %s комісії</string>
<string name="main_tokens">Токени</string>
@ -341,7 +345,7 @@
<string name="manage_tokens_list_header_title">Ринкова капіталізація</string>
<string name="manage_tokens_network_selector_native_subtitle">Спочатку був створений блокчейн криптовалюти</string>
<string name="manage_tokens_network_selector_native_title">Основна мережа</string>
<string name="manage_tokens_network_selector_non_native_info">Використання неосновних мереж для токенів дозволяє забезпечити крос-блокчейн інтероперабельність, що дає змогу використовувати активи в різноманітних децентралізованих додатках та смарт-контрактах на різних платформах. Однак це часто вимагає наявності кастодіана або смарт-контракту для безпечного зберігання оригінального активу, що вводить централізацію та ризик контрагента.</string>
<string name="manage_tokens_network_selector_non_native_info">Використання нерідних мереж для токенів забезпечує сумісність між блокчейнами, дозволяючи використовувати активи в різноманітних децентралізованих програмах і смарт-контрактах на різних платформах. Однак для цього часто використовується зберігач або смарт-контракт для надійного зберігання оригінального активу, вводячи централізацію та ризик контрагента.</string>
<string name="manage_tokens_network_selector_non_native_subtitle">Не оригінальний або первинний блокчейн, на якому розміщено токен</string>
<string name="manage_tokens_network_selector_non_native_title">Неосновні мережі</string>
<string name="manage_tokens_network_selector_title">Оберіть мережі</string>
@ -368,7 +372,7 @@
<string name="markets_available_networks">Доступні мережі</string>
<string name="markets_common_my_portfolio">Моє портфоліо</string>
<string name="markets_common_title">Маркет</string>
<string name="markets_generate_addresses_notification">Щоб згенерувати адреси для обраних мереж, потрібно відсканувати свою картку Tangem</string>
<string name="markets_generate_addresses_notification">Щоб згенерувати адреси для обраних мереж, відскануйте вашу картку або кільце Tangem гаманця</string>
<string name="markets_hint">Щоб додати токени, потягніть вгору або торкніться панелі пошуку</string>
<string name="markets_insights_info_description_message">Дані цього розділу отримані з наступних мереж: %s</string>
<string name="markets_loading_error_title">Не вдалося завантажити дані...</string>
@ -396,10 +400,10 @@
<string name="markets_sort_by_trending_title">В тренді</string>
<string name="markets_token_details_about_token_title">Про %s</string>
<plurals name="markets_token_details_amount_exchanges">
<item quantity="one">біржа</item>
<item quantity="few">біржі</item>
<item quantity="many">бірж</item>
<item quantity="other">бірж</item>
<item quantity="one">%d біржа</item>
<item quantity="few">%d біржі</item>
<item quantity="many">%d бірж</item>
<item quantity="other">%d бірж</item>
</plurals>
<plurals name="markets_token_details_based_on_ratings">
<item quantity="one">На основі %d оцінки</item>
@ -464,11 +468,11 @@
<string name="markets_tooltip_message">Потягніть вгору або торкніться панелі пошуку, щоб додати токени безпосередньо з маркету</string>
<string name="markets_tooltip_title">Додати токени</string>
<string name="nfc_error_unavailable">Функція NFC недоступна на вашому пристрої</string>
<string name="onboarding_access_code_feature_1_description">Вам потрібно встановити єдиний код доступу для захисту всіх ваших карток</string>
<string name="onboarding_access_code_feature_1_description">Налаштуйте єдиний код доступу для захисту всіх ваших карток або кілець</string>
<string name="onboarding_access_code_feature_1_title">Захист</string>
<string name="onboarding_access_code_feature_2_description">Пізніше ви зможете налаштувати індивідуальний код доступу до кожної картки</string>
<string name="onboarding_access_code_feature_2_description">Встановіть індивідуальний код доступу для кожної картки або кільця пізніше.</string>
<string name="onboarding_access_code_feature_2_title">Персоналізація</string>
<string name="onboarding_access_code_feature_3_description">Код доступу можна відновити за допомогою прив\'язаної картки. Не зберігайте всі картки в одному місці.</string>
<string name="onboarding_access_code_feature_3_description">Відновіть код доступу за допомогою прив\'язаної картки або кільця. Не зберігайте всі свої пристрої в одному місці.</string>
<string name="onboarding_access_code_feature_3_title">Відновлення</string>
<string name="onboarding_access_code_hint">Оберіть будь-яке слово, фразу або число в якості коду доступу</string>
<string name="onboarding_access_code_intro_title">Створити код доступу</string>
@ -476,27 +480,29 @@
<string name="onboarding_access_code_repeat_code_title">Повторно введіть код доступу</string>
<string name="onboarding_access_code_too_short">Код доступу повинен містити не менше 4 символів</string>
<string name="onboarding_access_codes_doesnt_match">Введені коди доступу не збігаються</string>
<string name="onboarding_activation_error_message">Необхідно повторити операцію. Карту буде скинуто до заводських налаштувань.</string>
<string name="onboarding_activation_error_message">Необхідно повторити операцію, при цьому картка буде скинута до заводських налаштувань.</string>
<string name="onboarding_activation_error_title">Помилка активації</string>
<string name="onboarding_add_tokens">Додати токени</string>
<string name="onboarding_alert_message_not_max_backup_cards_added">Ви додали одну резервну картку. Після завершення процесу резервного копіювання ви не зможете додати більше резервних карток. Якщо у вас є ще одна картка, додайте її до резервної копії. Ви бажаєте продовжити?</string>
<string name="onboarding_alert_message_not_max_backup_cards_added">Ви додали одну резервну картку або кільце. Після завершення процесу резервного копіювання ви не зможете додати їх більше. Якщо у вас є ще одна картка або кільце, додайте її до резервної копії. Бажаєте продовжити?</string>
<string name="onboarding_backup_exit_warning">Процес резервного копіювання частково завершено. Ви не можете вийти з нього зараз.</string>
<string name="onboarding_bottom_sheet_passphrase_description">Парольна фраза це розширена функція безпеки, яку використовують криптогаманці. Вона додає додаткове слово або фразу на ваш вибір до вже існуючої seed - фрази, щоб розблокувати абсолютно новий набір адрес.</string>
<string name="onboarding_button_add_backup_card">Додати резервну картку</string>
<string name="onboarding_button_backup_card_format">Відсканувати картку #%d</string>
<string name="onboarding_button_add_backup_card">Додати картку або кільце</string>
<string name="onboarding_button_backup_card">Сканувати картку</string>
<string name="onboarding_button_backup_card_format">Сканувати картку #%d</string>
<string name="onboarding_button_backup_now">Створити резервну копію</string>
<string name="onboarding_button_backup_origin">Відсканувати основну картку</string>
<string name="onboarding_button_backup_origin">Сканувати картку</string>
<string name="onboarding_button_backup_ring">Сканувати кільце</string>
<string name="onboarding_button_continue_wallet">Перейти до мого гаманця</string>
<string name="onboarding_button_finalize_backup">Завершення бекапу</string>
<string name="onboarding_button_receive_crypto">Отримати криптовалюту</string>
<string name="onboarding_button_scan_origin_card">Сканувати основну картку</string>
<string name="onboarding_button_skip_backup">Пропустити</string>
<string name="onboarding_button_what_does_it_mean">Як це працює?</string>
<string name="onboarding_create_wallet_body">Давайте згенеруємо всі ключі на вашій картці та створимо безпечний гаманець</string>
<string name="onboarding_create_wallet_body">Давайте згенеруємо всі ключі на вашій картці або кільці та створимо безпечний гаманець</string>
<string name="onboarding_create_wallet_button_create_wallet">Створити гаманець</string>
<string name="onboarding_create_wallet_header">Створити гаманець</string>
<string name="onboarding_create_wallet_options_button_options">Інші опції</string>
<string name="onboarding_create_wallet_options_message">Ваші ключі будуть надійно згенеровані всередині картки. Ніякої seed-фрази, а це означає, що ніхто не зможе її експортувати або вкрасти.</string>
<string name="onboarding_create_wallet_options_message">Ваші ключі будуть надійно згенеровані всередині чіпу. Ніякої seed-фрази, а це означає, що ніхто не зможе її експортувати або вкрасти.</string>
<string name="onboarding_create_wallet_options_title">Генеруйте ключі приватно</string>
<string name="onboarding_done_body">Ваша картка активована та готова до використання</string>
<string name="onboarding_done_header">Успішно!</string>
@ -514,7 +520,7 @@
</plurals>
<string name="onboarding_seed_generate_title">Ваша seed-фраза</string>
<plurals name="onboarding_seed_generate_words_count">
<item quantity="one">%d слово</item>
<item quantity="one"></item>
<item quantity="few">%d слова</item>
<item quantity="many">%d слів</item>
<item quantity="other">%d слів</item>
@ -522,27 +528,30 @@
<string name="onboarding_seed_import_message">Щоб імпортувати гаманець, введіть seed-фразу в поле нижче</string>
<string name="onboarding_seed_intro_button_generate">Згенерувати seed-фразу</string>
<string name="onboarding_seed_intro_button_import">Імпорт гаманця</string>
<string name="onboarding_seed_intro_message">Seed-фраза — це набір слів, який дозволяє відновити ваш гаманець. На відміну від ключів, що генеруються карткою, seed-фраза не захищена і може бути скопійована та викрадена. Використовуйте цю опцію на свій власний ризик.</string>
<string name="onboarding_seed_intro_message">Seed-фраза — це набір слів, який надає можливість відновити гаманець. На відміну від ключів, що генеруються карткою або кільцем, seed-фраза не захищена і може бути скопійована та вкрадена. Використовуйте цей варіант на свій власний страх та ризик.</string>
<string name="onboarding_seed_intro_title">Використовувати seed-фразу</string>
<string name="onboarding_seed_mnemonic_invalid_checksum">Невірна seed-фраза. Будь ласка, перевірте порядок слів.</string>
<string name="onboarding_seed_mnemonic_wrong_words">Невірна seed-фраза. Будь ласка, перевірте правопис.</string>
<string name="onboarding_seed_phrase_intro_legacy">Застаріло</string>
<string name="onboarding_seed_user_validation_message">Щоб перевірити чи правильно ви записали seed-фразу, введіть 2-е, 7-е та 11-те слова</string>
<string name="onboarding_seed_user_validation_title">Отже, давайте перевіримо</string>
<string name="onboarding_subtitle_no_backup_cards">Щоб почати процес резервного копіювання, додайте одну або дві резервні картки.</string>
<string name="onboarding_subtitle_one_backup_card">Ви можете додати ще одну картку або завершити процес резервного копіювання</string>
<string name="onboarding_subtitle_no_backup_cards">Щоб почати процес резервного копіювання, додайте одну або дві резервні картки або кільця.</string>
<string name="onboarding_subtitle_one_backup_card">Ви можете додати ще одну картку або кільце або завершити процес резервного копіювання</string>
<string name="onboarding_subtitle_scan_backup_card_format">Підготуйте резервну картку з номером %s</string>
<string name="onboarding_subtitle_scan_primary">Відскануйте основну картку, щоб почати процес резервного копіювання.</string>
<string name="onboarding_subtitle_scan_primary">Відскануйте основну картку або кільце, щоб почати процес резервного копіювання.</string>
<string name="onboarding_subtitle_scan_primary_card_format">Підготуйте основну картку з номером %s</string>
<string name="onboarding_subtitle_success_tangem_wallet_onboarding">Ваша картка налаштована та готова до використання.</string>
<string name="onboarding_subtitle_two_backup_cards">Додано максимальну кількість карток. Завершіть процес резервного копіювання.</string>
<string name="onboarding_title">Активація картки</string>
<string name="onboarding_subtitle_scan_ring">Підготуйте кільце та натисніть кнопку сканування нижче</string>
<string name="onboarding_subtitle_success_tangem_wallet_onboarding">Ваш гаманець налаштований та готовий до використання.</string>
<string name="onboarding_subtitle_two_backup_cards">Додано максимальну кількість пристроїв. Завершіть процес резервного копіювання.</string>
<string name="onboarding_title">Активація гаманця</string>
<string name="onboarding_title_backup_card">Резервна картка</string>
<string name="onboarding_title_backup_card_format">Резервна картка #%d</string>
<string name="onboarding_title_no_backup_cards">Немає резервних карток</string>
<string name="onboarding_title_backup_ring">Резервне кільце</string>
<string name="onboarding_title_no_backup_cards">Немає резервних пристроїв</string>
<string name="onboarding_title_notifications">Сповіщення</string>
<string name="onboarding_title_one_backup_card">Додано одну резервну картку</string>
<string name="onboarding_title_one_backup_card">Додано один резервний пристрій</string>
<string name="onboarding_title_scan_origin_card">Підготуйте свою картку</string>
<string name="onboarding_title_two_backup_cards">Додано дві резервні картки</string>
<string name="onboarding_title_two_backup_cards">Додано два резервних пристрої</string>
<string name="onboarding_top_up_body">Поповніть гаманець на будь-яку суму, щоб почати користуватися карткою</string>
<string name="onboarding_top_up_body_no_account_error">Щоб почати, просто поповніть гаманець більше, ніж на %1$s %2$s</string>
<string name="onboarding_top_up_button_but_crypto">Купити криптовалюту</string>
@ -550,7 +559,7 @@
<string name="onboarding_topup_title">Активація гаманця</string>
<string name="onboarding_twin_exit_warning">Процес поєднання карток частково завершено. Ви не можете вийти з нього зараз.</string>
<string name="onboarding_twins_interrupt_warning">Якщо процес створення гаманця буде перервано будь-яким чином, вам доведеться почати все спочатку</string>
<string name="onboarding_wallet_info_subtitle_first">Ви можете створити резервну копію ключів на одній або двох інших порожніх картках Tangem Wallet.</string>
<string name="onboarding_wallet_info_subtitle_first">Ви можете створити резервну копію своїх ключів на одній або двох інших порожніх картках або кільцях Tangem Wallet.</string>
<string name="onboarding_wallet_info_subtitle_fourth">Код доступу можна відновити за допомогою однієї з резервних карток.</string>
<string name="onboarding_wallet_info_subtitle_second">Всі резервні карти можна використовувати як повнофункціональні з ідентичними ключами.</string>
<string name="onboarding_wallet_info_subtitle_third">Ви зможете встановити код доступу для захисту своїх гаманців.</string>
@ -558,6 +567,9 @@
<string name="onboarding_wallet_info_title_fourth">Відновлення коду доступу</string>
<string name="onboarding_wallet_info_title_second">Ідентичні картки</string>
<string name="onboarding_wallet_info_title_third">Код доступу</string>
<string name="onramp_residency_bottomsheet_country_not_supported">Наші сервіси недоступні в цій країні</string>
<string name="onramp_residency_bottomsheet_country_subtitle">Змінити або підтвердити</string>
<string name="onramp_residency_bottomsheet_title">Ваше місце проживання визначено як</string>
<string name="organize_tokens_group">Групами</string>
<string name="organize_tokens_sort_by_balance">За балансом</string>
<string name="organize_tokens_title">Сортування токенів</string>
@ -568,7 +580,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">Перекажіть кошти з іншого гаманця або біржі</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>
@ -605,13 +617,13 @@
<string name="reset_card_to_factory_button_title">Скинути картку</string>
<string name="reset_card_to_factory_condition_1">Я розумію, що після виконання цієї дії у мене більше не буде доступу до поточного гаманця</string>
<string name="reset_card_to_factory_condition_2">Я розумію, що не можу використати цю картку для відновлення свого коду доступу на інших картках поточного гаманця</string>
<string name="reset_card_with_backup_to_factory_message">Скидання до заводських налаштувань призведе до повного видалення гаманця з обраної картки. Ви не зможете відновити поточний гаманець або використати картку для відновлення коду доступу.</string>
<string name="reset_card_without_backup_to_factory_message">Скидання до заводських налаштувань призведе до повного видалення гаманця з обраної картки. Ви не зможете відновити поточний гаманець.</string>
<string name="reset_card_with_backup_to_factory_message">Скидання до заводських налаштувань призведе до повного видалення гаманця з обраної картки або кільця. Ви не зможете відновити поточний гаманець або використати цю картку або кільце для відновлення коду доступу.</string>
<string name="reset_card_without_backup_to_factory_message">Скидання до заводських налаштувань призведе до повного видалення гаманця з обраної картки або кільця. Ви не зможете відновити поточний гаманець.</string>
<string name="ring_promo_text">Власникам кілець - 3 обміни без комісії на Changelly до 15.11!</string>
<string name="ring_promo_title">Обмін з 0%% комісією!</string>
<string name="russian_bank_card_warning_subtitle">У вас є банківська картка іншої країни та посвідка на проживання або реєстрація за межами Російської Федерації?</string>
<string name="russian_bank_card_warning_title">Російські банківські картки наразі не приймаються</string>
<string name="save_user_wallet_agreement_access_description">Увійдіть у додаток та слідкуйте за своїм балансом без сканування картки</string>
<string name="save_user_wallet_agreement_access_description">Увійдіть у додаток та слідкуйте за своїм балансом без сканування картки чи кільця</string>
<string name="save_user_wallet_agreement_access_title">Доступ до додатку</string>
<string name="save_user_wallet_agreement_allow_biometrics">Використовувати біометрію</string>
<string name="save_user_wallet_agreement_code_description_biometrics">Для взаємодії з гаманцем будуть запитуватися біометричні дані замість коду доступу</string>
@ -619,12 +631,12 @@
<string name="save_user_wallet_agreement_enroll_biometrics_description">Схоже, що у вас відключена біометрична автентифікація, вона необхідна для збереження гаманців</string>
<string name="save_user_wallet_agreement_enroll_biometrics_title">Увімкніть біометричну автентифікацію</string>
<string name="save_user_wallet_agreement_header_biometrics">Бажаєте використовувати біометрію?</string>
<string name="save_user_wallet_agreement_notice">Зверніть увагу, що для здійснення транзакції з вашими коштами вам все одно знадобиться ваша картка</string>
<string name="save_user_wallet_agreement_notice">Зверніть увагу, що для здійснення транзакції з вашими коштами вам все одно знадобиться ваша картка або кільце</string>
<string name="scan_card_settings_button">Сканувати</string>
<string name="scan_card_settings_message">Відскануйте картку, щоб змінити її налаштування. Зміни торкнуться лише відсканованої картки і не вплинуть на інші картки, прив\'язані до вашого гаманця.</string>
<string name="scan_card_settings_title">Підготуйте свою картку</string>
<string name="scan_card_settings_message">Відскануйте картку або кільце, щоб змінити її налаштування. Зміни торкнуться лише тої картки або кільця, які ви відсканували, і не вплинуть на інші пристрої, прив\'язані до вашого гаманця.</string>
<string name="scan_card_settings_title">Підготуйте свій Tangem!</string>
<string name="send_additional_field_already_included">Вже включено до введеної адреси</string>
<string name="send_alert_fee_too_high_text">Сума комісії у %s разів перевищує рекомендовану. Переконайтеся, що користувацькі налаштування вірні.</string>
<string name="send_alert_fee_too_high_text">Сума комісії у %s разів перевищує рекомендовану. Переконайтеся, що вказана комісія вірна.</string>
<string name="send_alert_fee_too_low_text">Ви вказали комісію нижче рекомендованої, це може спричинити затримку вашої транзакції. Продовжити?</string>
<string name="send_alert_transaction_failed_text">Причина: %1$s\nКод: %2$s</string>
<string name="send_alert_transaction_failed_title">Транзакція не завершена</string>
@ -659,7 +671,7 @@
<string name="send_notification_exceed_balance_title">Сума перевищує баланс</string>
<string name="send_notification_existential_deposit_text">Для збереження вашого акаунту у блокчейні та захисту від можливих ризиків необхідний баланс не менше %s. Ця сума залишиться на вашому рахунку та не може бути знята.</string>
<string name="send_notification_existential_deposit_title">Екзистенційний депозит</string>
<string name="send_notification_fee_too_high_text">Сума комісії в %s разів перевищує рекомендовану. Переконайтеся, що користувацькі налаштування вірні.</string>
<string name="send_notification_fee_too_high_text">Сума комісії в %s разів перевищує рекомендовану. Переконайтеся, що вказана комісія вірна.</string>
<string name="send_notification_fee_too_high_title">Встановлена комісія завелика</string>
<string name="send_notification_high_fee_text">Через особливості мережі %1$s комісія за переказ всього балансу вища. Щоб зменшити комісію, Ви можете залишити %2$s.</string>
<string name="send_notification_high_fee_title">Підвищена комісія</string>
@ -693,12 +705,12 @@
<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_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>
<string name="sent_transaction_sent_title">Трансакцію надіслано</string>
<string name="settings_card_settings_footer">Підготуйте до сканування картку, яку потрібно налаштувати.</string>
<string name="settings_card_settings_footer">Підготуйтеся до сканування кільця або картки, яку ви хочете налаштувати.</string>
<string name="settings_forget_wallet">Забути гаманець</string>
<string name="settings_forget_wallet_footer">Це призведе до видалення гаманця з застосунку. Сам гаманець можна додати знову.</string>
<string name="settings_wallet_name_title">Ім\'я</string>
@ -718,17 +730,18 @@
<string name="staking_details_market_rating">Рейтинг ринку</string>
<string name="staking_details_metrics_block_header">Метрики</string>
<string name="staking_details_minimum_requirement">Мінімальні вимоги</string>
<string name="staking_details_no_rewards_to_claim">Немає винагород, щоб отримати</string>
<string name="staking_details_no_rewards_to_claim">Немає винагород, до отримання</string>
<string name="staking_details_reward_claiming">Отримати винагороду</string>
<string name="staking_details_reward_claiming_info">Спосіб отримання винагороди за стейкінг. Його можна отримати автоматично або вручну.</string>
<string name="staking_details_reward_claiming_info">Метод отримання винагород за стейкінг.\nВін може зараховуватися автоматично на вашу адресу або вручну, коли винагороду треба вивести, створивши транзакцію на її отримання.</string>
<string name="staking_details_reward_schedule">Розклад винагород</string>
<string name="staking_details_reward_schedule_info">Це графік, який визначає коли учасники стейкінгу отримують свої винагороди.</string>
<string name="staking_details_reward_schedule_info">Це графік, який визначає, коли учасники стейкінгу отримують свої винагороди. Час розподілу винагород може дещо відрізнятися залежно від валідатора та навантаження на мережу.</string>
<string name="staking_details_rewards_to_claim">Нагороди для отримання: %s</string>
<string name="staking_details_title">Стейкінг %s</string>
<string name="staking_details_unbonding_period">Період розблокування</string>
<string name="staking_details_unbonding_period_info">Період, який ви повинні чекати після запиту на виведення коштів зі стейкінгу, перш ніж токени стануть доступними.</string>
<string name="staking_details_warmup_period">Період блокування</string>
<string name="staking_details_warmup_period_info">Відведений час для активації участі в стейкінгу.</string>
<string name="staking_give_permission_fee_footer">Комісія мережі за схвалення токену, щоб верифікувати, що саме ви даєте дозвіл на використання вашого токена для стейкінгу.</string>
<string name="staking_legal">Використовуючи функцію стейкінгу, ви погоджуєтесь з %1$s та %2$s</string>
<string name="staking_locked">Заблоковано</string>
<string name="staking_migrate">Перемістити</string>
@ -739,19 +752,20 @@
<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_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_restake_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_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>
@ -762,19 +776,21 @@
<string name="staking_revote">Переголосувати</string>
<string name="staking_reward_claiming_auto">Автоматично</string>
<string name="staking_reward_claiming_manual">Вручну</string>
<string name="staking_reward_schedule_block">Блок</string>
<string name="staking_reward_schedule_day">День</string>
<string name="staking_reward_schedule_block">За блок</string>
<string name="staking_reward_schedule_day">Щоденно</string>
<string name="staking_reward_schedule_each">Кожен %s</string>
<string name="staking_reward_schedule_each_day">Щодня</string>
<string name="staking_reward_schedule_epoch">Епоха</string>
<string name="staking_reward_schedule_era">Ера</string>
<string name="staking_reward_schedule_hour">Година</string>
<string name="staking_reward_schedule_each_days">Кожні %s дні</string>
<string name="staking_reward_schedule_each_plural">Кожні</string>
<string name="staking_reward_schedule_epoch">За епоху</string>
<string name="staking_reward_schedule_era">За еру</string>
<string name="staking_reward_schedule_hour">Погодинно</string>
<string name="staking_reward_schedule_month">Місяць</string>
<string name="staking_reward_schedule_week">Тиждень</string>
<string name="staking_reward_schedule_week">Потижнево</string>
<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_summary_description_text">Ви стейкаєте %1$s і будете отримуватиме винагороду %2$s</string>
<string name="staking_tap_to_unlock">Натисніть, щоб розблокувати</string>
<string name="staking_tap_to_unlock_or_vote">Натисніть, щоб розблокувати або проголосувати</string>
<string name="staking_tap_to_withdraw">Натисніть, щоб вивести кошти</string>
@ -784,6 +800,7 @@
<string name="staking_unbonding">Розблокування</string>
<string name="staking_unlocked_locked">Розблокувати</string>
<string name="staking_unlocking">Розблокування</string>
<string name="staking_unstake_amount_validation_error">Сума перевищує баланс стейкінгу</string>
<string name="staking_unstaked">Вивід зі стейкінгу</string>
<string name="staking_unstaking">Зняти зі стейкінгу</string>
<string name="staking_unstaking_item_name">Виведення зі стейкінгу %s</string>
@ -794,17 +811,18 @@
<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_description">Тримайте свою криптовалюту в безпеці. Приватні ключі надійно зберігаються на картці або кільці</string>
<string name="story_awe_title">Революційний апаратний гаманець</string>
<string name="story_backup_description">До трьох карток з одним гаманцем</string>
<string name="story_backup_description">До трьох карток або кілець з одним гаманцем</string>
<string name="story_backup_title">Всі ключі у безпеці</string>
<string name="story_currencies_description">Апаратний гаманець для ваших біткоїнів, ефіріуму та багатьох інших валют одночасно — і все це на одній картці</string>
<string name="story_currencies_description">Апаратний гаманець для ваших біткоїнів, ефіріуму та багатьох інших валют одночасно — і все це на одній картці або кільці</string>
<string name="story_currencies_title">Тисячі криптовалют</string>
<string name="story_finish_description">Використовуйте його в дорозі, будь-де і будь-коли. Ніяких дротів чи батарейок. Просто прикладіть картку до телефону, коли вам потрібна криптовалюта.</string>
<string name="story_finish_description">Використовуйте його в дорозі, будь-де і будь-коли. Ніяких дротів чи батарейок. Просто прикладіть картку або кільце до телефону, коли вам потрібна криптовалюта.</string>
<string name="story_finish_title">Гаманець для кожного</string>
<string name="story_meet_title">Зустрічайте Tangem</string>
<string name="story_web3_description">Обмінюйте, купуйте NFT, отримуйте позики та робіть депозити у понад 100 різних децентралізованих сервісах</string>
<string name="story_web3_title">Web 3.0 сумісність</string>
<string name="swap_give_permission_fee_footer">Мережа стягує комісію за схвалення токену за підтвердження, що саме ви дозволяєте використовувати ваш токен для обміну.</string>
<string name="swap_promo_text">Обмінюйте більше токенів за вигіднішим курсом прямо у своєму гаманці.</string>
<string name="swap_promo_title">З\'явився новий провайдер обмінів!</string>
<string name="swapping_alert_cex_description">Сума включає: \n• комісію постачальника послуг\n• комісію мережі за відправлення %s з біржі назад на адресу користувача.</string>
@ -861,28 +879,28 @@
<string name="twin_error_wrong_twin">Ви відсканували не ту twin-картку. Будь ласка, спробуйте відсканувати іншу</string>
<string name="twins_onboarding_description_format">Це картка, яку ви тримаєте в руках. У парної картки номер %s.\n\nОбидві картки можна використовувати для зняття коштів з цього гаманця.</string>
<string name="twins_onboarding_subtitle">Один гаманець. Дві картки.</string>
<string name="twins_recreate_button_format">Відсканувати картку #%s</string>
<string name="twins_recreate_button_format">Сканувати картку #%s</string>
<string name="twins_recreate_title_creating_wallet">Створення гаманця</string>
<string name="twins_recreate_title_format">Відскануйте twin-картку # %s</string>
<string name="twins_recreate_title_preparing">Підготовка картки</string>
<string name="twins_recreate_toolbar">Tangem Twin</string>
<string name="twins_recreate_warning">Ця дія є незворотною. Ви не матимете доступу до старого гаманця.</string>
<string name="twins_scan_twin_with_number">Прикладіть twin-картку з номером %s та не прибирайте її до завершення операції</string>
<string name="unlock_wallet_description_full">Використовуйте %s або відскануйте картку, щоб отримати доступ до свого гаманця</string>
<string name="unlock_wallet_description_full">Використовуйте %s або відскануйте картку/кільце, щоб отримати доступ до свого гаманця</string>
<string name="user_push_notification_agreement_argument_one">Будьте в курсі останніх функцій та новин</string>
<string name="user_push_notification_agreement_argument_two">Дізнавайтеся першими про нові акції</string>
<string name="user_push_notification_agreement_header">Бажаєте використовувати Push-повідомлення?</string>
<string name="user_wallet_list_add_button">Додати новий гаманець</string>
<string name="user_wallet_list_delete_prompt">Ви впевнені, що хочете видалити цей гаманець?</string>
<string name="user_wallet_list_error_unable_to_unlock">Сталася помилка, будь ласка, відскануйте свою картку, щоб увійти в систему</string>
<string name="user_wallet_list_error_unable_to_unlock">Сталася помилка, будь ласка, відскануйте свою картку або кільце, для входу</string>
<string name="user_wallet_list_error_wallet_already_saved">Цей гаманець вже збережено, ви можете додати інший</string>
<string name="user_wallet_list_rename_popup_error_already_exists">Гаманець з назвою %s вже існує</string>
<string name="user_wallet_list_rename_popup_placeholder">Назва гаманця</string>
<string name="user_wallet_list_rename_popup_title">Перейменувати гаманець</string>
<string name="user_wallet_list_rename_popup_title">Перейменування гаманця</string>
<string name="user_wallet_list_unlock_all">Розблокувати все</string>
<string name="user_wallet_list_unlock_all_with">Розблокувати все з %s</string>
<string name="wallet_balance_blockchain_unreachable_try_later">Блокчейн недоступний. Спробуйте пізніше</string>
<string name="wallet_balance_missing_derivation">Відскануйте картку</string>
<string name="wallet_balance_missing_derivation">Відскануйте картку або кільце</string>
<string name="wallet_connect_alert_sign_message">Запит на підпис повідомлення.\n\n%s</string>
<string name="wallet_connect_bnb_sign_message">Dapp %1$s, запит на\nпідпис транзакції BNB.\n\n%2$s</string>
<string name="wallet_connect_bnb_trade_order_message">Торговий ордер на %1$s\nЦіна: %2$s\nСума до отримання: %3$s\nСума до сплати: %4$s</string>
@ -891,12 +909,13 @@
<string name="wallet_connect_create_tx_message">Запит на створення транзакції для %1$s\n%2$s\n\nСума: %3$s\nКомісія: %4$s\nВсього: %5$s\nБаланс: %6$s</string>
<string name="wallet_connect_create_tx_not_enough_funds">Неможливо відправити транзакцію. Недостатньо коштів.</string>
<string name="wallet_connect_error_failed_to_connect">Не вдалося встановити сеанс WalletConnect. Будь ласка, спробуйте пізніше.</string>
<string name="wallet_connect_error_missing_blockchains">Не всі токени додано до вашого списку. Будь ласка, додайте їх спочатку і спробуйте ще раз. Відсутні токени:\n</string>
<string name="wallet_connect_error_sing_failed">Не вдалося підписати повідомлення.\nБудь ласка, спробуйте ще раз</string>
<string name="wallet_connect_error_timeout">Не вдалося створити сеанс WalletConnect за відведений час. Будь ласка, спробуйте пізніше.</string>
<string name="wallet_connect_error_unsupported_blockchains">Запит на підключення сеансу WalletConnect містить непідтримувані блокчейни. Непідтримувані блокчейни:\n</string>
<string name="wallet_connect_error_unsupported_dapp">Зв\'язок з цим Dapp сервісом не може бути встановлений через його технічну реалізацію.</string>
<string name="wallet_connect_error_with_framework_message">Ми зіткнулися з невідомою помилкою. Повідомлення про помилку: %s. Якщо проблема не зникає — зверніться до нашої служби підтримки.</string>
<string name="wallet_connect_error_wrong_card_selected">Невірна картка обрана в додатку Tangem</string>
<string name="wallet_connect_error_wrong_card_selected">Невірна картка або кільце обрана в додатку Tangem</string>
<string name="wallet_connect_failed_to_build_tx">Не вдалося створити транзакцію з даних Dapp. Код: %s</string>
<string name="wallet_connect_generic_error_with_code">Ми зіткнулися з невідомою помилкою. Код помилки: %d. Якщо проблема не зникає — зверніться до нашої служби підтримки.</string>
<string name="wallet_connect_no_sessions_message">Немає відкритих сеансів WalletConnect</string>
@ -921,10 +940,10 @@
<string name="wallet_notification_no_internet">Немає підключення до інтернету</string>
<string name="wallet_settings_title">Налаштування гаманця</string>
<string name="wallet_title">Tangem</string>
<string name="warning_access_denied_message">Використовуйте %s або відскануйте картку, щоб розблокувати доступ до гаманця</string>
<string name="warning_access_denied_message">Використовуйте %s або відскануйте картку/кільце, щоб розблокувати доступ до вашого гаманця</string>
<string name="warning_approval_in_progress_message">Процес підтвердження наразі триває і буде завершено найближчим часом</string>
<string name="warning_approval_in_progress_title">Підтвердження в процесі</string>
<string name="warning_backup_errors_message">Схоже, що активація картки була виконана неправильно. Це може бути пов\'язано з проблемою з модулем NFC вашого пристрою або неправильним прикладанням картки до пристрою. Зверніться за допомогою до нашої служби підтримки.</string>
<string name="warning_backup_errors_message">Схоже, що активація карток або кільця була виконана неправильно. Це може бути пов\'язано з проблемою з модулем NFC вашого пристрою або неправильним прикладанням картки або кільця до телефону. Будь ласка, зверніться за допомогою до нашої служби підтримки для уточнення деталей.</string>
<string name="warning_backup_errors_title">Помилка активації</string>
<string name="warning_beacon_chain_retirement_content">За рішенням розробників мережі BNB стандарт BEP-2 перестане підтримуватись у червні 2024 року. Щоб не втратити свої активи, їх необхідно конвертувати у стандарт BEP-20. Використовуйте функцію обміну, щоб перевести їх у мережу BNB Smart Chain.</string>
<string name="warning_beacon_chain_retirement_title">Відключення мережі BNB Beacon Chain</string>
@ -943,7 +962,7 @@
<string name="warning_existential_deposit_title">Для роботи з мережею вимагається депозит</string>
<string name="warning_express_active_transaction_message">Обмін буде доступний після завершення %s транзакції</string>
<string name="warning_express_active_transaction_title">У вас є активна транзакція</string>
<string name="warning_express_approval_in_progress_message">Затвердження обміну триває і незабаром буде завершено</string>
<string name="warning_express_approval_in_progress_message">Дозвіл обміну триває і незабаром буде завершено</string>
<string name="warning_express_approval_in_progress_title">Затвердження в процесі</string>
<string name="warning_express_dust_message">Мінімальна сума обміну становить - %1$s. Будь ласка, переконайтеся, що залишок на рахунку після обміну буде не менше за %2$s.</string>
<string name="warning_express_no_exchangeable_coins_description">У вашому списку немає доступних монет для обміну %s</string>
@ -967,13 +986,13 @@
<string name="warning_low_signatures_message">На цій картці залишається лише %s підписів. Ви повинні вивести всі свої кошти.</string>
<string name="warning_low_signatures_title">Низька кількість підписів</string>
<string name="warning_manage_tokens_legacy_derivation_message">Токени в різних мережах можуть мати різні адреси. Переконайтеся, що ваша адреса відповідає мережі, коли переказуєте кошти.</string>
<string name="warning_matic_migration_message">Токен MATIC мігрує до POL. Однак кінцевого терміну не встановлено і MATIC ще не застарілий. Ви можете безпечно продовжувати використовувати токен MATIC або обміняти його на POL.</string>
<string name="warning_matic_migration_message">Токен MATIC мігрує до POL. Однак кінцевого терміну не встановлено і MATIC ще не застарілий. Ви можете спокійно продовжувати використовувати токен MATIC або обміняти його на POL.</string>
<string name="warning_matic_migration_title">Міграція MATIC у POL</string>
<plurals name="warning_missing_derivation_message">
<item quantity="one">Використовуйте вашу картку, щоб отримати адресу для %d мережі</item>
<item quantity="few">Використовуйте вашу картку, щоб отримати адреси для %d мереж</item>
<item quantity="many">Використовуйте вашу картку, щоб отримати адреси для %d мереж</item>
<item quantity="other">Використовуйте вашу картку, щоб отримати адреси для %d мереж</item>
<item quantity="one">Використовуйте вашу картку або кільце, щоб отримати адресу для %d мережі</item>
<item quantity="few">Використовуйте вашу картку або кільце, щоб отримати адреси для %d мереж</item>
<item quantity="many">Використовуйте вашу картку або кільце, щоб отримати адреси для %d мереж</item>
<item quantity="other">Використовуйте вашу картку або кільце, щоб отримати адреси для %d мереж</item>
</plurals>
<string name="warning_missing_derivation_title">Деякі адреси відсутні</string>
<string name="warning_network_unreachable_message">Мережа наразі недоступна. Будь ласка, спробуйте пізніше.</string>
@ -1000,11 +1019,11 @@
<string name="welcome_interrupted_backup_alert_message">Ви не завершили резервне копіювання. Бажаєте продовжити?</string>
<string name="welcome_interrupted_backup_alert_resume">Так, поновити</string>
<string name="welcome_interrupted_backup_discard_discard">Відмовитися</string>
<string name="welcome_interrupted_backup_discard_message">Якщо зараз відмовитися, то доведеться скинути картки до заводських налаштувань, щоб почати спочатку</string>
<string name="welcome_interrupted_backup_discard_message">Якщо зараз відмовитися, то доведеться скидувати пристроїв до заводських налаштувань, щоб почати спочатку</string>
<string name="welcome_interrupted_backup_discard_resume">Відновити бекап</string>
<string name="welcome_interrupted_backup_discard_title">Це незворотна дія</string>
<string name="welcome_unlock">Увійдіть за допомогою %s</string>
<string name="welcome_unlock_card">Сканувати картку</string>
<string name="welcome_unlock_description">Використовуйте %s або відскануйте картку для доступу в додаток</string>
<string name="welcome_unlock_card">Сканувати картку або кільце</string>
<string name="welcome_unlock_description">Використовуйте %s або відскануйте картку або кільце для входу у додаток</string>
<string name="welcome_unlock_title">З поверненням!</string>
</resources>

View file

@ -83,10 +83,12 @@
<string name="common_buy_currency">Go to %1$s</string>
<string name="common_camera_denied_alert_message">You have not given access to your camera, please adjust your privacy settings</string>
<string name="common_cancel">Cancel</string>
<string name="common_change">Change</string>
<string name="common_choose_action">Choose action</string>
<string name="common_claim">Claim</string>
<string name="common_claim_rewards">Claim rewards</string>
<string name="common_close">Close</string>
<string name="common_confirm">Confirm</string>
<string name="common_continue">Continue</string>
<string name="common_copy">Copy</string>
<string name="common_copy_address">Copy address</string>
@ -257,6 +259,7 @@
<string name="express_exchange_status_exchanging">Exchanging</string>
<string name="express_exchange_status_exchanging_active">Exchanging...</string>
<string name="express_exchange_status_failed">Failed</string>
<string name="express_exchange_status_paused">Paused</string>
<string name="express_exchange_status_received">Deposit received</string>
<string name="express_exchange_status_receiving">Awaiting deposit</string>
<string name="express_exchange_status_receiving_active">Awaiting deposit...</string>
@ -297,17 +300,16 @@
<string name="feedback_subject_tx_failed">Can\'t send a transaction</string>
<string name="feedback_token_description_error">Coin description error</string>
<string name="give_permission_current_transaction">Transaction</string>
<string name="give_permission_fee_footer">The network will charge a token approval fee to verify that you are authorizing the use of your token for the swap.</string>
<string name="give_permission_policy_type_footer">Specify the approve limit for the selected token</string>
<string name="give_permission_rows_amount">Amount %s</string>
<string name="give_permission_staking_footer">The Approve function is needed to grant permission to another address to use a specific amount of your tokens. By design, smart contracts can\'t access your tokens unless you approve. By \"unlocking\" your tokens, you authorize the StakeKit smart contract to use them. The network\'s miners receive a gas fee (paid by you) to record this action on the blockchain. You can stake your token after giving approval.</string>
<string name="give_permission_staking_subtitle">To continue you need to allow StakeKit smart contract to use your %s</string>
<string name="give_permission_staking_subtitle">To continue you need to allow Polygon smart contract to use your %s</string>
<string name="give_permission_swap_subtitle" formatted="false">To continue, grant %1s smart contracts permission to use your %2s</string>
<string name="give_permission_title">Give Permission</string>
<string name="give_permission_unlimited">Unlimited</string>
<string name="home_button_order">Order Tangem</string>
<string name="home_button_scan">Scan Tangem</string>
<string name="information_generated_with_ai">This information was generated with AI.\nTap here, If you find any errors.</string>
<string name="information_generated_with_ai">This information was generated with AI.\nTap here, if you find any errors.</string>
<string name="initial_message_change_access_code_body">To change the access code tap the card or ring as shown above and do not remove until the end of the operation</string>
<string name="initial_message_change_passcode_body">To change the passcode tap the card as shown above and do not remove until the end of the operation</string>
<string name="initial_message_create_wallet_body">To create the wallet tap the card as shown above and do not remove until the end of the operation</string>
@ -337,7 +339,7 @@
<string name="manage_tokens_list_header_title">Coin market cap</string>
<string name="manage_tokens_network_selector_native_subtitle">Blockchain the cryptocurrency was initially created</string>
<string name="manage_tokens_network_selector_native_title">Native network</string>
<string name="manage_tokens_network_selector_non_native_info">Using non-native networks for tokens enables cross-blockchain interoperability, allowing assets to be utilized in diverse decentralized applications and smart contracts across platforms. However, this often involves a custodian or smart contract to hold the original asset securely, introducing centralization and counterparty risk.</string>
<string name="manage_tokens_network_selector_non_native_info">Using non-native networks for tokens enables cross-blockchain interoperability, allowing assets to be utilized in diverse decentralized applications and smart contracts across platforms. However, this often involves a custodian or smart contract to hold the original asset securely, introducing centralization and counterparty risk.</string>
<string name="manage_tokens_network_selector_non_native_subtitle">Not original or primary blockchain the token is hosted</string>
<string name="manage_tokens_network_selector_non_native_title">Non-native networks</string>
<string name="manage_tokens_network_selector_title">Choose networks</string>
@ -549,6 +551,9 @@
<string name="onboarding_wallet_info_title_fourth">Access code restore</string>
<string name="onboarding_wallet_info_title_second">Identical cards</string>
<string name="onboarding_wallet_info_title_third">Access code</string>
<string name="onramp_residency_bottomsheet_country_not_supported">Our services are not available in this country</string>
<string name="onramp_residency_bottomsheet_country_subtitle">Change or confirm it</string>
<string name="onramp_residency_bottomsheet_title">Your residence has been identified as</string>
<string name="organize_tokens_group">Group</string>
<string name="organize_tokens_sort_by_balance">By balance</string>
<string name="organize_tokens_title">Organize tokens</string>
@ -705,7 +710,7 @@
<string name="staking_details_market_rating">Market rating</string>
<string name="staking_details_metrics_block_header">Metrics</string>
<string name="staking_details_minimum_requirement">Minimum Requirement</string>
<string name="staking_details_no_rewards_to_claim">No rewards</string>
<string name="staking_details_no_rewards_to_claim">No rewards available</string>
<string name="staking_details_reward_claiming">Reward claiming</string>
<string name="staking_details_reward_claiming_info">Method of receiving staking rewards.\nIt can be either automatic, where the reward is credited to your address, or manual, where you need to withdraw the reward by creating a transaction to receive it.</string>
<string name="staking_details_reward_schedule">Reward schedule</string>
@ -716,6 +721,7 @@
<string name="staking_details_unbonding_period_info">The period you must wait after requesting to withdraw funds from staking before the tokens become available.</string>
<string name="staking_details_warmup_period">Warmup period</string>
<string name="staking_details_warmup_period_info">The allocated time for activating participation in staking.</string>
<string name="staking_give_permission_fee_footer">The network will charge a token approval fee to verify that you are authorizing the use of your token for the staking.</string>
<string name="staking_legal">By using staking functionality, you agree with providers %1$s and %2$s</string>
<string name="staking_locked">Locked</string>
<string name="staking_migrate">Migrate</string>
@ -754,6 +760,8 @@
<string name="staking_reward_schedule_day">Daily</string>
<string name="staking_reward_schedule_each">Each %s</string>
<string name="staking_reward_schedule_each_day">Each day</string>
<string name="staking_reward_schedule_each_days">Each %s days</string>
<string name="staking_reward_schedule_each_plural">Each</string>
<string name="staking_reward_schedule_epoch">Per Epoch</string>
<string name="staking_reward_schedule_era">Per Era</string>
<string name="staking_reward_schedule_hour">Hourly</string>
@ -762,7 +770,7 @@
<string name="staking_rewards">Rewards</string>
<string name="staking_stake_locked">Stake locked</string>
<string name="staking_stake_more">Stake more</string>
<string name="staking_summary_description_text">You stake %1$s and will be receiving your reward each %2$s</string>
<string name="staking_summary_description_text">You stake %1$s and will be receiving your reward %2$s</string>
<string name="staking_tap_to_unlock">Tap to unlock</string>
<string name="staking_tap_to_unlock_or_vote">Tap to unlock or vote</string>
<string name="staking_tap_to_withdraw">Tap to withdraw</string>
@ -772,6 +780,7 @@
<string name="staking_unbonding">Unbonding</string>
<string name="staking_unlocked_locked">Unlock</string>
<string name="staking_unlocking">Unlocking</string>
<string name="staking_unstake_amount_validation_error">Amount exceeds staked balance</string>
<string name="staking_unstaked">Unstaked</string>
<string name="staking_unstaking">Unstaking</string>
<string name="staking_unstaking_item_name">Unstaking assets %s</string>
@ -793,6 +802,7 @@
<string name="story_meet_title">Meet Tangem</string>
<string name="story_web3_description">Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services</string>
<string name="story_web3_title">Web 3.0 Compatible</string>
<string name="swap_give_permission_fee_footer">The network will charge a token approval fee to verify that you are authorizing the use of your token for the swap.</string>
<string name="swap_promo_text">Exchange more tokens at better rates directly in your wallet.</string>
<string name="swap_promo_title">New Swap Provider Available!</string>
<string name="swapping_alert_cex_description">The amount includes:\n• service provider\'s fee\n• network fee for sending %s from the exchange back to the user\'s address.</string>

View file

@ -24,7 +24,7 @@ fun FiatIcon(
size: Dp,
isGrayscale: Boolean,
modifier: Modifier = Modifier,
@DrawableRes fallbackResId: Int = R.drawable.ic_shape_circle,
@DrawableRes fallbackResId: Int = R.drawable.ic_shape_circle_40,
) {
val iconData: Any = if (url.isNullOrBlank()) fallbackResId else url
val alpha = if (isGrayscale) GRAY_SCALE_ALPHA else 1f

View file

@ -11,6 +11,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.AnnotatedString.Builder
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.decapitalize
import org.intellij.markdown.MarkdownElementTypes
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
@ -26,11 +27,16 @@ sealed interface TextReference {
/**
* Text resource id
*
* @property id resource id
* @property formatArgs arguments. Impossible to use [kotlinx.collections.immutable.ImmutableList] because [Any] is
* unstable.
* @property id resource id
* @property formatArgs arguments. Impossible to use [kotlinx.collections.immutable.ImmutableList] because
* [Any] is unstable.
* @property decapitalize whether resolved reference should be decapitalized
*/
data class Res(@StringRes val id: Int, val formatArgs: WrappedList<Any> = WrappedList(emptyList())) : TextReference
data class Res(
@StringRes val id: Int,
val formatArgs: WrappedList<Any> = WrappedList(emptyList()),
val decapitalize: Boolean = false,
) : TextReference
/**
* Plural resource id
@ -78,10 +84,15 @@ sealed interface TextReference {
*
* @param id The resource ID of the string.
* @param formatArgs A list of format arguments to be applied to the string resource.
* @return A [TextReference] representing the string resource with format arguments.
* @param decapitalize Whether resolved reference should be decapitalized
* @return [TextReference] representing the string resource with format arguments.
*/
fun resourceReference(@StringRes id: Int, formatArgs: WrappedList<Any> = WrappedList(emptyList())): TextReference {
return TextReference.Res(id, formatArgs)
fun resourceReference(
@StringRes id: Int,
formatArgs: WrappedList<Any> = WrappedList(emptyList()),
decapitalize: Boolean = false,
): TextReference {
return TextReference.Res(id, formatArgs, decapitalize)
}
/**
@ -161,7 +172,13 @@ fun TextReference.resolveReference(): String {
.map { if (it is TextReference) it.resolveReference() else it }
.toTypedArray()
stringResource(id = id, *args)
val resolvedReference = stringResource(id = id, *args)
if (decapitalize) {
resolvedReference.replaceFirstChar { char -> char.lowercase() }
} else {
resolvedReference
}
}
is TextReference.PluralRes -> pluralStringResource(id, count, *formatArgs.toTypedArray())
is TextReference.Str -> value

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size
android:width="40dp"
android:height="40dp" />
</shape>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:fillColor="#D9D9D9"/>
</vector>

View file

@ -11,6 +11,7 @@ object SupportedLanguages {
const val JAPANESE = "ja"
const val UKRAINIAN = "uk"
const val CHINESE = "uk"
const val SPANISH = "es"
val supportedLangugeCodes = listOf(
ENGLISH,
@ -21,6 +22,7 @@ object SupportedLanguages {
JAPANESE,
UKRAINIAN,
CHINESE,
SPANISH,
)
fun getCurrentSupportedLanguageCode(): String {

View file

@ -99,6 +99,7 @@ internal class DefaultManageTokensRepository(
loadUserTokensFromRemote: Boolean,
): BatchFetchResult.Success<List<ManagedCryptoCurrency>> {
val supportedBlockchains = getSupportedBlockchains(userWallet)
val query = request.params.searchText.takeUnless(String?::isNullOrBlank)
val call = suspend {
tangemTechApi.getCoins(
@ -107,7 +108,7 @@ internal class DefaultManageTokensRepository(
transform = Blockchain::toNetworkId,
),
active = true,
searchText = request.params.searchText,
searchText = query,
offset = request.offset * request.limit,
limit = request.limit,
).getOrThrow()
@ -135,7 +136,7 @@ internal class DefaultManageTokensRepository(
val items = if (isFirstBatchFetching &&
tokensResponse != null &&
userWallet != null &&
request.params.searchText.isNullOrBlank()
query == null
) {
managedCryptoCurrencyFactory.createWithCustomTokens(
coinsResponse = updatedCoinsResponse,

View file

@ -1,6 +1,7 @@
package com.tangem.data.markets.converters
import com.tangem.datasource.api.markets.models.response.TokenMarketExchangesResponse
import com.tangem.domain.markets.BuildConfig
import com.tangem.domain.markets.TokenMarketExchange
import com.tangem.utils.converter.Converter
@ -11,6 +12,8 @@ import com.tangem.utils.converter.Converter
*/
internal object TokenMarketExchangeConverter : Converter<TokenMarketExchangesResponse.Exchange, TokenMarketExchange> {
private const val PROD_IMAGE_HOST = "https://s3.eu-central-1.amazonaws.com/tangem.api/exchanges/"
private const val DEV_IMAGE_HOST = "https://s3.eu-central-1.amazonaws.com/tangem.api.dev/exchanges/"
private val RISKY_INTERVAL = 0..3
private val CAUTION_INTERVAL = 4..7
@ -19,7 +22,7 @@ internal object TokenMarketExchangeConverter : Converter<TokenMarketExchangesRes
TokenMarketExchange(
id = id,
name = name,
imageUrl = imageUrl,
imageUrl = "${getImageHost()}large/$id.png",
isCentralized = isCentralized,
volumeInUsd = volumeInUsd,
trustScore = when (trustScore) {
@ -32,4 +35,12 @@ internal object TokenMarketExchangeConverter : Converter<TokenMarketExchangesRes
)
}
}
private fun getImageHost(): String {
return if (BuildConfig.TESTER_MENU_ENABLED) {
DEV_IMAGE_HOST
} else {
PROD_IMAGE_HOST
}
}
}

View file

@ -13,7 +13,7 @@ internal class DefaultStakingErrorResolver(
return if (throwable is ApiResponseError.HttpException) {
stakeKitErrorConverter.convert(throwable.errorBody.orEmpty())
} else {
StakingError.UnknownError
StakingError.UnknownError()
}
}
}

View file

@ -607,9 +607,9 @@ internal class DefaultStakingRepository(
Blockchain.Solana.run { id + toCoinId() } to SOLANA_INTEGRATION_ID,
Blockchain.Cosmos.run { id + toCoinId() } to COSMOS_INTEGRATION_ID,
Blockchain.Tron.run { id + toCoinId() } to TRON_INTEGRATION_ID,
Blockchain.Ethereum.id + Blockchain.Polygon.toCoinId() to ETHEREUM_POLYGON_INTEGRATION_ID,
Blockchain.Ethereum.id + Blockchain.Polygon.toMigratedCointId() to ETHEREUM_POLYGON_INTEGRATION_ID,
Blockchain.BSC.run { id + toCoinId() } to BINANCE_INTEGRATION_ID,
// Blockchain.Ethereum.id + Blockchain.Polygon.toCoinId() to ETHEREUM_POLYGON_INTEGRATION_ID,
// Blockchain.BSC.run { id + toCoinId() } to BINANCE_INTEGRATION_ID,
// Blockchain.Polkadot.run { id + toCoinId() } to POLKADOT_INTEGRATION_ID,
// Blockchain.Avalanche.run { id + toCoinId() } to AVALANCHE_INTEGRATION_ID,
// Blockchain.Cronos.run { id + toCoinId() } to CRONOS_INTEGRATION_ID,

View file

@ -14,7 +14,7 @@ internal class StakeKitErrorConverter(
@Suppress("CyclomaticComplexMethod", "LongMethod")
override fun convert(value: String): StakingError {
return try {
val stakeKitErrorResponse = jsonAdapter.fromJson(value) ?: return StakingError.UnknownError
val stakeKitErrorResponse = jsonAdapter.fromJson(value) ?: return StakingError.UnknownError(value)
if (stakeKitErrorResponse.type == AccessDeniedErrorTypeDTO.GEO_LOCATION) {
StakingError.UnavailableDueToGeolocationError(
@ -106,10 +106,10 @@ internal class StakeKitErrorConverter(
StakingError.GRTStakingDisabledError
StakeKitErrorMessageDTO.GRT_STAKING_DISABLED_LEDGER_LIVE_ERROR ->
StakingError.GRTStakingDisabledLedgerLiveError
else -> StakingError.UnknownError
else -> StakingError.UnknownError(value)
}
} catch (e: Exception) {
StakingError.UnknownError
StakingError.UnknownError(value)
}
}
}

View file

@ -4,6 +4,7 @@ import com.tangem.blockchain.common.*
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.blockchain.common.transaction.TransactionSendResult
import com.tangem.blockchain.common.transaction.TransactionsSendResult
import com.tangem.blockchain.extensions.Result
import com.tangem.common.CompletionResult
import kotlin.random.Random
@ -39,6 +40,11 @@ class DemoTransactionSender(private val walletManager: WalletManager) : Transact
}
}
override suspend fun sendMultiple(
transactionDataList: List<TransactionData>,
signer: TransactionSigner,
): Result<TransactionsSendResult> = Result.Failure(Exception(ID).toBlockchainSdkError())
private fun getDataToSign(): ByteArray {
val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
return IntRange(start = 1, endInclusive = 32)

View file

@ -16,12 +16,19 @@ class ValidateTokenFormUseCase(
networkId: Network.ID,
formValues: AddCustomTokenForm.Raw,
): EitherNel<CustomTokenFormValidationException, AddCustomTokenForm.Validated> = either {
if (formValues.name.isBlank() && formValues.symbol.isBlank() && formValues.decimals.isBlank()) {
val contractAddress = withError({ nonEmptyListOf(it) }) {
ensureIsContractAddressValid(formValues.contractAddress, networkId)
}
if (formValues.name.isBlank() &&
formValues.symbol.isBlank() &&
formValues.decimals.isBlank()
) {
if (formValues.contractAddress.isBlank()) {
AddCustomTokenForm.Validated.Empty
} else {
val contractAddress = withError({ nonEmptyListOf(it) }) {
ensureIsContractAddressValid(formValues.contractAddress, networkId)
}
AddCustomTokenForm.Validated.ContractAddress(contractAddress)
AddCustomTokenForm.Validated.ContractAddressOnly(contractAddress)
}
} else {
zipOrAccumulate(
{ ensureIsContractAddressValid(formValues.contractAddress, networkId) },
@ -43,10 +50,6 @@ class ValidateTokenFormUseCase(
contractAddress: String,
networkId: Network.ID,
): String {
ensure(contractAddress.isNotBlank()) {
CustomTokenFormValidationException.ContractAddress.Empty
}
val isValid = catch({ repository.validateContractAddress(contractAddress, networkId) }) {
raise(CustomTokenFormValidationException.DataError(it))
}

View file

@ -11,7 +11,9 @@ sealed class AddCustomTokenForm {
sealed class Validated : AddCustomTokenForm() {
data class ContractAddress(
data object Empty : Validated()
data class ContractAddressOnly(
val contractAddress: String,
) : Validated()

View file

@ -4,8 +4,6 @@ sealed class CustomTokenFormValidationException {
sealed class ContractAddress : CustomTokenFormValidationException() {
data object Empty : ContractAddress()
data object Invalid : ContractAddress()
}

View file

@ -92,5 +92,5 @@ sealed class StakingError {
data class DataError(val cause: Throwable) : StakingError()
data object UnknownError : StakingError()
data class UnknownError(val message: String? = null) : StakingError()
}

View file

@ -42,7 +42,8 @@ class InvalidatePendingTransactionsUseCase(
newBalancesId: Int,
pendingData: List<Pair<PendingTransaction, BalanceItem>>,
): Pair<List<BalanceItem>, List<PendingTransaction>> {
val balances = realData.associateBy { BalanceIdentity(it.groupId, it.type, it.amount, it.date) }
val balances = realData.groupBy { BalanceIdentity(it.groupId, it.type, it.amount, it.date) }
.mapValues { it.value.toMutableList() }
.toMutableMap()
val transactionsToRemove = mutableListOf<PendingTransaction>()
@ -56,28 +57,34 @@ class InvalidatePendingTransactionsUseCase(
transactionsToRemove.add(pendingTransaction)
}
balances.containsKey(key) -> {
balances[key] = balanceItem
val removed = balances[key]?.removeIf { !it.isPending } ?: false
if (removed) {
balances[key]?.add(balanceItem)
}
}
else -> {
val groupId = UUID.randomUUID().toString()
val now = DateTime.now()
balances[BalanceIdentity(groupId, BalanceType.STAKED, pendingTransaction.amount, now)] =
BalanceItem(
groupId = groupId,
type = pendingTransaction.type,
amount = pendingTransaction.amount,
rawCurrencyId = pendingTransaction.rawCurrencyId,
validatorAddress = pendingTransaction.validator?.address,
date = null,
pendingActions = emptyList(),
token = pendingTransaction.token,
isPending = true,
mutableListOf(
BalanceItem(
groupId = groupId,
type = pendingTransaction.type,
amount = pendingTransaction.amount,
rawCurrencyId = pendingTransaction.rawCurrencyId,
validatorAddress = pendingTransaction.validator?.address,
date = null,
pendingActions = emptyList(),
token = pendingTransaction.token,
isPending = true,
),
)
balances.entries.find {
it.key.type == BalanceType.STAKED &&
it.key.amount == pendingTransaction.amount &&
!it.value.isPending
!it.value.any { it.isPending }
}
?.key
?.let { balances.remove(it) }
@ -85,7 +92,7 @@ class InvalidatePendingTransactionsUseCase(
}
}
return balances.values.toList() to transactionsToRemove
return balances.values.flatten() to transactionsToRemove
}
private data class BalanceIdentity(

View file

@ -63,15 +63,9 @@ internal class CustomTokenFormModel @Inject constructor(
if (params.network.canHandleTokens) {
observeTokenFormUpdates()
} else {
modelScope.launch {
customCurrencyValidator.createCoin(
userWalletId = params.userWalletId,
networkId = params.network.id,
derivationPath = getDerivationPath(),
)
}
}
createCoin()
}
private fun getInitialState(): CustomTokenFormUM {
@ -114,6 +108,7 @@ internal class CustomTokenFormModel @Inject constructor(
}
.distinctUntilChanged()
.sample(periodMillis = 1_000)
.drop(count = 1) // Skip initial state
.onEach { formValues ->
customCurrencyValidator.validateForm(
userWalletId = params.userWalletId,
@ -153,6 +148,14 @@ internal class CustomTokenFormModel @Inject constructor(
}
}
private fun createCoin() = modelScope.launch {
customCurrencyValidator.createCoin(
userWalletId = params.userWalletId,
networkId = params.network.id,
derivationPath = getDerivationPath(),
)
}
private fun updateStateWithCurrency(
currency: CryptoCurrency,
fillForm: Boolean,

View file

@ -75,9 +75,12 @@ internal class CustomCurrencyValidator @Inject constructor(
is AddCustomTokenForm.Validated.All -> {
findOrCreateCurrency(userWalletId, networkId, derivationPath, validatedForm)
}
is AddCustomTokenForm.Validated.ContractAddress -> {
is AddCustomTokenForm.Validated.ContractAddressOnly -> {
findToken(userWalletId, networkId, derivationPath, validatedForm)
}
is AddCustomTokenForm.Validated.Empty -> {
createCoin(userWalletId, networkId, derivationPath)
}
}
}.saveInAndJoin(validateFormJobHolder)
}
@ -132,7 +135,7 @@ internal class CustomCurrencyValidator @Inject constructor(
userWalletId: UserWalletId,
networkId: Network.ID,
derivationPath: Network.DerivationPath,
validatedForm: AddCustomTokenForm.Validated.ContractAddress,
validatedForm: AddCustomTokenForm.Validated.ContractAddressOnly,
) {
updateStatus(Status.SearchingToken)

View file

@ -96,9 +96,6 @@ internal fun CustomTokenFormUM.updateWithContractAddressException(
val updatedFields = fields.mutate {
it[Field.CONTRACT_ADDRESS] = it.getValue(Field.CONTRACT_ADDRESS).copy(
error = when (exception) {
CustomTokenFormValidationException.ContractAddress.Empty -> {
null // Should not display this error
}
CustomTokenFormValidationException.ContractAddress.Invalid -> {
resourceReference(R.string.custom_token_creation_error_invalid_contract_address)
}

View file

@ -526,9 +526,12 @@ internal class MarketsTokenDetailsModel @Inject constructor(
}
private fun onListedOnClick(exchangesCount: Int) {
showBottomSheet(content = ExchangesBottomSheetContent.Loading(exchangesCount))
modelScope.launch {
showBottomSheet(content = ExchangesBottomSheetContent.Loading(exchangesCount))
// Delay to show the bottom sheet
delay(timeMillis = 800L)
val maybeExchanges = getTokenExchangesUseCase(tokenId = params.token.id)
updateExchangeBSContent(maybeExchanges = maybeExchanges, exchangesCount = exchangesCount)

View file

@ -3,11 +3,10 @@ package com.tangem.features.markets.details.impl.ui.components
import android.content.res.Configuration
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
@ -17,9 +16,6 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import com.tangem.core.ui.components.SpacerH
import com.tangem.core.ui.components.SpacerH12
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
@ -57,44 +53,37 @@ internal fun ExchangesBottomSheet(config: TangemBottomSheetConfig) {
addBottomInsets = false,
title = { Title(textResId = it.titleResId, onBackClick = config.onDismissRequest) },
content = { content ->
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(state = rememberScrollState()),
) {
Subtitle(
subtitleRes = content.subtitleResId,
volumeReference = content.volumeReference,
modifier = Modifier.padding(
start = TangemTheme.dimens.spacing16,
top = TangemTheme.dimens.spacing12,
end = TangemTheme.dimens.spacing16,
bottom = TangemTheme.dimens.spacing8,
),
)
when (content) {
is ExchangesBottomSheetContent.Content,
is ExchangesBottomSheetContent.Loading,
-> {
content.exchangeItems.fastForEach { item ->
key(item.id) {
TokenItem(state = item, isBalanceHidden = false)
}
}
}
is ExchangesBottomSheetContent.Error -> {
Error(
content = content,
modifier = Modifier
.align(alignment = Alignment.CenterHorizontally)
.padding(horizontal = 16.dp)
.weight(1f),
Box {
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(bottom = bottomBarHeight),
) {
item(key = "subtitle") {
Subtitle(
subtitleRes = content.subtitleResId,
volumeReference = content.volumeReference,
modifier = Modifier.padding(
start = TangemTheme.dimens.spacing16,
top = TangemTheme.dimens.spacing12,
end = TangemTheme.dimens.spacing16,
bottom = TangemTheme.dimens.spacing8,
),
)
}
items(
items = content.exchangeItems,
key = TokenItemState::id,
itemContent = { TokenItem(state = it, isBalanceHidden = false) },
)
}
SpacerH(bottomBarHeight)
if (content is ExchangesBottomSheetContent.Error) {
Error(
content = content,
modifier = Modifier.align(Alignment.Center),
)
}
}
},
)

View file

@ -10,6 +10,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
@ -33,7 +34,7 @@ import kotlinx.coroutines.delay
*/
@Composable
internal fun ListedOnBlock(state: ListedOnUM, modifier: Modifier = Modifier) {
Box {
Box(modifier = modifier) {
InformationBlock(
title = {
Text(
@ -44,9 +45,11 @@ internal fun ListedOnBlock(state: ListedOnUM, modifier: Modifier = Modifier) {
overflow = TextOverflow.Ellipsis,
)
},
modifier = modifier.clickable(enabled = state is ListedOnUM.Content) {
(state as? ListedOnUM.Content)?.onClick?.invoke()
},
modifier = Modifier
.clip(shape = TangemTheme.shapes.roundedCornersXMedium)
.clickable(enabled = state is ListedOnUM.Content) {
(state as? ListedOnUM.Content)?.onClick?.invoke()
},
) {
Description(
state = state,

View file

@ -93,7 +93,7 @@ internal class SendNotificationFactory constructor(
val currencyCheck = getCurrencyCheckUseCase(
userWalletId = userWalletId,
currencyStatus = cryptoCurrencyStatus,
amount = amountValue,
amount = sendingAmount,
fee = feeValue,
)
buildList {

View file

@ -72,10 +72,7 @@ internal class FeeConverter(
normalFee
} else {
when (normalFee) {
is Fee.Ethereum.Legacy -> ethereumCustomFeeConverter.convertBack(
normalFee = normalFee,
value = customValues,
)
is Fee.Ethereum -> ethereumCustomFeeConverter.convertBack(normalFee = normalFee, value = customValues)
is Fee.Bitcoin -> bitcoinCustomFeeConverter.convertBack(normalFee = normalFee, value = customValues)
is Fee.Kaspa -> kaspaCustomFeeConverter.convertBack(normalFee = normalFee, value = customValues)
else -> {

View file

@ -49,7 +49,7 @@ internal class SendFeeCustomFieldConverter(
override fun convert(value: Fee): ImmutableList<SendTextField.CustomFee> {
return when (value) {
is Fee.Ethereum.Legacy -> ethereumCustomFeeConverter.convert(value)
is Fee.Ethereum -> ethereumCustomFeeConverter.convert(value)
is Fee.Bitcoin -> bitcoinCustomFeeConverter.convert(value)
is Fee.Kaspa -> kaspaCustomFeeConverter.convert(value)
else -> persistentListOf()
@ -59,6 +59,7 @@ internal class SendFeeCustomFieldConverter(
fun onValueChange(feeSelectorState: FeeSelectorState.Content, index: Int, value: String) = feeSelectorState.copy(
customValues = when (val fee = feeSelectorState.fees.normal) {
is Fee.Ethereum -> ethereumCustomFeeConverter.onValueChange(
feeValue = fee,
customValues = feeSelectorState.customValues,
index = index,
value = value,

View file

@ -0,0 +1,24 @@
package com.tangem.features.send.impl.presentation.state.fee.custom
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.features.send.impl.presentation.state.fields.SendTextField
import kotlinx.collections.immutable.ImmutableList
/**
* Base ethereum custom fee converter
*
* @param T subtype of [Fee.Ethereum]
*
[REDACTED_AUTHOR]
*/
internal interface BaseEthereumCustomFeeConverter<T : Fee.Ethereum> : CustomFeeConverter<T> {
fun getGasLimitIndex(feeValue: T): Int
fun onValueChange(
feeValue: T,
customValues: ImmutableList<SendTextField.CustomFee>,
index: Int,
value: String,
): ImmutableList<SendTextField.CustomFee>
}

View file

@ -8,7 +8,6 @@ import com.tangem.blockchain.common.transaction.Fee
import com.tangem.common.ui.amountScreen.utils.getFiatReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.utils.parseBigDecimal
import com.tangem.core.ui.utils.parseToBigDecimal
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.features.send.impl.R
@ -18,203 +17,119 @@ import com.tangem.features.send.impl.presentation.state.fields.SendTextField
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
import com.tangem.utils.Provider
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import java.math.RoundingMode
internal class EthereumCustomFeeConverter(
private val clickIntents: SendClickIntents,
private val stateRouterProvider: Provider<StateRouter>,
private val appCurrencyProvider: Provider<AppCurrency>,
private val feeCryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus?>,
) : CustomFeeConverter<Fee.Ethereum.Legacy> {
) : BaseEthereumCustomFeeConverter<Fee.Ethereum> {
override fun convert(value: Fee.Ethereum.Legacy): ImmutableList<SendTextField.CustomFee> {
val feeValue = value.amount.value
val feeCurrency = feeCryptoCurrencyStatusProvider()?.value
return persistentListOf(
SendTextField.CustomFee(
value = feeValue?.parseBigDecimal(value.amount.decimals).orEmpty(),
decimals = value.amount.decimals,
symbol = value.amount.currencySymbol,
onValueChange = { clickIntents.onCustomFeeValueChange(FEE_AMOUNT, it) },
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Next,
keyboardType = KeyboardType.Number,
),
title = resourceReference(R.string.send_max_fee),
footer = resourceReference(R.string.send_custom_amount_fee_footer),
label = getFiatReference(
rate = feeCurrency?.fiatRate,
value = feeValue,
appCurrency = appCurrencyProvider(),
),
keyboardActions = KeyboardActions(),
),
SendTextField.CustomFee(
value = value.gasPrice.toBigDecimal().movePointLeft(GIGA_DECIMALS).parseBigDecimal(GIGA_DECIMALS),
decimals = GIGA_DECIMALS,
symbol = ETHEREUM_GAS_UNIT,
title = resourceReference(R.string.send_gas_price),
footer = resourceReference(R.string.send_gas_price_footer),
onValueChange = { clickIntents.onCustomFeeValueChange(GAS_PRICE, it) },
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Next,
keyboardType = KeyboardType.Number,
),
keyboardActions = KeyboardActions(),
),
SendTextField.CustomFee(
value = value.gasLimit.toString(),
decimals = GAS_DECIMALS,
symbol = "",
title = resourceReference(R.string.send_gas_limit),
footer = resourceReference(R.string.send_gas_limit_footer),
onValueChange = { clickIntents.onCustomFeeValueChange(GAS_LIMIT, it) },
keyboardOptions = KeyboardOptions(
imeAction = if (
checkExceedBalance(
feeBalance = feeCurrency?.amount,
feeAmount = feeValue,
)
) {
ImeAction.None
} else {
ImeAction.Done
},
keyboardType = KeyboardType.Number,
),
keyboardActions = KeyboardActions(
onDone = { clickIntents.onNextClick(stateRouterProvider().isEditState) },
),
),
)
private val feeCurrency: CryptoCurrencyStatus.Value?
get() = feeCryptoCurrencyStatusProvider()?.value
private val legacyFeeConverter = EthereumLegacyCustomFeeConverter(
clickIntents = clickIntents,
appCurrencyProvider = appCurrencyProvider,
feeCryptoCurrencyStatusProvider = feeCryptoCurrencyStatusProvider,
)
private val eipFeeConverter = EthereumEIPCustomFeeConverter(
clickIntents = clickIntents,
appCurrencyProvider = appCurrencyProvider,
feeCryptoCurrencyStatusProvider = feeCryptoCurrencyStatusProvider,
)
override fun convert(value: Fee.Ethereum): ImmutableList<SendTextField.CustomFee> {
return buildList {
convertFeeValue(value).let(::add)
when (value) {
is Fee.Ethereum.EIP1559 -> eipFeeConverter.convert(value)
is Fee.Ethereum.Legacy -> legacyFeeConverter.convert(value)
}
.let(::addAll)
convertGasLimitValue(value).let(::add)
}
.toImmutableList()
}
override fun convertBack(
normalFee: Fee.Ethereum.Legacy,
value: ImmutableList<SendTextField.CustomFee>,
): Fee.Ethereum.Legacy {
val feeAmount = value[FEE_AMOUNT].value.parseToBigDecimal(value[FEE_AMOUNT].decimals)
val gasPrice = value[GAS_PRICE].value.parseToBigDecimal(GAS_DECIMALS).toBigInteger()
val gasLimit = value[GAS_LIMIT].value.parseToBigDecimal(GAS_DECIMALS).toBigInteger()
return normalFee.copy(
amount = normalFee.amount.copy(value = feeAmount),
gasPrice = gasPrice,
gasLimit = gasLimit,
)
override fun convertBack(normalFee: Fee.Ethereum, value: ImmutableList<SendTextField.CustomFee>): Fee.Ethereum {
return when (normalFee) {
is Fee.Ethereum.EIP1559 -> eipFeeConverter.convertBack(normalFee = normalFee, value = value)
is Fee.Ethereum.Legacy -> legacyFeeConverter.convertBack(normalFee = normalFee, value = value)
}
}
fun onValueChange(
override fun getGasLimitIndex(feeValue: Fee.Ethereum): Int {
return when (feeValue) {
is Fee.Ethereum.EIP1559 -> eipFeeConverter.getGasLimitIndex(feeValue)
is Fee.Ethereum.Legacy -> legacyFeeConverter.getGasLimitIndex(feeValue)
}
}
override fun onValueChange(
feeValue: Fee.Ethereum,
customValues: ImmutableList<SendTextField.CustomFee>,
index: Int,
value: String,
): ImmutableList<SendTextField.CustomFee> {
val mutableCustomValues = customValues.toMutableList()
return mutableCustomValues.apply {
when (index) {
FEE_AMOUNT -> setOnAmountChange(value, index)
GAS_PRICE -> setOnGasPriceChange(value, index)
else -> setOnGasLimitChange(value, index)
}
}.toImmutableList()
}
private fun MutableList<SendTextField.CustomFee>.setEmpty(index: Int) {
set(index, this[index].copy(value = ""))
}
private fun MutableList<SendTextField.CustomFee>.setOnAmountChange(value: String, index: Int) {
val gasLimit = this[GAS_LIMIT].value.parseToBigDecimal(this[GAS_LIMIT].decimals)
if (value.isBlank()) {
setEmpty(FEE_AMOUNT)
setEmpty(GAS_PRICE)
} else {
val newFeeAmountDecimal = value.parseToBigDecimal(this[FEE_AMOUNT].decimals)
val newFeeAmount = newFeeAmountDecimal.movePointRight(this[GAS_PRICE].decimals) // from ETH to GWEI
val newGasPrice = newFeeAmount.divide(gasLimit, this[GAS_PRICE].decimals, RoundingMode.HALF_UP)
set(GAS_PRICE, this[GAS_PRICE].copy(value = newGasPrice.parseBigDecimal(this[GAS_PRICE].decimals)))
set(
index,
this[index].copy(
value = value,
label = getFiatReference(
rate = feeCryptoCurrencyStatusProvider()?.value?.fiatRate,
value = newFeeAmountDecimal,
appCurrency = appCurrencyProvider(),
),
),
)
return when (feeValue) {
is Fee.Ethereum.EIP1559 -> eipFeeConverter.onValueChange(feeValue, customValues, index, value)
is Fee.Ethereum.Legacy -> legacyFeeConverter.onValueChange(feeValue, customValues, index, value)
}
}
private fun MutableList<SendTextField.CustomFee>.setOnGasPriceChange(value: String, index: Int) {
val gasLimit = this[GAS_LIMIT].value.parseToBigDecimal(this[GAS_LIMIT].decimals)
if (value.isBlank()) {
setEmpty(FEE_AMOUNT)
setEmpty(GAS_PRICE)
} else {
val newGasPrice = value.parseToBigDecimal(this[GAS_PRICE].decimals)
.movePointLeft(this[GAS_PRICE].decimals) // from GWEI to ETH
val newFeeAmount = gasLimit * newGasPrice
set(
FEE_AMOUNT,
this[FEE_AMOUNT].copy(
value = newFeeAmount.parseBigDecimal(this[FEE_AMOUNT].decimals),
label = getFiatReference(
rate = feeCryptoCurrencyStatusProvider()?.value?.fiatRate,
value = newFeeAmount,
appCurrency = appCurrencyProvider(),
),
),
)
set(index, this[index].copy(value = value))
}
private fun convertFeeValue(value: Fee.Ethereum): SendTextField.CustomFee {
val feeValue = value.amount.value
return SendTextField.CustomFee(
value = feeValue?.parseBigDecimal(value.amount.decimals).orEmpty(),
decimals = value.amount.decimals,
symbol = value.amount.currencySymbol,
onValueChange = { clickIntents.onCustomFeeValueChange(FEE_AMOUNT, it) },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next, keyboardType = KeyboardType.Number),
title = resourceReference(R.string.send_max_fee),
footer = resourceReference(R.string.send_custom_amount_fee_footer),
label = getFiatReference(
rate = feeCurrency?.fiatRate,
value = feeValue,
appCurrency = appCurrencyProvider(),
),
keyboardActions = KeyboardActions(),
)
}
private fun MutableList<SendTextField.CustomFee>.setOnGasLimitChange(value: String, index: Int) {
if (value.isBlank()) {
setEmpty(FEE_AMOUNT)
setEmpty(GAS_LIMIT)
} else {
val newGasLimit = value.parseToBigDecimal(this[GAS_LIMIT].decimals)
val gasPrice = this[GAS_PRICE].value.parseToBigDecimal(this[GAS_PRICE].decimals)
.movePointLeft(this[GAS_PRICE].decimals) // from GWEI to ETH
val newFeeAmount = newGasLimit * gasPrice
set(
FEE_AMOUNT,
this[FEE_AMOUNT].copy(
value = newFeeAmount.parseBigDecimal(this[FEE_AMOUNT].decimals),
label = getFiatReference(
rate = feeCryptoCurrencyStatusProvider()?.value?.fiatRate,
value = newFeeAmount,
appCurrency = appCurrencyProvider(),
),
),
)
val isNotExceedBalance = checkExceedBalance(
feeBalance = feeCryptoCurrencyStatusProvider()?.value?.amount,
feeAmount = newFeeAmount,
)
set(
index,
this[index].copy(
value = value,
keyboardOptions = KeyboardOptions(
imeAction = if (!isNotExceedBalance) ImeAction.None else ImeAction.Done,
keyboardType = KeyboardType.Number,
),
),
)
}
private fun convertGasLimitValue(value: Fee.Ethereum): SendTextField.CustomFee {
val isExceedBalance = checkExceedBalance(feeBalance = feeCurrency?.amount, feeAmount = value.amount.value)
return SendTextField.CustomFee(
value = value.gasLimit.toString(),
decimals = GAS_DECIMALS,
symbol = "",
title = resourceReference(R.string.send_gas_limit),
footer = resourceReference(R.string.send_gas_limit_footer),
onValueChange = { clickIntents.onCustomFeeValueChange(getGasLimitIndex(value), it) },
keyboardOptions = KeyboardOptions(
imeAction = if (isExceedBalance) ImeAction.None else ImeAction.Done,
keyboardType = KeyboardType.Number,
),
keyboardActions = KeyboardActions(
onDone = { clickIntents.onNextClick(stateRouterProvider().isEditState) },
),
)
}
companion object {
private const val ETHEREUM_GAS_UNIT = "GWEI"
private const val GIGA_DECIMALS = 9
private const val FEE_AMOUNT = 0
private const val GAS_PRICE = 1
private const val GAS_LIMIT = 2
private const val GAS_DECIMALS = 0
const val ETHEREUM_GAS_UNIT = "GWEI"
const val GIGA_DECIMALS = 9
const val GAS_DECIMALS = 0
const val FEE_AMOUNT = 0
}
}
internal fun MutableList<SendTextField.CustomFee>.setEmpty(index: Int) {
set(index, this[index].copy(value = ""))
}

View file

@ -0,0 +1,196 @@
package com.tangem.features.send.impl.presentation.state.fee.custom
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.common.ui.amountScreen.utils.getFiatReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.utils.parseBigDecimal
import com.tangem.core.ui.utils.parseToBigDecimal
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.features.send.impl.R
import com.tangem.features.send.impl.presentation.state.fee.checkExceedBalance
import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.ETHEREUM_GAS_UNIT
import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.FEE_AMOUNT
import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.GAS_DECIMALS
import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.GIGA_DECIMALS
import com.tangem.features.send.impl.presentation.state.fields.SendTextField
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
import com.tangem.utils.Provider
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import java.math.RoundingMode
internal class EthereumEIPCustomFeeConverter(
private val clickIntents: SendClickIntents,
private val appCurrencyProvider: Provider<AppCurrency>,
private val feeCryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus?>,
) : BaseEthereumCustomFeeConverter<Fee.Ethereum.EIP1559> {
override fun convert(value: Fee.Ethereum.EIP1559): ImmutableList<SendTextField.CustomFee> {
return persistentListOf(
SendTextField.CustomFee(
value = value.maxFeePerGas.toBigDecimal().movePointLeft(GIGA_DECIMALS).parseBigDecimal(GIGA_DECIMALS),
decimals = GIGA_DECIMALS,
symbol = ETHEREUM_GAS_UNIT,
title = resourceReference(R.string.send_custom_evm_max_fee),
footer = resourceReference(R.string.send_custom_evm_max_fee_footer),
onValueChange = { clickIntents.onCustomFeeValueChange(MAX_FEE, it) },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next, keyboardType = KeyboardType.Number),
keyboardActions = KeyboardActions(),
),
SendTextField.CustomFee(
value = value.priorityFee.toBigDecimal().movePointLeft(GIGA_DECIMALS).parseBigDecimal(GIGA_DECIMALS),
decimals = GIGA_DECIMALS,
symbol = ETHEREUM_GAS_UNIT,
title = resourceReference(R.string.send_custom_evm_priority_fee),
footer = resourceReference(R.string.send_custom_evm_priority_fee_footer),
onValueChange = { clickIntents.onCustomFeeValueChange(PRIORITY_FEE, it) },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next, keyboardType = KeyboardType.Number),
keyboardActions = KeyboardActions(),
),
)
}
override fun convertBack(
normalFee: Fee.Ethereum.EIP1559,
value: ImmutableList<SendTextField.CustomFee>,
): Fee.Ethereum.EIP1559 {
val feeAmount = value[FEE_AMOUNT].value.parseToBigDecimal(value[FEE_AMOUNT].decimals)
val maxFee = value[MAX_FEE].value.parseToBigDecimal(GAS_DECIMALS).toBigInteger()
val priorityFee = value[PRIORITY_FEE].value.parseToBigDecimal(GAS_DECIMALS).toBigInteger()
val gasLimit = value[GAS_LIMIT].value.parseToBigDecimal(GAS_DECIMALS).toBigInteger()
return normalFee.copy(
amount = normalFee.amount.copy(value = feeAmount),
maxFeePerGas = maxFee,
priorityFee = priorityFee,
gasLimit = gasLimit,
)
}
override fun getGasLimitIndex(feeValue: Fee.Ethereum.EIP1559): Int = GAS_LIMIT
override fun onValueChange(
feeValue: Fee.Ethereum.EIP1559,
customValues: ImmutableList<SendTextField.CustomFee>,
index: Int,
value: String,
): ImmutableList<SendTextField.CustomFee> {
val mutableCustomValues = customValues.toMutableList()
return mutableCustomValues.apply {
when (index) {
FEE_AMOUNT -> setOnAmountChange(value, index)
MAX_FEE -> setOnMaxFeeChange(value, index)
GAS_LIMIT -> setOnGasLimitChange(value, index)
else -> set(index, this[index].copy(value = value))
}
}.toImmutableList()
}
private fun MutableList<SendTextField.CustomFee>.setOnAmountChange(value: String, index: Int) {
val gasLimit = this[GAS_LIMIT].value.parseToBigDecimal(this[GAS_LIMIT].decimals)
if (value.isBlank()) {
setEmpty(FEE_AMOUNT)
setEmpty(MAX_FEE)
} else {
val newFeeAmountDecimal = value.parseToBigDecimal(this[FEE_AMOUNT].decimals)
val newFeeAmount = newFeeAmountDecimal.movePointRight(GIGA_DECIMALS) // from ETH to GWEI
val newMaxFee = newFeeAmount.divide(gasLimit, this[MAX_FEE].decimals, RoundingMode.HALF_UP)
set(
index = MAX_FEE,
element = this[MAX_FEE].copy(value = newMaxFee.parseBigDecimal(this[MAX_FEE].decimals)),
)
set(
index = index,
element = this[index].copy(
value = value,
label = getFiatReference(
rate = feeCryptoCurrencyStatusProvider()?.value?.fiatRate,
value = newFeeAmountDecimal,
appCurrency = appCurrencyProvider(),
),
),
)
}
}
private fun MutableList<SendTextField.CustomFee>.setOnMaxFeeChange(value: String, index: Int) {
val gasLimit = this[GAS_LIMIT].value.parseToBigDecimal(this[GAS_LIMIT].decimals)
if (value.isBlank()) {
setEmpty(FEE_AMOUNT)
setEmpty(MAX_FEE)
} else {
val newMaxFee = value.parseToBigDecimal(this[MAX_FEE].decimals).movePointLeft(this[MAX_FEE].decimals)
val newFeeAmount = gasLimit * newMaxFee
set(
FEE_AMOUNT,
this[FEE_AMOUNT].copy(
value = newFeeAmount.parseBigDecimal(this[FEE_AMOUNT].decimals),
label = getFiatReference(
rate = feeCryptoCurrencyStatusProvider()?.value?.fiatRate,
value = newFeeAmount,
appCurrency = appCurrencyProvider(),
),
),
)
set(index, this[index].copy(value = value))
}
}
private fun MutableList<SendTextField.CustomFee>.setOnGasLimitChange(value: String, index: Int) {
if (value.isBlank()) {
setEmpty(FEE_AMOUNT)
setEmpty(GAS_LIMIT)
} else {
val newGasLimit = value.parseToBigDecimal(this[GAS_LIMIT].decimals)
val maxFee = this[MAX_FEE].value.parseToBigDecimal(this[MAX_FEE].decimals)
.movePointLeft(this[MAX_FEE].decimals) // from GWEI to ETH
val newFeeAmount = newGasLimit * maxFee
set(
index = FEE_AMOUNT,
element = this[FEE_AMOUNT].copy(
value = newFeeAmount.parseBigDecimal(this[FEE_AMOUNT].decimals),
label = getFiatReference(
rate = feeCryptoCurrencyStatusProvider()?.value?.fiatRate,
value = newFeeAmount,
appCurrency = appCurrencyProvider(),
),
),
)
val isNotExceedBalance = checkExceedBalance(
feeBalance = feeCryptoCurrencyStatusProvider()?.value?.amount,
feeAmount = newFeeAmount,
)
set(
index = index,
element = this[index].copy(
value = value,
keyboardOptions = KeyboardOptions(
imeAction = if (!isNotExceedBalance) ImeAction.None else ImeAction.Done,
keyboardType = KeyboardType.Number,
),
),
)
}
}
private companion object {
const val MAX_FEE = 1
const val PRIORITY_FEE = 2
const val GAS_LIMIT = 3
}
}

View file

@ -0,0 +1,179 @@
package com.tangem.features.send.impl.presentation.state.fee.custom
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.common.ui.amountScreen.utils.getFiatReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.utils.parseBigDecimal
import com.tangem.core.ui.utils.parseToBigDecimal
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.features.send.impl.R
import com.tangem.features.send.impl.presentation.state.fee.checkExceedBalance
import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.ETHEREUM_GAS_UNIT
import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.FEE_AMOUNT
import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.GAS_DECIMALS
import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.GIGA_DECIMALS
import com.tangem.features.send.impl.presentation.state.fields.SendTextField
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
import com.tangem.utils.Provider
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import java.math.RoundingMode
internal class EthereumLegacyCustomFeeConverter(
private val clickIntents: SendClickIntents,
private val appCurrencyProvider: Provider<AppCurrency>,
private val feeCryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus?>,
) : BaseEthereumCustomFeeConverter<Fee.Ethereum.Legacy> {
override fun convert(value: Fee.Ethereum.Legacy): ImmutableList<SendTextField.CustomFee> {
return persistentListOf(
SendTextField.CustomFee(
value = value.gasPrice.toBigDecimal().movePointLeft(GIGA_DECIMALS).parseBigDecimal(GIGA_DECIMALS),
decimals = GIGA_DECIMALS,
symbol = ETHEREUM_GAS_UNIT,
title = resourceReference(R.string.send_gas_price),
footer = resourceReference(R.string.send_gas_price_footer),
onValueChange = { clickIntents.onCustomFeeValueChange(GAS_PRICE, it) },
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Next,
keyboardType = KeyboardType.Number,
),
keyboardActions = KeyboardActions(),
),
)
}
override fun convertBack(
normalFee: Fee.Ethereum.Legacy,
value: ImmutableList<SendTextField.CustomFee>,
): Fee.Ethereum.Legacy {
val feeAmount = value[FEE_AMOUNT].value.parseToBigDecimal(value[FEE_AMOUNT].decimals)
val gasPrice = value[GAS_PRICE].value.parseToBigDecimal(GAS_DECIMALS).toBigInteger()
val gasLimit = value[GAS_LIMIT].value.parseToBigDecimal(GAS_DECIMALS).toBigInteger()
return normalFee.copy(
amount = normalFee.amount.copy(value = feeAmount),
gasPrice = gasPrice,
gasLimit = gasLimit,
)
}
override fun getGasLimitIndex(feeValue: Fee.Ethereum.Legacy): Int = GAS_LIMIT
override fun onValueChange(
feeValue: Fee.Ethereum.Legacy,
customValues: ImmutableList<SendTextField.CustomFee>,
index: Int,
value: String,
): ImmutableList<SendTextField.CustomFee> {
val mutableCustomValues = customValues.toMutableList()
return mutableCustomValues.apply {
when (index) {
FEE_AMOUNT -> setOnAmountChange(value, index)
GAS_PRICE -> setOnGasPriceChange(value, index)
GAS_LIMIT -> setOnGasLimitChange(value, index)
else -> set(index, this[index].copy(value = value))
}
}.toImmutableList()
}
private fun MutableList<SendTextField.CustomFee>.setOnAmountChange(value: String, index: Int) {
val gasLimit = this[GAS_LIMIT].value.parseToBigDecimal(this[GAS_LIMIT].decimals)
if (value.isBlank()) {
setEmpty(FEE_AMOUNT)
setEmpty(GAS_PRICE)
} else {
val newFeeAmountDecimal = value.parseToBigDecimal(this[FEE_AMOUNT].decimals)
val newFeeAmount = newFeeAmountDecimal.movePointRight(this[GAS_PRICE].decimals) // from ETH to GWEI
val newGasPrice = newFeeAmount.divide(gasLimit, this[GAS_PRICE].decimals, RoundingMode.HALF_UP)
set(GAS_PRICE, this[GAS_PRICE].copy(value = newGasPrice.parseBigDecimal(this[GAS_PRICE].decimals)))
set(
index,
this[index].copy(
value = value,
label = getFiatReference(
rate = feeCryptoCurrencyStatusProvider()?.value?.fiatRate,
value = newFeeAmountDecimal,
appCurrency = appCurrencyProvider(),
),
),
)
}
}
private fun MutableList<SendTextField.CustomFee>.setOnGasPriceChange(value: String, index: Int) {
val gasLimit = this[GAS_LIMIT].value.parseToBigDecimal(this[GAS_LIMIT].decimals)
if (value.isBlank()) {
setEmpty(FEE_AMOUNT)
setEmpty(GAS_PRICE)
} else {
val newGasPrice = value.parseToBigDecimal(this[GAS_PRICE].decimals)
.movePointLeft(this[GAS_PRICE].decimals) // from GWEI to ETH
val newFeeAmount = gasLimit * newGasPrice
set(
FEE_AMOUNT,
this[FEE_AMOUNT].copy(
value = newFeeAmount.parseBigDecimal(this[FEE_AMOUNT].decimals),
label = getFiatReference(
rate = feeCryptoCurrencyStatusProvider()?.value?.fiatRate,
value = newFeeAmount,
appCurrency = appCurrencyProvider(),
),
),
)
set(index, this[index].copy(value = value))
}
}
private fun MutableList<SendTextField.CustomFee>.setOnGasLimitChange(value: String, index: Int) {
if (value.isBlank()) {
setEmpty(FEE_AMOUNT)
setEmpty(GAS_LIMIT)
} else {
val newGasLimit = value.parseToBigDecimal(this[GAS_LIMIT].decimals)
val gasPrice = this[GAS_PRICE].value.parseToBigDecimal(this[GAS_PRICE].decimals)
.movePointLeft(this[GAS_PRICE].decimals) // from GWEI to ETH
val newFeeAmount = newGasLimit * gasPrice
set(
index = FEE_AMOUNT,
element = this[FEE_AMOUNT].copy(
value = newFeeAmount.parseBigDecimal(this[FEE_AMOUNT].decimals),
label = getFiatReference(
rate = feeCryptoCurrencyStatusProvider()?.value?.fiatRate,
value = newFeeAmount,
appCurrency = appCurrencyProvider(),
),
),
)
val isNotExceedBalance = checkExceedBalance(
feeBalance = feeCryptoCurrencyStatusProvider()?.value?.amount,
feeAmount = newFeeAmount,
)
set(
index = index,
element = this[index].copy(
value = value,
keyboardOptions = KeyboardOptions(
imeAction = if (!isNotExceedBalance) ImeAction.None else ImeAction.Done,
keyboardType = KeyboardType.Number,
),
),
)
}
}
private companion object {
const val GAS_PRICE = 1
const val GAS_LIMIT = 2
}
}

View file

@ -2,6 +2,7 @@ package com.tangem.features.staking.impl.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.domain.staking.model.stakekit.StakingError
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
internal sealed class StakingAnalyticsEvents(
@ -147,14 +148,18 @@ internal sealed class StakingAnalyticsEvents(
data object ButtonExplore : StakingAnalyticsEvents(event = "Button - Explore")
data class StakingError(
data class StakekitError(
val token: String,
val errorType: String,
val stakeKitError: StakingError,
) : StakingAnalyticsEvents(
event = "Errors",
params = mapOf(
AnalyticsParam.TOKEN_PARAM to token,
AnalyticsParam.ERROR_DESCRIPTION to errorType,
AnalyticsParam.ERROR_TYPE to if (stakeKitError is StakingError.UnknownError) {
stakeKitError.message ?: "Unknown"
} else {
stakeKitError.javaClass.simpleName
},
),
)

View file

@ -69,9 +69,9 @@ internal class YieldBalancesConverter(
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data
val rewards = yieldBalance?.balance?.items
?.filter { it.type == BalanceType.REWARDS }
?.filter { it.type == BalanceType.REWARDS && !it.amount.isZero() }
val isActionable = rewards?.all { it.pendingActions.isNotEmpty() } == true
val isActionable = rewards?.any { it.pendingActions.isNotEmpty() } == true
val isRewardsClaimable = rewards?.isNotEmpty() == true
val isSolana = isSolana(cryptoCurrencyStatus.currency.network.id.value)

View file

@ -135,7 +135,7 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor(
}
if (result.isNullOrEmpty()) {
onStakingFeeError(StakingError.UnknownError)
onStakingFeeError(StakingError.UnknownError())
return
}

View file

@ -87,7 +87,7 @@ internal class StakingTransactionSender @AssistedInject constructor(
)
if (fullTransactionsData.isNullOrEmpty()) {
onConstructError(StakingError.UnknownError)
onConstructError(StakingError.UnknownError())
return
}
@ -202,9 +202,9 @@ internal class StakingTransactionSender @AssistedInject constructor(
),
).getOrElse {
analyticsEventHandler.send(
StakingAnalyticsEvents.StakingError(
token = state.cryptoCurrencyName,
errorType = it.javaClass.simpleName,
StakingAnalyticsEvents.StakekitError(
token = state.cryptoCurrencySymbol,
stakeKitError = it,
),
)
onConstructError(it)
@ -260,9 +260,9 @@ internal class StakingTransactionSender @AssistedInject constructor(
)
.onLeft { error ->
analyticsEventHandler.send(
StakingAnalyticsEvents.StakingError(
token = stateController.value.cryptoCurrencyName,
errorType = error.javaClass.simpleName,
StakingAnalyticsEvents.StakekitError(
token = stateController.value.cryptoCurrencySymbol,
stakeKitError = error,
),
)
saveUnsubmittedHashUseCase.invoke(

View file

@ -10,10 +10,8 @@ import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.features.staking.impl.R
import com.tangem.features.staking.impl.presentation.state.FeeState
import com.tangem.features.staking.impl.presentation.state.StakingStates
import com.tangem.features.staking.impl.presentation.state.StakingUiState
import com.tangem.features.staking.impl.presentation.state.utils.getRewardSchedule
import com.tangem.features.staking.impl.presentation.state.*
import com.tangem.features.staking.impl.presentation.state.utils.getRewardScheduleText
import com.tangem.utils.transformer.Transformer
internal class SetConfirmationStateLoadingTransformer(
@ -45,9 +43,10 @@ internal class SetConfirmationStateLoadingTransformer(
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
)
val rewardSchedule = getRewardSchedule(
yield.metadata.rewardSchedule,
cryptoCurrency.network.id.value,
val rewardSchedule = getRewardScheduleText(
rewardSchedule = yield.metadata.rewardSchedule,
networkId = cryptoCurrency.network.id.value,
decapitalize = true,
)
return if (isEnterAction && amountDecimal != null && rewardSchedule != null) {
resourceReference(

View file

@ -20,7 +20,7 @@ import com.tangem.features.staking.impl.presentation.state.*
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.state.utils.getRewardSchedule
import com.tangem.features.staking.impl.presentation.state.utils.getRewardScheduleText
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
import com.tangem.lib.crypto.BlockchainUtils.isPolkadot
import com.tangem.utils.Provider
@ -192,7 +192,11 @@ internal class SetInitialDataStateTransformer(
}
private fun createRewardScheduleItem(): RoundedListWithDividersItemData? {
val endTextReference = getRewardScheduleText() ?: return null
val endTextReference = getRewardScheduleText(
rewardSchedule = yield.metadata.rewardSchedule,
networkId = cryptoCurrencyStatusProvider().currency.network.id.value,
decapitalize = false,
) ?: return null
return RoundedListWithDividersItemData(
id = R.string.staking_details_reward_schedule,
@ -207,7 +211,9 @@ internal class SetInitialDataStateTransformer(
}
private fun getAprRange(validators: List<Yield.Validator>): TextReference {
val aprValues = validators.mapNotNull { it.apr }
val aprValues = validators
.filter { it.preferred }
.mapNotNull { it.apr }
val minApr = aprValues.min()
val maxApr = aprValues.max()
@ -221,18 +227,6 @@ internal class SetInitialDataStateTransformer(
return resourceReference(R.string.common_range, wrappedList(formattedMinApr, formattedMaxApr))
}
private fun getRewardScheduleText(): TextReference? {
val rewardSchedule = getRewardSchedule(
yield.metadata.rewardSchedule,
cryptoCurrencyStatusProvider().currency.network.id.value,
) ?: return null
return resourceReference(
R.string.staking_reward_schedule_each,
wrappedList(rewardSchedule),
)
}
private companion object {
val EQUALITY_THRESHOLD = BigDecimal(1E-10)

View file

@ -51,7 +51,7 @@ internal class ShowApprovalBottomSheetTransformer(
data = GiveTxPermissionState.ReadyForRequest(
currency = cryptoCurrency.symbol,
amount = amountState.amountTextField.value,
approveType = ApproveType.LIMITED,
approveType = ApproveType.UNLIMITED,
walletAddress = walletAddress,
spenderAddress = validatorAddress,
fee = resourceReference(
@ -71,6 +71,7 @@ internal class ShowApprovalBottomSheetTransformer(
formatArgs = wrappedList(cryptoCurrency.symbol),
),
dialogText = resourceReference(R.string.give_permission_staking_footer),
footerText = resourceReference(R.string.staking_give_permission_fee_footer),
onChangeApproveType = prevState.clickIntents::onApproveTypeChange,
),
onCancel = onDismiss,

View file

@ -16,23 +16,45 @@ private data object StakingRewardSchedule {
val SOLANA_SCHEDULE = 2 to 3
}
internal fun getRewardSchedule(schedule: Yield.Metadata.RewardSchedule, networkId: String): TextReference? =
when (schedule) {
internal fun getRewardScheduleText(
rewardSchedule: Yield.Metadata.RewardSchedule,
networkId: String,
decapitalize: Boolean,
): TextReference? {
return when (rewardSchedule) {
Yield.Metadata.RewardSchedule.WEEK -> resourceReference(
id = R.string.staking_reward_schedule_week,
decapitalize = decapitalize,
)
Yield.Metadata.RewardSchedule.HOUR -> resourceReference(
id = R.string.staking_reward_schedule_hour,
decapitalize = decapitalize,
)
Yield.Metadata.RewardSchedule.DAY -> resourceReference(
id = R.string.staking_reward_schedule_day,
decapitalize = decapitalize,
)
Yield.Metadata.RewardSchedule.MONTH -> resourceReference(
id = R.string.staking_reward_schedule_month,
decapitalize = decapitalize,
)
Yield.Metadata.RewardSchedule.BLOCK,
Yield.Metadata.RewardSchedule.EPOCH,
Yield.Metadata.RewardSchedule.ERA,
-> getCustomRewardSchedule(networkId)
Yield.Metadata.RewardSchedule.WEEK -> resourceReference(R.string.common_week)
Yield.Metadata.RewardSchedule.HOUR -> resourceReference(R.string.common_hour)
Yield.Metadata.RewardSchedule.DAY -> pluralReference(R.plurals.common_days_no_param, count = 1)
Yield.Metadata.RewardSchedule.MONTH -> resourceReference(R.string.common_month)
Yield.Metadata.RewardSchedule.UNKNOWN -> null
-> getCustomRewardSchedule(
networkId = networkId,
decapitalize = decapitalize,
)
else -> null
}
}
private fun getCustomRewardSchedule(networkId: String): TextReference? {
private fun getCustomRewardSchedule(networkId: String, decapitalize: Boolean = false): TextReference? {
return when {
isSolana(networkId) -> {
combinedReference(
resourceReference(id = R.string.staking_reward_schedule_each_plural, decapitalize = decapitalize),
stringReference(NON_BREAKING_SPACE.toString()),
stringReference("${SOLANA_SCHEDULE.first}$MINUS${SOLANA_SCHEDULE.second}$NON_BREAKING_SPACE"),
pluralReference(
id = R.plurals.common_days_no_param,
@ -42,11 +64,13 @@ private fun getCustomRewardSchedule(networkId: String): TextReference? {
}
isCosmos(networkId) -> {
combinedReference(
resourceReference(id = R.string.staking_reward_schedule_each_plural, decapitalize = decapitalize),
stringReference(NON_BREAKING_SPACE.toString()),
stringReference("${COSMOS_SCHEDULE.first}$MINUS${COSMOS_SCHEDULE.second}$NON_BREAKING_SPACE"),
resourceReference(R.string.common_second_no_param),
)
}
isTron(networkId) -> pluralReference(R.plurals.common_days_no_param, count = 1)
isTron(networkId) -> resourceReference(id = R.string.staking_reward_schedule_day, decapitalize = decapitalize)
else -> null
}
}

View file

@ -55,6 +55,7 @@ internal fun StakingClaimRewardsValidatorContent(
.roundedShapeItemDecoration(index, state.rewards.lastIndex, false)
.background(TangemTheme.colors.background.action)
.clickable(
enabled = item.pendingActions.isNotEmpty(),
onClick = {
clickIntents.onActiveStake(item)
},

View file

@ -244,9 +244,9 @@ internal class StakingViewModel @Inject constructor(
},
onStakingFeeError = { error ->
analyticsEventHandler.send(
StakingAnalyticsEvents.StakingError(
StakingAnalyticsEvents.StakekitError(
value.cryptoCurrencySymbol,
error.javaClass.simpleName,
error,
),
)
stateController.update(AddStakingErrorTransformer())
@ -283,9 +283,9 @@ internal class StakingViewModel @Inject constructor(
onConstructError = { error ->
Timber.e(error.toString())
analyticsEventHandler.send(
StakingAnalyticsEvents.StakingError(
StakingAnalyticsEvents.StakekitError(
token = value.cryptoCurrencySymbol,
errorType = error.javaClass.simpleName,
stakeKitError = error,
),
)
stakingEventFactory.createStakingErrorAlert(error)

View file

@ -169,14 +169,15 @@ internal class DefaultSwapRepository(
return withContext(coroutineDispatcher.io) {
either {
catch(
{
block = {
exchangeStatusConverter.convert(
tangemExpressApi
.getExchangeStatus(txId)
.getOrThrow(),
)
},
{
catch = {
Timber.e("getExchangeStatus error: $it")
raise(UnknownError(it.message))
},
)

View file

@ -9,7 +9,7 @@ internal class ExchangeStatusConverter : Converter<ExchangeStatusResponse, Excha
override fun convert(value: ExchangeStatusResponse): ExchangeStatusModel {
return ExchangeStatusModel(
providerId = value.providerId,
status = ExchangeStatus.values().firstOrNull {
status = ExchangeStatus.entries.firstOrNull {
it.name.lowercase() == value.status.name.lowercase()
},
txId = value.externalTxId,

View file

@ -24,4 +24,5 @@ enum class ExchangeStatus {
Cancelled,
TxFailed,
Unknown,
Paused,
}

View file

@ -1192,6 +1192,7 @@ internal class StateBuilder(
formatArgs = wrappedList(providerName, permissionDataState.currency),
),
dialogText = resourceReference(R.string.swapping_approve_information_text),
footerText = resourceReference(R.string.swap_give_permission_fee_footer),
)
}
}

View file

@ -155,7 +155,7 @@ internal object TokenDetailsPreviewData {
onStakeClicked = {},
)
val stakedBlock = StakingBlockUM.Staked(
val stakingBalanceBlock = StakingBlockUM.Staked(
cryptoValue = stringReference("5 SOL"),
fiatValue = stringReference("456.34 $"),
rewardValue = resourceReference(R.string.staking_details_no_rewards_to_claim, wrappedList("0.43 $")),
@ -351,6 +351,6 @@ internal object TokenDetailsPreviewData {
value = PagingData.from(txHistoryItems),
),
),
stakingBlocksState = stakedBlock,
stakingBlocksState = stakingBalanceBlock,
)
}

View file

@ -1,10 +1,10 @@
package com.tangem.feature.tokendetails.presentation.tokendetails.state
import androidx.compose.runtime.Stable
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.extensions.TextReference
import java.math.BigDecimal
@Stable
@Immutable
internal sealed interface StakingBlockUM {
data object TemporaryUnavailable : StakingBlockUM

View file

@ -35,7 +35,7 @@ internal data class SwapTransactionsState(
)
@Immutable
internal class ExchangeStatusState(
internal data class ExchangeStatusState(
val status: ExchangeStatus,
val text: TextReference,
val isActive: Boolean,

View file

@ -5,6 +5,7 @@ import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIco
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.core.ui.utils.toDateFormatWithTodayYesterday
import com.tangem.core.ui.utils.toTimeFormat
@ -26,6 +27,7 @@ import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
import timber.log.Timber
import java.math.BigDecimal
import java.util.Locale
@ -110,7 +112,10 @@ internal class TokenDetailsSwapTransactionsStateConverter(
refundToken: CryptoCurrency?,
isRefundTerminalStatus: Boolean,
): SwapTransactionsState {
if (statusModel == null || tx.activeStatus == statusModel.status) return tx
if (statusModel == null || tx.activeStatus == statusModel.status) {
Timber.e("UpdateTxStatus isn't required. Current status isn't changed")
return tx
}
val hasFailed = tx.hasFailed || statusModel.status == ExchangeStatus.Failed
val notifications = getNotification(statusModel.status, statusModel.txExternalUrl, refundToken)
val showProviderLink = getShowProviderLink(notifications, statusModel)
@ -185,6 +190,7 @@ internal class TokenDetailsSwapTransactionsStateConverter(
val isFailed = status == ExchangeStatus.Failed
val isSending = status == ExchangeStatus.Sending
val isRefunded = status == ExchangeStatus.Refunded
val isPaused = status == ExchangeStatus.Paused
val isWaitingDone = !isWaiting
val isConfirmingDone = !isConfirming && isWaitingDone
@ -208,15 +214,18 @@ internal class TokenDetailsSwapTransactionsStateConverter(
hasFailed = hasFailed,
isVerifying = isVerifying,
isFailed = isFailed,
isPaused = isPaused,
),
)
add(
sendStep(
isSending = isSending,
isSendingDone = isSendingDone,
isRefunded = isRefunded,
),
)
if (!isPaused) {
add(
sendStep(
isSending = isSending,
isSendingDone = isSendingDone,
isRefunded = isRefunded,
),
)
}
}
}
}.toPersistentList()
@ -272,6 +281,7 @@ internal class TokenDetailsSwapTransactionsStateConverter(
hasFailed: Boolean,
isVerifying: Boolean = false,
isFailed: Boolean = false,
isPaused: Boolean,
) = when {
isVerifying -> ExchangeStatusState(
status = ExchangeStatus.Verifying,
@ -279,6 +289,12 @@ internal class TokenDetailsSwapTransactionsStateConverter(
isActive = true,
isDone = false,
)
isPaused -> ExchangeStatusState(
status = ExchangeStatus.Paused,
text = resourceReference(id = R.string.express_exchange_status_paused),
isActive = true,
isDone = false,
)
hasFailed || isFailed || isRefunded -> ExchangeStatusState(
status = ExchangeStatus.Failed,
text = TextReference.Res(R.string.express_exchange_status_failed),

View file

@ -18,13 +18,17 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.feature.swap.domain.models.domain.ExchangeStatus
import com.tangem.feature.tokendetails.presentation.tokendetails.state.ExchangeStatusState
import com.tangem.features.tokendetails.impl.R
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@Composable
internal fun ExchangeStatusBlock(
@ -103,34 +107,34 @@ private fun ExchangeStatusStep(
label = "Exchange Step Change Success",
modifier = Modifier
.size(TangemTheme.dimens.size20),
) {
) { state ->
when {
it.status == ExchangeStatus.Cancelled -> ExchangeStep(
iconRes = R.drawable.ic_close_24,
color = TangemTheme.colors.icon.warning,
isDone = false,
)
it.status == ExchangeStatus.Failed -> ExchangeStep(
iconRes = R.drawable.ic_close_24,
color = TangemTheme.colors.icon.warning,
isDone = it.isDone,
)
it.status == ExchangeStatus.Refunded -> ExchangeStep(
iconRes = R.drawable.ic_close_24,
color = TangemTheme.colors.icon.warning,
isDone = it.isDone,
)
it.status == ExchangeStatus.Verifying -> ExchangeStep(
state.status == ExchangeStatus.Cancelled -> {
ExchangeStep(
iconRes = R.drawable.ic_close_24,
color = TangemTheme.colors.icon.warning,
isDone = false,
)
}
state.status == ExchangeStatus.Failed || state.status == ExchangeStatus.Refunded ||
state.status == ExchangeStatus.Paused -> {
ExchangeStep(
iconRes = R.drawable.ic_close_24,
color = TangemTheme.colors.icon.warning,
isDone = state.isDone,
)
}
state.status == ExchangeStatus.Verifying -> ExchangeStep(
iconRes = R.drawable.ic_exclamation_24,
color = TangemTheme.colors.icon.attention,
isDone = it.isDone,
isDone = state.isDone,
)
it.isDone -> ExchangeStep(
state.isDone -> ExchangeStep(
iconRes = R.drawable.ic_check_24,
color = TangemTheme.colors.icon.primary1,
isDone = true,
)
it.isActive -> ExchangeStepInProgress()
state.isActive -> ExchangeStepInProgress()
else -> ExchangeStepDefault()
}
}
@ -144,11 +148,14 @@ private fun ExchangeStatusStep(
@Composable
private fun ExchangeStatusStepText(stepStatus: ExchangeStatusState) {
val status = stepStatus.status
val textColor = when {
stepStatus.status == ExchangeStatus.Cancelled -> TangemTheme.colors.icon.warning
stepStatus.status == ExchangeStatus.Refunded -> TangemTheme.colors.icon.warning
stepStatus.status == ExchangeStatus.Failed && !stepStatus.isDone -> TangemTheme.colors.icon.warning
stepStatus.status == ExchangeStatus.Verifying && !stepStatus.isDone -> TangemTheme.colors.icon.attention
status == ExchangeStatus.Cancelled || status == ExchangeStatus.Refunded || status == ExchangeStatus.Paused -> {
TangemTheme.colors.icon.warning
}
status == ExchangeStatus.Failed && !stepStatus.isDone -> TangemTheme.colors.icon.warning
status == ExchangeStatus.Verifying && !stepStatus.isDone -> TangemTheme.colors.icon.attention
stepStatus.isDone -> TangemTheme.colors.text.primary1
!stepStatus.isActive -> TangemTheme.colors.text.disabled
else -> TangemTheme.colors.text.primary1
@ -222,4 +229,35 @@ private fun ExchangeStepSeparator() {
shape = CircleShape,
),
)
}
@Preview
@Composable
private fun Preview_ExchangeStatusBlock() {
val base = ExchangeStatusState(
status = ExchangeStatus.Failed,
text = resourceReference(id = R.string.express_exchange_status_failed),
isActive = true,
isDone = false,
)
TangemThemePreview {
ExchangeStatusBlock(
statuses = listOf(
base,
base.copy(isActive = false, isDone = false),
base.copy(isActive = true, isDone = false),
base.copy(isActive = true, isDone = true),
ExchangeStatusState(
status = ExchangeStatus.Paused,
text = resourceReference(id = R.string.express_exchange_status_paused),
isActive = true,
isDone = false,
),
)
.toImmutableList(),
showLink = false,
onClick = {},
)
}
}

View file

@ -1,18 +1,12 @@
package com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.staking
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@ -23,7 +17,7 @@ import com.tangem.core.ui.extensions.orMaskWithStars
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData.stakedBlock
import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData.stakingBalanceBlock
import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockUM
import com.tangem.features.tokendetails.impl.R
import com.tangem.utils.StringsSigns
@ -36,16 +30,7 @@ internal fun StakingBalanceBlock(
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.fillMaxWidth()
.clip(TangemTheme.shapes.roundedCornersXMedium)
.background(TangemTheme.colors.background.primary)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(),
onClick = state.onStakeClicked,
)
.padding(TangemTheme.dimens.spacing12),
modifier = modifier.fillMaxWidth(),
) {
Column(
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
@ -108,6 +93,6 @@ private fun StakingBalanceBlock_Preview(
private class StakingBalanceBlockPreviewProvider : PreviewParameterProvider<StakingBlockUM.Staked> {
override val values: Sequence<StakingBlockUM.Staked>
get() = sequenceOf(stakedBlock)
get() = sequenceOf(stakingBalanceBlock)
}
// endregion

View file

@ -1,12 +1,10 @@
package com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.staking
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.res.TangemTheme
@ -17,11 +15,7 @@ import com.tangem.features.tokendetails.impl.R
internal fun StakingTemporaryUnavailableBlock(modifier: Modifier = Modifier) {
Column(
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
modifier = modifier
.fillMaxWidth()
.clip(TangemTheme.shapes.roundedCornersXMedium)
.background(TangemTheme.colors.background.primary)
.padding(TangemTheme.dimens.spacing12),
modifier = modifier.fillMaxWidth(),
) {
Text(
text = stringResource(R.string.staking_native),

View file

@ -3,8 +3,11 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.
import android.content.res.Configuration
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Text
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
@ -14,18 +17,15 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.SecondaryButton
import com.tangem.core.ui.components.SpacerW8
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.components.*
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.utils.getGreyScaleColorFilter
import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData.stakingBalanceBlock
import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData.stakingAvailableBlock
import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData.stakingLoadingBlock
import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData.stakingTemporaryUnavailableBlock
import com.tangem.feature.tokendetails.presentation.tokendetails.state.IconState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockUM
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.CurrencyIcon
import com.tangem.features.tokendetails.impl.R
@ -39,26 +39,35 @@ import com.tangem.features.tokendetails.impl.R
*/
@Composable
internal fun TokenStakingBlock(state: StakingBlockUM, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
AnimatedContent(
targetState = state,
contentAlignment = Alignment.CenterStart,
label = "Staking block animation",
Column(
modifier = modifier
.clip(TangemTheme.shapes.roundedCornersXMedium)
.background(TangemTheme.colors.background.primary)
.clickable(
enabled = state is StakingBlockUM.Staked,
interactionSource = remember { MutableInteractionSource() },
indication = ripple(),
onClick = { (state as? StakingBlockUM.Staked)?.onStakeClicked?.invoke() },
)
.fillMaxWidth()
.padding(all = TangemTheme.dimens.spacing12),
) {
when (it) {
is StakingBlockUM.TemporaryUnavailable -> StakingTemporaryUnavailableBlock(modifier)
is StakingBlockUM.Loading -> StakingLoading(
iconState = it.iconState,
modifier = modifier,
)
is StakingBlockUM.Staked -> StakingBalanceBlock(
state = it,
isBalanceHidden = isBalanceHidden,
modifier = modifier,
)
is StakingBlockUM.StakeAvailable -> StakingAvailableContent(
state = it,
modifier = modifier,
)
AnimatedContent(
targetState = state,
contentAlignment = Alignment.CenterStart,
label = "Staking block animation",
) {
when (it) {
is StakingBlockUM.TemporaryUnavailable -> StakingTemporaryUnavailableBlock()
is StakingBlockUM.Loading -> StakingLoading()
is StakingBlockUM.Staked -> StakingBalanceBlock(
state = it,
isBalanceHidden = isBalanceHidden,
)
is StakingBlockUM.StakeAvailable -> StakingAvailableContent(
state = it,
)
}
}
}
}
@ -66,13 +75,7 @@ internal fun TokenStakingBlock(state: StakingBlockUM, isBalanceHidden: Boolean,
@Composable
private fun StakingAvailableContent(state: StakingBlockUM.StakeAvailable, modifier: Modifier = Modifier) {
Column(
modifier = modifier
.background(
color = TangemTheme.colors.background.primary,
shape = TangemTheme.shapes.roundedCornersXMedium,
)
.fillMaxWidth()
.padding(all = TangemTheme.dimens.spacing12),
modifier = modifier.fillMaxWidth(),
) {
Row {
val (alpha, colorFilter) = remember(state.iconState.isGrayscale) {
@ -115,52 +118,30 @@ private fun StakingAvailableContent(state: StakingBlockUM.StakeAvailable, modifi
}
@Composable
private fun StakingLoading(iconState: IconState, modifier: Modifier = Modifier) {
private fun StakingLoading(modifier: Modifier = Modifier) {
Column(
modifier = modifier
.background(
color = TangemTheme.colors.background.primary,
shape = TangemTheme.shapes.roundedCornersXMedium,
)
.fillMaxWidth()
.heightIn(min = TangemTheme.dimens.size72)
.padding(all = TangemTheme.dimens.spacing12),
modifier = modifier.fillMaxWidth(),
) {
Row {
val (alpha, colorFilter) = remember(iconState.isGrayscale) {
getGreyScaleColorFilter(iconState.isGrayscale)
}
CurrencyIcon(
modifier = Modifier
.size(TangemTheme.dimens.size20)
.clip(TangemTheme.shapes.roundedCorners8)
.align(Alignment.CenterVertically),
icon = iconState,
alpha = alpha,
colorFilter = colorFilter,
)
SpacerW8()
Column {
RectangleShimmer(
modifier = Modifier
.fillMaxWidth()
.height(TangemTheme.dimens.size20),
)
Spacer(modifier = Modifier.size(TangemTheme.dimens.size4))
Spacer(modifier = Modifier.size(TangemTheme.dimens.size8))
RectangleShimmer(
modifier = Modifier
.fillMaxWidth()
.height(TangemTheme.dimens.size20),
.height(TangemTheme.dimens.size36),
)
Spacer(modifier = Modifier.size(TangemTheme.dimens.size8))
}
}
SecondaryButton(
modifier = Modifier.fillMaxWidth(),
showProgress = true,
text = TextReference.EMPTY.resolveReference(),
onClick = { /* no-op */ },
RectangleShimmer(
modifier = Modifier
.fillMaxWidth()
.height(TangemTheme.dimens.size48),
)
}
}
@ -186,6 +167,7 @@ private class StakingBlockStateProvider : CollectionPreviewParameterProvider<Sta
stakingLoadingBlock,
stakingAvailableBlock,
stakingTemporaryUnavailableBlock,
stakingBalanceBlock,
),
)
// endregion Preview

View file

@ -37,6 +37,12 @@ internal enum class Wallet2CobrandImage(
batchIds = setOf("AF09"),
),
BitcoinGold(
cards2ResId = R.drawable.ill_bitcoingold_card2_120_106,
cards3ResId = R.drawable.ill_bitcoingold_card3_120_106,
batchIds = setOf("AF71"),
),
BitcoinPizzaDay(
cards2ResId = R.drawable.ill_pizza_day_card2_120_106,
cards3ResId = R.drawable.ill_pizza_day_card3_120_106,
@ -82,7 +88,7 @@ internal enum class Wallet2CobrandImage(
Kaspa2(
cards2ResId = R.drawable.ill_kaspa2_card2_120_106,
cards3ResId = R.drawable.ill_kaspa2_card3_120_106,
batchIds = setOf("AF25"),
batchIds = setOf("AF25", "AF61", "AF72"),
),
KaspaReseller(
@ -91,6 +97,12 @@ internal enum class Wallet2CobrandImage(
batchIds = setOf("AF31"),
),
Kaspa3(
cards2ResId = R.drawable.ill_kaspa3_card2_120_106,
cards3ResId = R.drawable.ill_kaspa3_card3_120_106,
batchIds = setOf("AF73"),
),
KishuInu(
cards2ResId = R.drawable.ill_kishu_inu_card2_120_106,
cards3ResId = R.drawable.ill_kishu_inu_card3_120_106,

View file

@ -181,11 +181,7 @@ private fun WalletContent(
contentPadding = contentPadding,
horizontalAlignment = Alignment.CenterHorizontally,
) {
item(
// !!! Type of the key should be saveable via Bundle on Android !!!
key = state.wallets.map { it.walletCardState.id.stringValue },
contentType = state.wallets.map { it.walletCardState.id },
) {
item(key = "WalletsList" + state.selectedWalletIndex, contentType = "WalletsList") {
WalletsList(
lazyListState = walletsListState,
wallets = state.wallets.map(WalletState::walletCardState).toImmutableList(),

View file

@ -58,17 +58,11 @@ internal fun WalletsList(
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
flingBehavior = rememberWalletsFlingBehaviour(lazyListState = lazyListState, itemWidth = itemWidth),
) {
items(
items = wallets,
key = { it.id.stringValue },
contentType = { it.id.stringValue },
) { state ->
items(items = wallets, contentType = { it.id.stringValue }) { state ->
WalletCard(
state = state,
isBalanceHidden = isBalanceHidden,
modifier = Modifier
.animateItemPlacement()
.width(itemWidth),
modifier = Modifier.width(itemWidth),
)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -69,7 +69,6 @@ zxingQrCode = "3.5.1"
mviCore = "1.3.1"
kotlinSerialization = "1.4.1"
arrow = "1.2.3"
reactiveNetwork = "3.0.8"
walletConnectCore = "1.18.0"
walletConnectWeb3 = "1.11.0"
prettyLogger = "2.2.0"
@ -89,7 +88,7 @@ markdownComposeView = "0.5.4"
# endregion Other libraries
# region Tangem
tangemBlockchainSdk = "develop-821"
tangemBlockchainSdk = "develop-835"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "develop-391"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
@ -252,7 +251,6 @@ mviCore-watcher = { module = "com.github.badoo.mvicore:mvicore-diff", version.re
kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinSerialization" }
arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" }
arrow-fx = { module = "io.arrow-kt:arrow-fx-coroutines", version.ref = "arrow" }
reactive-network = { module = "com.github.pwittchen:reactivenetwork-rx2", version.ref = "reactiveNetwork" }
walletConnectCore = { module = "com.walletconnect:android-core", version.ref = "walletConnectCore" }
walletConnectWeb3 = { module = "com.walletconnect:web3wallet", version.ref = "walletConnectWeb3" }
prettyLogger = { module = "com.orhanobut:logger", version.ref = "prettyLogger" }

View file

@ -405,4 +405,6 @@ private val excludedBlockchains = listOf(
Blockchain.Unknown,
Blockchain.Nexa,
Blockchain.NexaTestnet,
Blockchain.Casper,
Blockchain.CasperTestnet,
)