Updated on 2026-08-14
This commit is contained in:
commit
fcf404a2cf
37 changed files with 781 additions and 156 deletions
|
|
@ -301,6 +301,12 @@ sealed class NotificationUM(val config: NotificationConfig) {
|
|||
),
|
||||
subtitle = TextReference.EMPTY,
|
||||
)
|
||||
|
||||
data object YieldSupplyHighNetworkFee : Info(
|
||||
title = resourceReference(id = R.string.yield_module_high_network_fees_notification_title),
|
||||
subtitle = resourceReference(id = R.string.yield_module_high_network_fees_notification_description),
|
||||
iconTint = NotificationConfig.IconTint.Accent,
|
||||
)
|
||||
}
|
||||
|
||||
sealed interface Cardano {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
},
|
||||
{
|
||||
"name": "STAKING_CARDANO_ENABLED",
|
||||
"version": "undefined"
|
||||
"version": "5.31.1"
|
||||
},
|
||||
{
|
||||
"name": "STAKING_ETH_ENABLED",
|
||||
|
|
|
|||
|
|
@ -392,6 +392,7 @@
|
|||
<string name="common_week">Woche</string>
|
||||
<string name="common_with">mit</string>
|
||||
<string name="common_yes">Ja</string>
|
||||
<string name="common_yield_mode">Ertragsmodus</string>
|
||||
<string name="contract_address_copied_message">Vertragsadresse kopiert!</string>
|
||||
<string name="currency_subtitle_expanded">Verfügbare Netzwerke</string>
|
||||
<string name="custom_token_another_account_dialog_description">Die Ableitung Deines Tokens entspricht der Ableitung von %1$s. Dein Token wird diesem Konto gutgeschrieben.</string>
|
||||
|
|
@ -1483,11 +1484,11 @@
|
|||
<string name="tangempay_onboarding_security_description">Ein separates Zahlungskonto wird erstellt, ohne Ihre Adressen und Vermögenswerte offenzulegen</string>
|
||||
<string name="tangempay_onboarding_security_title">Unerreichte Privatsphäre</string>
|
||||
<string name="tangempay_onboarding_title">Erhalten Sie Ihre kostenlose Tangem Pay Card in wenigen Minuten</string>
|
||||
<string name="tangempay_payment_account">Payment account</string>
|
||||
<string name="tangempay_payment_account">Zahlungskonto</string>
|
||||
<string name="tangempay_payment_account_sync_needed">Synchronisierung des Zahlungskontos erforderlich</string>
|
||||
<string name="tangempay_service_unavailable_description">Wir beheben ein technisches Problem. Bitte versuchen Sie es später erneut.</string>
|
||||
<string name="tangempay_service_unavailable_title">Service vorübergehend nicht verfügbar</string>
|
||||
<string name="tangempay_service_unreachable_try_later">Der Dienst ist derzeit nicht erreichbar. Bitte versuchen Sie es später erneut.</string>
|
||||
<string name="tangempay_service_unreachable_try_later">Daten können derzeit nicht angezeigt werden, Kartenzahlungen funktionieren jedoch weiterhin.</string>
|
||||
<string name="tangempay_sync_needed">Synchronisation erforderlich</string>
|
||||
<string name="tangempay_tangem_visa_card">Tangem Visa Card</string>
|
||||
<string name="tangempay_temporarily_unavailable">Tangem Pay ist vorübergehend nicht verfügbar</string>
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@
|
|||
<string name="common_week">semana</string>
|
||||
<string name="common_with">con</string>
|
||||
<string name="common_yes">Sí</string>
|
||||
<string name="common_yield_mode">Modo de rendimiento</string>
|
||||
<string name="contract_address_copied_message">Dirección de contrato copiada</string>
|
||||
<string name="currency_subtitle_expanded">Redes disponibles</string>
|
||||
<string name="custom_token_contract_address_input_title">Dirección de contrato</string>
|
||||
|
|
@ -1319,11 +1320,11 @@
|
|||
<string name="tangempay_onboarding_security_description">Se creará una cuenta de pago separada sin divulgar tus direcciones y activos</string>
|
||||
<string name="tangempay_onboarding_security_title">Privacidad inigualable</string>
|
||||
<string name="tangempay_onboarding_title">Obtén tu tarjeta Tangem Pay gratuita en minutos</string>
|
||||
<string name="tangempay_payment_account">Payment account</string>
|
||||
<string name="tangempay_payment_account">Cuenta de pago</string>
|
||||
<string name="tangempay_payment_account_sync_needed">Sincronización de cuenta de pago necesaria</string>
|
||||
<string name="tangempay_service_unavailable_description">Estamos solucionando un problema técnico. Por favor, inténtelo de nuevo más tarde.</string>
|
||||
<string name="tangempay_service_unavailable_title">Servicio temporalmente no disponible</string>
|
||||
<string name="tangempay_service_unreachable_try_later">El servicio no está disponible actualmente. Inténtalo de nuevo más tarde.</string>
|
||||
<string name="tangempay_service_unreachable_try_later">No es posible mostrar los datos en este momento, pero los pagos con tarjeta siguen funcionando.</string>
|
||||
<string name="tangempay_sync_needed">Sincronización necesaria</string>
|
||||
<string name="tangempay_tangem_visa_card">Tangem Visa Card</string>
|
||||
<string name="tangempay_temporarily_unavailable">Tangem Pay temporalmente no disponible</string>
|
||||
|
|
@ -1417,6 +1418,10 @@
|
|||
<string name="user_wallet_list_rename_popup_title">Renombrar la billetera</string>
|
||||
<string name="user_wallet_list_unlock_all">Desbloquear todo</string>
|
||||
<string name="user_wallet_list_unlock_all_with">Desbloquear todo con %s</string>
|
||||
<string name="visa_onboarding_pin_code_description">Configure un código de 4 dígitos.\nSe utilizará para los pagos.</string>
|
||||
<string name="visa_onboarding_pin_code_title">Crear código PIN</string>
|
||||
<string name="visa_onboarding_pin_not_accepted">No se aceptó el PIN. Inténtalo de nuevo o usa un código diferente.</string>
|
||||
<string name="visa_onboarding_pin_validation_error_message">PIN no válido: evitar secuencias o repeticiones</string>
|
||||
<string name="wallet_add_common_title">Elija cómo agregar su billetera</string>
|
||||
<string name="wallet_balance_blockchain_unreachable_try_later">La blockchain está Inaccesible. Inténtelo más tarde</string>
|
||||
<string name="wallet_balance_missing_derivation">Escanee la tarjeta o el anillo</string>
|
||||
|
|
|
|||
|
|
@ -328,6 +328,7 @@
|
|||
<string name="common_week">semaine</string>
|
||||
<string name="common_with">avec</string>
|
||||
<string name="common_yes">Oui</string>
|
||||
<string name="common_yield_mode">Mode Rendement</string>
|
||||
<string name="contract_address_copied_message">Adresse du contrat copiée !</string>
|
||||
<string name="currency_subtitle_expanded">Réseaux disponibles</string>
|
||||
<string name="custom_token_contract_address_input_title">Adresse du contrat</string>
|
||||
|
|
@ -1300,11 +1301,11 @@
|
|||
<string name="tangempay_onboarding_security_description">Un compte de paiement séparé sera créé sans divulguer vos adresses et actifs</string>
|
||||
<string name="tangempay_onboarding_security_title">Confidentialité inégalée</string>
|
||||
<string name="tangempay_onboarding_title">Obtenez votre carte Tangem Pay gratuite en quelques minutes</string>
|
||||
<string name="tangempay_payment_account">Payment account</string>
|
||||
<string name="tangempay_payment_account">Compte de paiement</string>
|
||||
<string name="tangempay_payment_account_sync_needed">Synchronisation du compte de paiement nécessaire</string>
|
||||
<string name="tangempay_service_unavailable_description">Nous réparons un problème technique. Veuillez réessayer plus tard.</string>
|
||||
<string name="tangempay_service_unavailable_title">Service temporairement indisponible</string>
|
||||
<string name="tangempay_service_unreachable_try_later">Le service est actuellement indisponible. Veuillez réessayer plus tard.</string>
|
||||
<string name="tangempay_service_unreachable_try_later">Les données ne peuvent pas être affichées pour le moment, mais les paiements par carte fonctionnent toujours.</string>
|
||||
<string name="tangempay_sync_needed">Synchronisation requise</string>
|
||||
<string name="tangempay_tangem_visa_card">Tangem Visa Card</string>
|
||||
<string name="tangempay_temporarily_unavailable">Tangem Pay est temporairement indisponible</string>
|
||||
|
|
@ -1408,6 +1409,9 @@
|
|||
<string name="visa_onboarding_in_progress_description">Cela ne prendra pas longtemps. Nous configurons votre compte.</string>
|
||||
<string name="visa_onboarding_in_progress_issuer_description">Cela ne prendra pas longtemps. Nous terminons l\'activation.</string>
|
||||
<string name="visa_onboarding_in_progress_title">Tout est en cours de préparation !</string>
|
||||
<string name="visa_onboarding_pin_code_description">Créez un code à 4 chiffres. Il servira pour les paiements.</string>
|
||||
<string name="visa_onboarding_pin_code_title">Créer un code PIN</string>
|
||||
<string name="visa_onboarding_pin_not_accepted">Le code PIN n\'a pas été accepté. Veuillez réessayer ou utiliser un autre code.</string>
|
||||
<string name="visa_onboarding_pin_validation_error_message">Code PIN invalide : évitez les séquences ou les répétitions</string>
|
||||
<string name="visa_onboarding_wallet_connect_title">Accéder le site Web</string>
|
||||
<string name="visa_onboarding_welcome_back_description">Continuons la configuration de votre compte.</string>
|
||||
|
|
|
|||
|
|
@ -162,11 +162,11 @@
|
|||
<string name="tangempay_onboarding_security_description">Verrà creato un conto di pagamento separato senza divulgare i tuoi indirizzi e asset</string>
|
||||
<string name="tangempay_onboarding_security_title">Privacy senza rivali</string>
|
||||
<string name="tangempay_onboarding_title">Ottieni la tua carta Tangem Pay gratuita in pochi minuti</string>
|
||||
<string name="tangempay_payment_account">Payment account</string>
|
||||
<string name="tangempay_payment_account">Conto di pagamento</string>
|
||||
<string name="tangempay_payment_account_sync_needed">Sincronizzazione del conto di pagamento necessaria</string>
|
||||
<string name="tangempay_service_unavailable_description">Stiamo risolvendo un problema tecnico. Riprova più tardi.</string>
|
||||
<string name="tangempay_service_unavailable_title">Servizio temporaneamente non disponibile</string>
|
||||
<string name="tangempay_service_unreachable_try_later">Il servizio è attualmente non raggiungibile. Riprova più tardi.</string>
|
||||
<string name="tangempay_service_unreachable_try_later">Al momento non è possibile visualizzare i dati, ma i pagamenti con carta continuano a funzionare.</string>
|
||||
<string name="tangempay_sync_needed">Sincronizzazione necessaria</string>
|
||||
<string name="tangempay_tangem_visa_card">Tangem Visa Card</string>
|
||||
<string name="tangempay_temporarily_unavailable">Tangem Pay è temporaneamente non disponibile</string>
|
||||
|
|
@ -174,6 +174,10 @@
|
|||
<string name="tangempay_use_tangem_device_to_restore_payment_account">Usa la tua carta o il tuo anello per ripristinare l\'accesso al tuo conto di pagamento</string>
|
||||
<string name="tangempay_your_pin_code">Il tuo codice PIN</string>
|
||||
<string name="twins_recreate_toolbar">Tangem Twin</string>
|
||||
<string name="visa_onboarding_pin_code_description">Imposta un codice di 4 cifre.\nVerrà utilizzato per i pagamenti.</string>
|
||||
<string name="visa_onboarding_pin_code_title">Crea codice PIN</string>
|
||||
<string name="visa_onboarding_pin_not_accepted">Il PIN non è stato accettato. Riprova o utilizza un codice diverso.</string>
|
||||
<string name="visa_onboarding_pin_validation_error_message">PIN non valido: evitare sequenze o ripetizioni</string>
|
||||
<string name="wallet_connect_title">WalletConnect</string>
|
||||
<string name="wallet_notification_address_copied">L\'indirizzo è stato copiato con successo</string>
|
||||
<string name="wallet_notification_no_internet">Nessuna connessione a Internet</string>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<string name="access_code_alert_skip_ok">とにかくスキップ</string>
|
||||
<string name="access_code_alert_skip_title">アクセスコードが設定されていません</string>
|
||||
<string name="access_code_alert_validation_cancel">コードを変更</string>
|
||||
<string name="access_code_alert_validation_description">アクセスコードは、ウォレットのロック解除・資産へのアクセス保護に使用されます</string>
|
||||
<string name="access_code_alert_validation_description">アクセスコードは、ウォレットのロック解除およびウォレットへのアクセス保護に使用されます</string>
|
||||
<string name="access_code_alert_validation_ok">このまま使う</string>
|
||||
<string name="access_code_alert_validation_title">このアクセスコードは簡単に推測される可能性があります</string>
|
||||
<string name="access_code_check_title">アクセスコードを入力</string>
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
<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_access_code_warning">まずアクセスコードを設定してから、生体認証を有効にしてください</string>
|
||||
<string name="app_settings_access_code_warning">生体認証を有効にするには、アクセスコードを設定してください</string>
|
||||
<string name="app_settings_biometrics_footer">%1$sを使用してウォレットのロックを解除し、取引の署名などの機密性の高い操作を承認してください。ハードウェアウォレットの場合は、署名にカードまたはリングが必要です。</string>
|
||||
<string name="app_settings_default_fee">デフォルト手数料</string>
|
||||
<string name="app_settings_default_fee_footer">デフォルト手数料を有効にすると、取引手数料が自動的に設定され、送金時に手数料ページを表示する必要がなくなります。必要に応じて、いつでもこのページに戻ることができます。</string>
|
||||
|
|
@ -136,7 +136,7 @@
|
|||
<string name="backup_info_title">リカバリーフレーズ</string>
|
||||
<string name="backup_seed_caution">これらの単語は誰にも教えないでください。Tangemがこれらの単語を尋ねることは、絶対にありません。以下の%s個の単語はウォレットのリカバリーフレーズです。デバイスを紛失した場合、これらの単語を使用してウォレットを復元できます。</string>
|
||||
<string name="backup_seed_description">これらの%s個の単語を番号順に書き留め、安全かつ他人の目に触れない場所に保管してください</string>
|
||||
<string name="backup_seed_responsibility">ウォレットおよびリカバリーフレーズの保護とバックアップは、すべてあなた自身の責任となります。</string>
|
||||
<string name="backup_seed_responsibility">ウォレットの安全確保およびリカバリーフレーズの安全なバックアップは、すべてご自身の責任となります。</string>
|
||||
<string name="backup_seed_title">リカバリーフレーズ</string>
|
||||
<string name="balance_hidden_description">残高を表示または非表示にするには、デバイスの画面を下向きにするか、設定でオフにしてください。</string>
|
||||
<string name="balance_hidden_do_not_show_button">今後表示しない</string>
|
||||
|
|
@ -386,6 +386,7 @@
|
|||
<string name="common_week">週</string>
|
||||
<string name="common_with">で</string>
|
||||
<string name="common_yes">はい</string>
|
||||
<string name="common_yield_mode">利息モード</string>
|
||||
<string name="contract_address_copied_message">コントラクトアドレスをコピーしました!</string>
|
||||
<string name="currency_subtitle_expanded">利用可能なネットワーク</string>
|
||||
<string name="custom_token_another_account_dialog_description">このトークンの導出パスが%1$sの導出パスと一致しています。トークンはこのアカウントに追加されます。</string>
|
||||
|
|
@ -575,8 +576,8 @@
|
|||
<string name="hw_activation_need_finish">今すぐ確定</string>
|
||||
<string name="hw_activation_need_title">ウォレットの設定を完了する</string>
|
||||
<string name="hw_activation_need_warning_description">アクセスコードでアプリを保護して、設定を完了してください。</string>
|
||||
<string name="hw_backup_alert_description">そうした場合は、最初からやり直す必要があります。</string>
|
||||
<string name="hw_backup_alert_title">本当にアクティベーション処理を終了してもよろしいですか?</string>
|
||||
<string name="hw_backup_alert_description">終了すると、最初からやり直す必要があります。</string>
|
||||
<string name="hw_backup_alert_title">セットアップを中止してもよろしいですか?</string>
|
||||
<string name="hw_backup_banner_description">暗号資産をオフラインで厳重保管。カードサイズで、金庫以上の安心を。</string>
|
||||
<string name="hw_backup_close_description">実行すると、最初からやり直す必要があります。</string>
|
||||
<string name="hw_backup_google_drive_description">Googleドライブのバックアップから既存のウォレットを復元する</string>
|
||||
|
|
@ -585,18 +586,19 @@
|
|||
<string name="hw_backup_hardware_create_title">新しいウォレットを作成</string>
|
||||
<string name="hw_backup_hardware_description">Tangemの高性能ハードウェアウォレットで、セキュリティをさらに強化しましょう。</string>
|
||||
<string name="hw_backup_hardware_title">ハードウェアウォレット</string>
|
||||
<string name="hw_backup_hardware_upgrade_description">現在のウォレットをTangemウォレットに移します。</string>
|
||||
<string name="hw_backup_hardware_upgrade_description">現在のウォレットをTangemに移します。</string>
|
||||
<string name="hw_backup_hardware_upgrade_title">現在のウォレットをアップグレードする</string>
|
||||
<string name="hw_backup_need_action">バックアップへ移動</string>
|
||||
<string name="hw_backup_need_description">アクセスコードを作成する前にウォレットをバックアップしてください。</string>
|
||||
<string name="hw_backup_need_finish_first">まずバックアップを完了する</string>
|
||||
<string name="hw_backup_need_finish_first">先にバックアップを完了してください</string>
|
||||
<string name="hw_backup_need_title">まずバックアップを完了する</string>
|
||||
<string name="hw_backup_section_other_title">その他の方法</string>
|
||||
<string name="hw_backup_seed_description">リカバリーフレーズは、ご自身で安全な場所に保管し、資金を守るために他人には絶対に共有しないでください。</string>
|
||||
<string name="hw_backup_seed_description">資金を保護するため、リカバリーフレーズは安全な場所に保管し、他人に知られないようにしてください。</string>
|
||||
<string name="hw_backup_seed_title">リカバリーフレーズ</string>
|
||||
<string name="hw_backup_to_secure_description">アクセスコードを使用してウォレットを保護するには、まずバックアップを完了してください。</string>
|
||||
<string name="hw_backup_to_upgrade_description">ウォレットをハードウェアにアップグレードするには、まずバックアップしてください。</string>
|
||||
<string name="hw_create_keys_title">鍵はアプリに保存されます</string>
|
||||
<string name="hw_backup_to_secure_description">アクセスコードでウォレットを保護するには、バックアップの手続きを完了してください。</string>
|
||||
<string name="hw_backup_to_upgrade_description">ハードウェアウォレットにアップグレードするには、バックアップの手続きを完了してください。</string>
|
||||
<string name="hw_create_keys_title">秘密鍵はデバイス上に保持されます</string>
|
||||
<string name="hw_create_seed_description">リカバリーフレーズを使ってウォレットを作成または復元してください。</string>
|
||||
<string name="hw_create_seed_title">シードフレーズのバックアップ</string>
|
||||
<string name="hw_create_title">モバイルウォレットを作成する</string>
|
||||
<string name="hw_import_existing_wallet">既存のウォレットをインポートする</string>
|
||||
|
|
@ -610,25 +612,25 @@
|
|||
<string name="hw_remove_wallet_notification_action_backup_view">バックアップを表示</string>
|
||||
<string name="hw_remove_wallet_notification_action_forget">ウォレット削除</string>
|
||||
<string name="hw_remove_wallet_notification_action_forget_anyway">とにかく削除する</string>
|
||||
<string name="hw_remove_wallet_notification_description_has_backup">このウォレットにはバックアップが存在します。後で復元できるように、削除する前に内容を確認してください。</string>
|
||||
<string name="hw_remove_wallet_notification_description_without_backup">バックアップなしでこのウォレットを削除すると、資金へのアクセスを永久に失います。</string>
|
||||
<string name="hw_remove_wallet_notification_title">このウォレットを削除しますか?</string>
|
||||
<string name="hw_remove_wallet_warning_access">ウォレットの削除前にバックアップをしていなければ、アクセスを失う可能性があることを理解しています。</string>
|
||||
<string name="hw_remove_wallet_warning_device">ウォレットを削除しても中身自体が消えるわけではなく、単にこのデバイスから表示が消えるだけであることを理解しています。</string>
|
||||
<string name="hw_upgrade_backup_description">もはや、シードフレーズは不要。Tangemカードやリングが、そのまま安全なバックアップになります。</string>
|
||||
<string name="hw_remove_wallet_notification_description_has_backup">このウォレットにはバックアップがあります。ウォレットを削除する前に、復元できることを確認してください。</string>
|
||||
<string name="hw_remove_wallet_notification_description_without_backup">バックアップを行わずにこのウォレットを削除すると、資金へのアクセスを永久に失います。</string>
|
||||
<string name="hw_remove_wallet_notification_title">このウォレットを削除してもよろしいですか?</string>
|
||||
<string name="hw_remove_wallet_warning_access">ウォレットを削除する前にバックアップを行っていない場合、ウォレットへのアクセスを失うことを理解しています。</string>
|
||||
<string name="hw_remove_wallet_warning_device">ウォレットを削除しても中身自体が消えるわけではなく、このデバイスから表示が消えるだけであることを理解しています。</string>
|
||||
<string name="hw_upgrade_backup_description">シードフレーズは不要です。Tangemカードまたはリングが安全なバックアップとなります。</string>
|
||||
<string name="hw_upgrade_backup_title">Tangemでバックアップ</string>
|
||||
<string name="hw_upgrade_error_card_already_has_wallet">アップグレードできません。このデバイスにはすでにウォレットが存在します。</string>
|
||||
<string name="hw_upgrade_error_card_key_import">別のデバイスを選択してください。このデバイスはアップグレードに使用できません。</string>
|
||||
<string name="hw_upgrade_error_wallet2_card_required">操作中にエラーが発生しました。</string>
|
||||
<string name="hw_upgrade_funds_access_description">処理中も、資金は安全に保たれ、常にアクセス可能です。</string>
|
||||
<string name="hw_upgrade_funds_access_title">資金へのアクセス</string>
|
||||
<string name="hw_upgrade_general_security_description">ウォレットのデータはアプリから削除され、Tangemデバイスに保存されます。</string>
|
||||
<string name="hw_upgrade_general_security_description">ウォレットのデータはアプリから削除され、ハードウェアウォレットに保存されます</string>
|
||||
<string name="hw_upgrade_general_security_title">セキュリティ全般</string>
|
||||
<string name="hw_upgrade_key_migration_description">秘密鍵はアプリからTangemデバイスに移動されます。</string>
|
||||
<string name="hw_upgrade_key_migration_title">鍵の移行</string>
|
||||
<string name="hw_upgrade_key_migration_description">秘密鍵はアプリからTangemハードウェアウォレットへ移行されます</string>
|
||||
<string name="hw_upgrade_key_migration_title">キーの移行</string>
|
||||
<string name="hw_upgrade_scan_device">デバイスをスキャン</string>
|
||||
<string name="hw_upgrade_start_action">アップグレードを開始</string>
|
||||
<string name="hw_upgrade_start_description">ハードウェアウォレットにアップグレードすると、資産がコールドストレージで安全に保管されます。</string>
|
||||
<string name="hw_upgrade_start_description">ハードウェアウォレットへのアップグレードを行います。資産はコールドストレージで安全に保管されます。</string>
|
||||
<string name="hw_upgrade_start_title">Tangemウォレット</string>
|
||||
<string name="hw_upgrade_title">ハードウェアウォレットにアップグレード</string>
|
||||
<string name="hw_upgrade_to_cold_banner_description">Tangemの業界最高クラスのハードウェアウォレットで、暗号資産を安全に保管しましょう。</string>
|
||||
|
|
@ -714,6 +716,7 @@
|
|||
<string name="markets_sort_by_top_gainers_title">上昇率上位</string>
|
||||
<string name="markets_sort_by_top_losers_title">下落率上位</string>
|
||||
<string name="markets_sort_by_trending_title">トレンド</string>
|
||||
<string name="markets_sort_by_yield_mode_title">利息モード</string>
|
||||
<string name="markets_staking_banner_description_placeholder">ステーキングは暗号資産で報酬を受け取る最も簡単な方法です。 %s</string>
|
||||
<string name="markets_staking_banner_title">最大%s APYを獲得</string>
|
||||
<string name="markets_token_added">トークンを追加しました</string>
|
||||
|
|
@ -963,6 +966,7 @@
|
|||
<string name="onramp_currency_other">その他の通貨</string>
|
||||
<string name="onramp_currency_popular">人気の法定通貨</string>
|
||||
<string name="onramp_currency_search">通貨で検索</string>
|
||||
<string name="onramp_error_transaction_already_processed">この取引はすでに処理されています。これ以上の対応は必要ありません。</string>
|
||||
<string name="onramp_fetching_best_rates">最良のレートを取得しています...</string>
|
||||
<string name="onramp_instant_status">即時</string>
|
||||
<string name="onramp_legal">オンランプ機能を使用することにより、プロバイダの%1$sおよび%2$sに同意するものとします</string>
|
||||
|
|
@ -1481,7 +1485,7 @@
|
|||
<string name="tangempay_payment_account_sync_needed">支払いアカウントの同期が必要です</string>
|
||||
<string name="tangempay_service_unavailable_description">技術的な問題を修正しています。後でもう一度お試しください。</string>
|
||||
<string name="tangempay_service_unavailable_title">サービスは一時的に利用できません</string>
|
||||
<string name="tangempay_service_unreachable_try_later">現在サービスに接続できません。後ほどもう一度お試しください。</string>
|
||||
<string name="tangempay_service_unreachable_try_later">現在、データを表示できませんが、カードでのお支払いは引き続きご利用いただけます。</string>
|
||||
<string name="tangempay_sync_needed">同期が必要です</string>
|
||||
<string name="tangempay_tangem_visa_card">Tangem Visaカード</string>
|
||||
<string name="tangempay_temporarily_unavailable">Tangem Payは一時的に利用できません</string>
|
||||
|
|
@ -1589,6 +1593,7 @@
|
|||
<string name="visa_onboarding_in_progress_issuer_description">長くはかかりません。アクティベーションを完了しています。</string>
|
||||
<string name="visa_onboarding_in_progress_title">準備完了です!</string>
|
||||
<string name="visa_onboarding_pin_code_description">4桁のコードを設定します。 \nお支払いの際に使用されます。</string>
|
||||
<string name="visa_onboarding_pin_code_title">PINコードを作成する</string>
|
||||
<string name="visa_onboarding_pin_not_accepted">PINの認証に失敗しました。もう一度お試しいただくか、別のコードを使用してください。</string>
|
||||
<string name="visa_onboarding_pin_validation_error_message">無効な暗証番号:連続や繰り返しを避けてください</string>
|
||||
<string name="visa_onboarding_wallet_connect_title">ウェブサイトに移動</string>
|
||||
|
|
|
|||
|
|
@ -402,6 +402,7 @@
|
|||
<string name="common_week">неделю</string>
|
||||
<string name="common_with">с</string>
|
||||
<string name="common_yes">Да</string>
|
||||
<string name="common_yield_mode">Режим доходности</string>
|
||||
<string name="contract_address_copied_message">Адрес контракта скопирован!</string>
|
||||
<string name="currency_subtitle_expanded">Доступные сети</string>
|
||||
<string name="custom_token_another_account_dialog_description">Деривация вашего токена совпадает с деривацией %1$s. Токен будет добавлен к этой учётной записи.</string>
|
||||
|
|
@ -1518,16 +1519,16 @@
|
|||
<string name="tangempay_onboarding_security_description">Мы создадим отдельный платежный счет без раскрытия ваших активов \nи их адресов</string>
|
||||
<string name="tangempay_onboarding_security_title">Абсолютная приватность</string>
|
||||
<string name="tangempay_onboarding_title">Откройте виртуальную \nTangem Pay Card</string>
|
||||
<string name="tangempay_payment_account">Payment account</string>
|
||||
<string name="tangempay_payment_account_sync_needed">Требуется синхронизация платежного счета</string>
|
||||
<string name="tangempay_payment_account">Платежный аккаунт</string>
|
||||
<string name="tangempay_payment_account_sync_needed">Требуется синхронизация платежного аккаунта</string>
|
||||
<string name="tangempay_service_unavailable_description">Мы устраняем техническую проблему. Пожалуйста, попробуйте позже.</string>
|
||||
<string name="tangempay_service_unavailable_title">Сервис временно недоступен</string>
|
||||
<string name="tangempay_service_unreachable_try_later">Сервис временно недоступен. Пожалуйста, попробуйте позже.</string>
|
||||
<string name="tangempay_service_unreachable_try_later">Не можем показать данные карты, но оплаты продолжают работать.</string>
|
||||
<string name="tangempay_sync_needed">Требуется синхронизация</string>
|
||||
<string name="tangempay_tangem_visa_card">Tangem Visa Card</string>
|
||||
<string name="tangempay_temporarily_unavailable">Tangem Pay временно недоступен</string>
|
||||
<string name="tangempay_title">Tangem Pay</string>
|
||||
<string name="tangempay_use_tangem_device_to_restore_payment_account">Используйте вашу карту или кольцо для восстановления доступа к платежному счету</string>
|
||||
<string name="tangempay_use_tangem_device_to_restore_payment_account">Используйте вашу карту или кольцо для восстановления доступа к платежному аккаунту</string>
|
||||
<string name="tangempay_your_pin_code">Ваш PIN-код</string>
|
||||
<string name="this_is_my_wallet_title">Это мой кошелек</string>
|
||||
<string name="toast_balances_hidden">Балансы скрыты</string>
|
||||
|
|
@ -1621,7 +1622,11 @@
|
|||
<string name="user_wallet_list_unlock_all_with">Разблокировать все с %s</string>
|
||||
<string name="visa_onboarding_access_code_navigation_title">Код доступа</string>
|
||||
<string name="visa_onboarding_account_activation_navigation_title">Активация аккаунта</string>
|
||||
<string name="visa_onboarding_pin_code_description">Установите 4-значный код.\nОн будет использоваться для платежей.</string>
|
||||
<string name="visa_onboarding_pin_code_navigation_title">ПИН-код</string>
|
||||
<string name="visa_onboarding_pin_code_title">Установить ПИН-код</string>
|
||||
<string name="visa_onboarding_pin_not_accepted">ПИН не принят. Попробуйте ещё раз или введите другой код.</string>
|
||||
<string name="visa_onboarding_pin_validation_error_message">Слабый ПИН: не используйте повторы или последовательности.</string>
|
||||
<string name="visa_unlock_notification_button">Разблокировать</string>
|
||||
<string name="wallet_add_common_title">Выберите способ добавления кошелька</string>
|
||||
<string name="wallet_add_hardware_description">Отсканируйте вашу карту или кольцо Tangem, чтобы восстановить её или импортировать из другого кошелька.</string>
|
||||
|
|
|
|||
|
|
@ -257,6 +257,7 @@
|
|||
<string name="common_week">тиждень</string>
|
||||
<string name="common_with">з</string>
|
||||
<string name="common_yes">Так</string>
|
||||
<string name="common_yield_mode">Режим дохідності</string>
|
||||
<string name="contract_address_copied_message">Адреса контракту скопійована!</string>
|
||||
<string name="currency_subtitle_expanded">Доступні мережі</string>
|
||||
<string name="custom_token_contract_address_input_title">Адреса контракту</string>
|
||||
|
|
|
|||
|
|
@ -405,11 +405,11 @@
|
|||
<string name="tangempay_onboarding_security_description">將創建單獨的支付帳戶,且不會透露您的地址和資產</string>
|
||||
<string name="tangempay_onboarding_security_title">無與倫比的隱私</string>
|
||||
<string name="tangempay_onboarding_title">在幾分鐘內獲得免費的 Tangem Pay 卡</string>
|
||||
<string name="tangempay_payment_account">Payment account</string>
|
||||
<string name="tangempay_payment_account">付款帳戶</string>
|
||||
<string name="tangempay_payment_account_sync_needed">需要同步支付账户</string>
|
||||
<string name="tangempay_service_unavailable_description">我们正在修复技术问题。请稍后再试。</string>
|
||||
<string name="tangempay_service_unavailable_title">服務暫時無法使用</string>
|
||||
<string name="tangempay_service_unreachable_try_later">服务当前不可用,请稍后再试</string>
|
||||
<string name="tangempay_service_unreachable_try_later">目前無法顯示資料,但卡片支付仍可正常使用。</string>
|
||||
<string name="tangempay_sync_needed">需要同步</string>
|
||||
<string name="tangempay_tangem_visa_card">Tangem Visa Card</string>
|
||||
<string name="tangempay_temporarily_unavailable">Tangem Pay暂时不可用</string>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<string name="access_code_alert_skip_ok">Skip anyway</string>
|
||||
<string name="access_code_alert_skip_title">Access code not set</string>
|
||||
<string name="access_code_alert_validation_cancel">Change code</string>
|
||||
<string name="access_code_alert_validation_description">Your access code will be used to unlock your wallet and to protect access to the assets</string>
|
||||
<string name="access_code_alert_validation_description">Your access code unlocks and protects access to your wallet</string>
|
||||
<string name="access_code_alert_validation_ok">Use anyway</string>
|
||||
<string name="access_code_alert_validation_title">This access code can be easily guessed</string>
|
||||
<string name="access_code_check_title">Enter access code</string>
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
<string name="alert_manage_tokens_unsupported_message">Tokens in %1$s network are not supported by this card or ring due to firmware limitation.</string>
|
||||
<string name="alert_troubleshooting_scan_card_title">Are you having difficulty scanning your card or ring?</string>
|
||||
<string name="alert_unsupported_card">This card is not designed to work with this app</string>
|
||||
<string name="app_settings_access_code_warning">Set an access code first to enable biometrics</string>
|
||||
<string name="app_settings_access_code_warning">Set an access code to enable biometrics</string>
|
||||
<string name="app_settings_biometrics_footer">Use %1$s to unlock your wallet and approve sensitive actions, like signing transactions. For hardware wallets, a card or ring is still required to sign.</string>
|
||||
<string name="app_settings_default_fee">Default Fee</string>
|
||||
<string name="app_settings_default_fee_footer">Enable Default Fee to set transaction fees automatically and skip the Fee page when sending funds. You can always go back to this page if necessary.</string>
|
||||
|
|
@ -137,7 +137,7 @@
|
|||
<string name="backup_info_title">Recovery phrase</string>
|
||||
<string name="backup_seed_caution">Never share these words with anyone. Tangem will never ask you for them. The %s words below are your wallet\'s recovery phrase. Use them to restore your wallet if you lose your device.</string>
|
||||
<string name="backup_seed_description">Write down these %s words in numerical order and keep them safe and private</string>
|
||||
<string name="backup_seed_responsibility">You are fully responsible for securing and backing up your wallet and recovery phrase.</string>
|
||||
<string name="backup_seed_responsibility">You are fully responsible for securing your wallet and safely backing up your recovery phrase.</string>
|
||||
<string name="backup_seed_title">Recovery phrase</string>
|
||||
<string name="balance_hidden_description">To hide or show your balances, simply flip your device screen down, or switch it off in Settings</string>
|
||||
<string name="balance_hidden_do_not_show_button">Don\'t show again</string>
|
||||
|
|
@ -394,6 +394,7 @@
|
|||
<string name="common_week">week</string>
|
||||
<string name="common_with">with</string>
|
||||
<string name="common_yes">Yes</string>
|
||||
<string name="common_yield_mode">Yield Mode</string>
|
||||
<string name="contract_address_copied_message">Contract address copied!</string>
|
||||
<string name="currency_subtitle_expanded">Available networks</string>
|
||||
<string name="custom_token_another_account_dialog_description">Derivation of your token matches the derivation of %1$s. Your token will be added to this account.</string>
|
||||
|
|
@ -583,7 +584,7 @@
|
|||
<string name="hw_activation_need_finish">Finalize now</string>
|
||||
<string name="hw_activation_need_title">Finalize wallet setup</string>
|
||||
<string name="hw_activation_need_warning_description">Complete setup by securing the app with an access code.</string>
|
||||
<string name="hw_backup_alert_description">If you do, you\'ll need to start over.</string>
|
||||
<string name="hw_backup_alert_description">If you exit, you\'ll need to start over.</string>
|
||||
<string name="hw_backup_alert_title">Are you sure you want to quit the setup process?</string>
|
||||
<string name="hw_backup_banner_description">Keeps your crypto safe and offline. Slim as a credit card, safer than a bank vault.</string>
|
||||
<string name="hw_backup_close_description">If you do, you\'ll need to start over.</string>
|
||||
|
|
@ -592,7 +593,7 @@
|
|||
<string name="hw_backup_hardware_create_description">Create a secure wallet and transfer your funds for extra protection.</string>
|
||||
<string name="hw_backup_hardware_create_title">Create new wallet</string>
|
||||
<string name="hw_backup_hardware_description">Level up your security with the superior Tangem hardware wallet.</string>
|
||||
<string name="hw_backup_hardware_title">Hardware Wallet</string>
|
||||
<string name="hw_backup_hardware_title">Hardware wallet</string>
|
||||
<string name="hw_backup_hardware_upgrade_description">Move your current wallet into Tangem.</string>
|
||||
<string name="hw_backup_hardware_upgrade_title">Upgrade current wallet</string>
|
||||
<string name="hw_backup_need_action">Go to backup</string>
|
||||
|
|
@ -603,7 +604,7 @@
|
|||
<string name="hw_backup_section_other_title">Other methods</string>
|
||||
<string name="hw_backup_seed_description">Save your recovery phrase in a secure place and keep it private to protect your funds.</string>
|
||||
<string name="hw_backup_seed_title">Recovery phrase</string>
|
||||
<string name="hw_backup_to_secure_description">To secure your wallet with an Access Code, complete the backup first.</string>
|
||||
<string name="hw_backup_to_secure_description">To secure your wallet with an access code, complete the backup process.</string>
|
||||
<string name="hw_backup_to_upgrade_description">To upgrade to a hardware wallet, complete the backup process.</string>
|
||||
<string name="hw_create_keys_description">Your private keys are securely encrypted and stored on your phone</string>
|
||||
<string name="hw_create_keys_title">Private keys stay on your device</string>
|
||||
|
|
@ -624,24 +625,24 @@
|
|||
<string name="hw_remove_wallet_notification_description_has_backup">This wallet has a backup. Ensure you can recover it before forgetting the wallet.</string>
|
||||
<string name="hw_remove_wallet_notification_description_without_backup">If you forget this wallet without a backup, you\'ll permanently lose access to your funds.</string>
|
||||
<string name="hw_remove_wallet_notification_title">Are you sure you want to forget this wallet?</string>
|
||||
<string name="hw_remove_wallet_warning_access">I understand that if I haven\'t backed up my wallet before removing it, I may lose access to it.</string>
|
||||
<string name="hw_remove_wallet_warning_access">I understand that if I haven\'t backed up my wallet before removing it, I will lose access to it.</string>
|
||||
<string name="hw_remove_wallet_warning_device">I understand that removing my wallet does not delete it, only removes it from my device.</string>
|
||||
<string name="hw_upgrade_backup_description">Seed phrase not required. Your Tangem card or ring becomes your secure backup.</string>
|
||||
<string name="hw_upgrade_backup_title">Backup with Tangem</string>
|
||||
<string name="hw_upgrade_error_card_already_has_wallet">Can’t upgrade. A wallet already exists on this device.</string>
|
||||
<string name="hw_upgrade_error_card_already_has_wallet">Can\'t upgrade. A wallet already exists on this device.</string>
|
||||
<string name="hw_upgrade_error_card_key_import">Pick another device. This one can’t be used for the upgrade.</string>
|
||||
<string name="hw_upgrade_error_wallet2_card_required">An error occurred during the operation.</string>
|
||||
<string name="hw_upgrade_funds_access_description">Your funds remain safe and fully accessible during the process</string>
|
||||
<string name="hw_upgrade_funds_access_title">Access to funds</string>
|
||||
<string name="hw_upgrade_general_security_description">Your wallet data will be erased from the app and stored on your Tangem device</string>
|
||||
<string name="hw_upgrade_general_security_description">Your wallet data will be erased from the app and stored on your hardware wallet</string>
|
||||
<string name="hw_upgrade_general_security_title">General security</string>
|
||||
<string name="hw_upgrade_key_migration_description">Private keys will be moved from the app to your Tangem device</string>
|
||||
<string name="hw_upgrade_key_migration_title">Key Migration</string>
|
||||
<string name="hw_upgrade_key_migration_description">Private keys will be moved from the app to your Tangem hardware wallet</string>
|
||||
<string name="hw_upgrade_key_migration_title">Key migration</string>
|
||||
<string name="hw_upgrade_scan_device">Scan device</string>
|
||||
<string name="hw_upgrade_start_action">Start upgrade</string>
|
||||
<string name="hw_upgrade_start_description">You\'re about to upgrade to our hardware wallet. It will keep your assets safe in cold storage.</string>
|
||||
<string name="hw_upgrade_start_title">Tangem Wallet</string>
|
||||
<string name="hw_upgrade_title">Upgrade to Hardware Wallet</string>
|
||||
<string name="hw_upgrade_title">Upgrade to our Hardware Wallet</string>
|
||||
<string name="hw_upgrade_to_cold_banner_description">Keep your crypto safe with Tangem\'s top-tier hardware wallet.</string>
|
||||
<string name="hw_upgrade_to_cold_banner_title">Upgrade your wallet to hardware security</string>
|
||||
<string name="information_generated_with_ai">This information was generated with AI.\nTap here, if you find any errors.</string>
|
||||
|
|
@ -1437,6 +1438,7 @@
|
|||
<string name="tangem_pay_unfreeze_card_failed">Failed to unfreeze the card. Try again later.</string>
|
||||
<string name="tangem_pay_unfreeze_card_success">Your card is unfrozen.</string>
|
||||
<string name="tangem_pay_withdrawal">Withdrawal</string>
|
||||
<string name="tangempay_account_unable_to_use_rooted">Unable to use on rooted device</string>
|
||||
<string name="tangempay_card_details_add_funds">Add funds</string>
|
||||
<string name="tangempay_card_details_add_funds_subtitle">Top-up options</string>
|
||||
<string name="tangempay_card_details_card_number">Card Number</string>
|
||||
|
|
@ -1478,6 +1480,7 @@
|
|||
<string name="tangempay_card_details_withdraw_in_progress_title">Withdrawal in progress</string>
|
||||
<string name="tangempay_change_pin_code">Change PIN-code</string>
|
||||
<string name="tangempay_come_back_if_forget_pin">Come back to the app if you forget it.</string>
|
||||
<string name="tangempay_factory_settings_warning_title">I understand that I will completely lose access to my Tangem Pay Card and all funds on it without the possibility of recovery</string>
|
||||
<string name="tangempay_failed_to_issue_card">Failed to issue card</string>
|
||||
<string name="tangempay_failed_to_issue_card_retry_description">A technical error has occurred, please try again by clicking the button below.</string>
|
||||
<string name="tangempay_failed_to_issue_card_support_description">A technical error has occurred, please contact support.</string>
|
||||
|
|
@ -1508,10 +1511,10 @@
|
|||
<string name="tangempay_payment_account_sync_needed">Payment account sync needed</string>
|
||||
<string name="tangempay_service_unavailable_description">We’re fixing a technical issue. Please try again later.</string>
|
||||
<string name="tangempay_service_unavailable_title">Service temporarily unavailable</string>
|
||||
<string name="tangempay_service_unreachable_try_later">The service is currently unreachable. Please try again later.</string>
|
||||
<string name="tangempay_service_unreachable_try_later">Unable to display details. However, card payments are still working.</string>
|
||||
<string name="tangempay_sync_needed">Sync needed</string>
|
||||
<string name="tangempay_tangem_visa_card">Tangem Visa Card</string>
|
||||
<string name="tangempay_temporarily_unavailable">Tangem Pay is temporarily unavailable</string>
|
||||
<string name="tangempay_temporarily_unavailable">Tangem Pay is temporarily unreachable</string>
|
||||
<string name="tangempay_title">Tangem Pay</string>
|
||||
<string name="tangempay_use_tangem_device_to_restore_payment_account">Use your card or ring to restore access to your payment account</string>
|
||||
<string name="tangempay_your_pin_code">Your PIN code</string>
|
||||
|
|
@ -1729,7 +1732,7 @@
|
|||
<string name="wallet_create_scan_question">Using a Tangem Wallet already?</string>
|
||||
<string name="wallet_create_scan_title">Scan now</string>
|
||||
<string name="wallet_create_title">Pick a wallet setup method</string>
|
||||
<string name="wallet_import_buy_question">Want to purchase Tangem Wallet?</string>
|
||||
<string name="wallet_import_buy_question">Want to buy a Tangem Wallet?</string>
|
||||
<string name="wallet_import_buy_title">Buy now</string>
|
||||
<string name="wallet_import_google_drive_description">Recover existing wallet via Google Drive backup</string>
|
||||
<string name="wallet_import_google_drive_title">Import from Google Drive</string>
|
||||
|
|
@ -1959,7 +1962,7 @@
|
|||
<string name="welcome_create_wallet_mobile_description_full">Create or import a software wallet on your phone.</string>
|
||||
<string name="welcome_create_wallet_mobile_title">Start with Mobile Wallet</string>
|
||||
<string name="welcome_create_wallet_other_method">Other method</string>
|
||||
<string name="welcome_create_wallet_use_hardware_description">Use Tangem Hardware Wallet</string>
|
||||
<string name="welcome_create_wallet_use_hardware_description">Use a Tangem hardware wallet</string>
|
||||
<string name="welcome_create_wallet_use_hardware_title">Learn more & buy</string>
|
||||
<string name="welcome_interrupted_backup_alert_discard">Discard</string>
|
||||
<string name="welcome_interrupted_backup_alert_message">You have an interrupted backup. Do you want to resume?</string>
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
|
|||
override suspend fun swapTransactionSent(
|
||||
userWallet: UserWallet,
|
||||
fromCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toAddress: String,
|
||||
payInAddress: String,
|
||||
txId: String,
|
||||
txHash: String,
|
||||
txExtraId: String?,
|
||||
|
|
@ -289,7 +289,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
|
|||
txId = txId,
|
||||
fromNetwork = currency.network.backendId,
|
||||
fromAddress = status.networkAddress?.defaultAddress?.value.orEmpty(),
|
||||
payinAddress = toAddress,
|
||||
payinAddress = payInAddress,
|
||||
payinExtraId = txExtraId,
|
||||
txHash = txHash,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -3,21 +3,21 @@ package com.tangem.domain.apptheme.model
|
|||
/**
|
||||
* Enumerates the possible modes for the application's theme.
|
||||
*/
|
||||
enum class AppThemeMode {
|
||||
enum class AppThemeMode(val value: String) {
|
||||
/**
|
||||
* Forces the dark theme mode regardless of system settings.
|
||||
*/
|
||||
FORCE_DARK,
|
||||
FORCE_DARK("Dark"),
|
||||
|
||||
/**
|
||||
* Forces the light theme mode regardless of system settings.
|
||||
*/
|
||||
FORCE_LIGHT,
|
||||
FORCE_LIGHT("Light"),
|
||||
|
||||
/**
|
||||
* Follows the system-wide theme mode.
|
||||
*/
|
||||
FOLLOW_SYSTEM,
|
||||
FOLLOW_SYSTEM("System"),
|
||||
|
||||
;
|
||||
|
||||
|
|
@ -30,6 +30,6 @@ enum class AppThemeMode {
|
|||
/**
|
||||
* List of available [AppThemeMode]s.
|
||||
* */
|
||||
val available: List<AppThemeMode> = values().toList()
|
||||
val available: List<AppThemeMode> = entries
|
||||
}
|
||||
}
|
||||
|
|
@ -86,6 +86,13 @@ fun UserWallet.requireHotWallet(): UserWallet.Hot {
|
|||
?: error("This user wallet is not a hot wallet")
|
||||
}
|
||||
|
||||
fun UserWallet.isImported(): Boolean {
|
||||
return when (this) {
|
||||
is UserWallet.Cold -> isImported
|
||||
is UserWallet.Hot -> true
|
||||
}
|
||||
}
|
||||
|
||||
fun UserWallet.copy(name: String = this.name, walletId: UserWalletId = this.walletId): UserWallet = when (this) {
|
||||
is UserWallet.Cold -> this.copy(name = name, walletId = walletId)
|
||||
is UserWallet.Hot -> this.copy(name = name, walletId = walletId)
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ interface SwapRepositoryV2 {
|
|||
*
|
||||
* @param userWallet selected user wallet
|
||||
* @param fromCryptoCurrencyStatus currency status being swapped from
|
||||
* @param toAddress swap destination address
|
||||
* @param payInAddress swap destination address
|
||||
* @param txId transaction id in ExpressApi
|
||||
* @param txHash transaction hash in blockchain
|
||||
* @param txExtraId extra transaction id in ExpressApi
|
||||
|
|
@ -101,7 +101,7 @@ interface SwapRepositoryV2 {
|
|||
suspend fun swapTransactionSent(
|
||||
userWallet: UserWallet,
|
||||
fromCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toAddress: String,
|
||||
payInAddress: String,
|
||||
txId: String,
|
||||
txHash: String,
|
||||
txExtraId: String?,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,10 @@ class GetSwapSupportedPairsUseCase(
|
|||
swapTxType = swapTxType,
|
||||
)
|
||||
|
||||
val filteredOutInitial = cryptoCurrencyList.filterNot { it.id.rawNetworkId == initialCurrency.id.rawNetworkId }
|
||||
val filteredOutInitial = cryptoCurrencyList.filterNot { currency ->
|
||||
currency.id.rawNetworkId == initialCurrency.id.rawNetworkId &&
|
||||
currency.id.rawCurrencyId == initialCurrency.id.rawCurrencyId
|
||||
}
|
||||
|
||||
val fromGroup = pairs.groupPairs(
|
||||
initialCurrency = initialCurrency,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ class SwapTransactionSentUseCase(
|
|||
swapDataTransactionModel: SwapDataTransactionModel,
|
||||
provider: ExpressProvider,
|
||||
txHash: String,
|
||||
payInAddress: String,
|
||||
timestamp: Long,
|
||||
swapTxType: SwapTxType,
|
||||
) = Either.catch {
|
||||
|
|
@ -63,7 +64,7 @@ class SwapTransactionSentUseCase(
|
|||
swapRepositoryV2.swapTransactionSent(
|
||||
userWallet = userWallet,
|
||||
fromCryptoCurrencyStatus = fromCryptoCurrencyStatus,
|
||||
toAddress = swapDataTransactionModel.txTo,
|
||||
payInAddress = payInAddress,
|
||||
txId = swapDataTransactionModel.txId,
|
||||
txHash = txHash,
|
||||
txExtraId = swapDataTransactionModel.txExtraId,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.domain.yield.supply.models
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class YieldSupplyFee(
|
||||
val value: BigDecimal,
|
||||
val isHighFee: Boolean = false,
|
||||
)
|
||||
|
|
@ -2,6 +2,8 @@ package com.tangem.domain.yield.supply.usecase
|
|||
|
||||
import arrow.core.Either
|
||||
import arrow.core.Either.Companion.catch
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
|
@ -10,6 +12,7 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository
|
|||
import com.tangem.domain.transaction.FeeRepository
|
||||
import com.tangem.domain.yield.supply.YieldSupplyConst.YIELD_SUPPLY_EVM_CONSTANT_GAS_LIMIT
|
||||
import com.tangem.domain.yield.supply.fixFee
|
||||
import com.tangem.domain.yield.supply.models.YieldSupplyFee
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
|
|
@ -25,7 +28,7 @@ class YieldSupplyGetCurrentFeeUseCase(
|
|||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
): Either<Throwable, BigDecimal> = catch {
|
||||
): Either<Throwable, YieldSupplyFee> = catch {
|
||||
val feeWithoutGas = feeRepository.getEthereumFeeWithoutGas(userWalletId, cryptoCurrencyStatus.currency)
|
||||
|
||||
val fiatRate = cryptoCurrencyStatus.value.fiatRate ?: error("Fiat rate is missing")
|
||||
|
|
@ -60,6 +63,23 @@ class YieldSupplyGetCurrentFeeUseCase(
|
|||
|
||||
val tokenValue = rateRatio.multiply(nativeGas.amount.value)
|
||||
|
||||
tokenValue.stripTrailingZeros()
|
||||
val isEthereum = cryptoCurrencyStatus.currency
|
||||
.network.id.rawId.value == Blockchain.Ethereum.id
|
||||
|
||||
val isHighFee = if (isEthereum) {
|
||||
val maxFeePerGas = (feeWithoutGas as? Fee.Ethereum.EIP1559)?.maxFeePerGas ?: 0.toBigInteger()
|
||||
maxFeePerGas >= HIGH_ETHEREUM_FEE
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
YieldSupplyFee(
|
||||
value = tokenValue.stripTrailingZeros(),
|
||||
isHighFee = isHighFee,
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val HIGH_ETHEREUM_FEE = 400_000_000.toBigInteger()
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,9 @@ class YieldSupplyGetRewardsBalanceUseCase(
|
|||
val fiatRate = status.value.fiatRate
|
||||
|
||||
if (cryptoAmount?.compareTo(BigDecimal.ZERO) == 0) {
|
||||
emit(
|
||||
YieldSupplyRewardBalance(fiatBalance = null, cryptoBalance = null),
|
||||
)
|
||||
return@flow
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,384 @@
|
|||
package com.tangem.domain.yield.supply.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.network.NetworkAddress
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.transaction.FeeRepository
|
||||
import com.tangem.domain.utils.convertToSdkAmount
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
import java.math.RoundingMode
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class YieldSupplyGetCurrentFeeUseCaseTest {
|
||||
|
||||
private val feeRepository: FeeRepository = mockk()
|
||||
private val quotesRepository: QuotesRepository = mockk()
|
||||
private val currenciesRepository: CurrenciesRepository = mockk()
|
||||
|
||||
private lateinit var useCase: YieldSupplyGetCurrentFeeUseCase
|
||||
|
||||
private val userWalletId = UserWalletId("abcdef012345")
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
useCase = YieldSupplyGetCurrentFeeUseCase(
|
||||
feeRepository = feeRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
currenciesRepository = currenciesRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN valid inputs on non-ethereum WHEN invoke THEN returns fee value and not high`() = runTest {
|
||||
val rawNetworkId = Blockchain.BSC.id
|
||||
val tokenDecimals = 8
|
||||
val nativeDecimals = 18
|
||||
val token = createToken(rawNetworkId = rawNetworkId, decimals = tokenDecimals)
|
||||
val cryptoStatus = createStatus(token = token, fiatRate = BigDecimal("2.00"))
|
||||
val nativeCoin = createCoin(rawNetworkId = rawNetworkId, decimals = nativeDecimals)
|
||||
val nativeFiatRate = BigDecimal("4.00")
|
||||
|
||||
val maxFeePerGas = BigInteger.valueOf(1_000_000_000L)
|
||||
val feeWithoutGas = Fee.Ethereum.EIP1559(
|
||||
maxFeePerGas = maxFeePerGas,
|
||||
priorityFee = BigInteger.ONE,
|
||||
gasLimit = BigInteger.ZERO,
|
||||
amount = BigDecimal.ZERO.convertToSdkAmount(cryptoStatus),
|
||||
)
|
||||
|
||||
coEvery { feeRepository.getEthereumFeeWithoutGas(userWalletId, token) } returns feeWithoutGas
|
||||
coEvery {
|
||||
currenciesRepository.getNetworkCoin(
|
||||
userWalletId = userWalletId,
|
||||
networkId = token.network.id,
|
||||
derivationPath = token.network.derivationPath,
|
||||
)
|
||||
} returns nativeCoin
|
||||
coEvery {
|
||||
quotesRepository.getMultiQuoteSyncOrNull(setOf(nativeCoin.id.rawCurrencyId!!))
|
||||
} returns setOf(
|
||||
QuoteStatus(
|
||||
rawCurrencyId = nativeCoin.id.rawCurrencyId!!,
|
||||
value = QuoteStatus.Data(
|
||||
source = StatusSource.ACTUAL,
|
||||
fiatRate = nativeFiatRate,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val gasLimit = BigInteger.valueOf(350_000)
|
||||
val nativeGasValue = maxFeePerGas.multiply(gasLimit).toBigDecimal().movePointLeft(nativeDecimals)
|
||||
val rateRatio = nativeFiatRate.divide(cryptoStatus.value.fiatRate!!, tokenDecimals, RoundingMode.HALF_UP)
|
||||
val expectedTokenValue = rateRatio.multiply(nativeGasValue).stripTrailingZeros()
|
||||
|
||||
val result = useCase(userWalletId, cryptoStatus)
|
||||
|
||||
assertThat(result.isRight()).isTrue()
|
||||
val fee = (result as Either.Right).value
|
||||
assertThat(fee.value).isEqualTo(expectedTokenValue)
|
||||
assertThat(fee.isHighFee).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN ethereum with high gas WHEN invoke THEN returns high fee flag`() = runTest {
|
||||
val rawNetworkId = Blockchain.Ethereum.id
|
||||
val tokenDecimals = 8
|
||||
val nativeDecimals = 18
|
||||
val token = createToken(rawNetworkId = rawNetworkId, decimals = tokenDecimals)
|
||||
val cryptoStatus = createStatus(token = token, fiatRate = BigDecimal("2.00"))
|
||||
val nativeCoin = createCoin(rawNetworkId = rawNetworkId, decimals = nativeDecimals)
|
||||
val nativeFiatRate = BigDecimal("4.00")
|
||||
|
||||
val maxFeePerGas = BigInteger.valueOf(400_000_000L) // threshold
|
||||
val feeWithoutGas = Fee.Ethereum.EIP1559(
|
||||
maxFeePerGas = maxFeePerGas,
|
||||
priorityFee = BigInteger.ONE,
|
||||
gasLimit = BigInteger.ZERO,
|
||||
amount = BigDecimal.ZERO.convertToSdkAmount(cryptoStatus),
|
||||
)
|
||||
|
||||
coEvery { feeRepository.getEthereumFeeWithoutGas(userWalletId, token) } returns feeWithoutGas
|
||||
coEvery {
|
||||
currenciesRepository.getNetworkCoin(
|
||||
userWalletId = userWalletId,
|
||||
networkId = token.network.id,
|
||||
derivationPath = token.network.derivationPath,
|
||||
)
|
||||
} returns nativeCoin
|
||||
coEvery {
|
||||
quotesRepository.getMultiQuoteSyncOrNull(setOf(nativeCoin.id.rawCurrencyId!!))
|
||||
} returns setOf(
|
||||
QuoteStatus(
|
||||
rawCurrencyId = nativeCoin.id.rawCurrencyId!!,
|
||||
value = QuoteStatus.Data(
|
||||
source = StatusSource.ACTUAL,
|
||||
fiatRate = nativeFiatRate,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val gasLimit = BigInteger.valueOf(350_000)
|
||||
val nativeGasValue = maxFeePerGas.multiply(gasLimit).toBigDecimal().movePointLeft(nativeDecimals)
|
||||
val rateRatio = nativeFiatRate.divide(cryptoStatus.value.fiatRate!!, tokenDecimals, RoundingMode.HALF_UP)
|
||||
val expectedTokenValue = rateRatio.multiply(nativeGasValue).stripTrailingZeros()
|
||||
|
||||
val result = useCase(userWalletId, cryptoStatus)
|
||||
|
||||
assertThat(result.isRight()).isTrue()
|
||||
val fee = (result as Either.Right).value
|
||||
assertThat(fee.value).isEqualTo(expectedTokenValue)
|
||||
assertThat(fee.isHighFee).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN token fiat rate missing WHEN invoke THEN returns error`() = runTest {
|
||||
val rawNetworkId = Blockchain.BSC.id
|
||||
val token = createToken(rawNetworkId = rawNetworkId, decimals = 8)
|
||||
val cryptoStatus = createStatus(token = token, fiatRate = null)
|
||||
|
||||
coEvery { feeRepository.getEthereumFeeWithoutGas(userWalletId, token) } returns Fee.Ethereum.EIP1559(
|
||||
maxFeePerGas = BigInteger.ONE,
|
||||
priorityFee = BigInteger.ONE,
|
||||
gasLimit = BigInteger.ZERO,
|
||||
amount = BigDecimal.ZERO.convertToSdkAmount(
|
||||
createStatus(token = token, fiatRate = BigDecimal.ONE),
|
||||
),
|
||||
)
|
||||
|
||||
val result = useCase(userWalletId, cryptoStatus)
|
||||
|
||||
assertThat(result.isLeft()).isTrue()
|
||||
val error = (result as Either.Left).value
|
||||
assertThat(error).isInstanceOf(IllegalStateException::class.java)
|
||||
assertThat(error.message).isEqualTo("Fiat rate is missing")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN native quotes unavailable WHEN invoke THEN returns error`() = runTest {
|
||||
val rawNetworkId = Blockchain.BSC.id
|
||||
val token = createToken(rawNetworkId = rawNetworkId, decimals = 8)
|
||||
val cryptoStatus = createStatus(token = token, fiatRate = BigDecimal("2.00"))
|
||||
val nativeCoin = createCoin(rawNetworkId = rawNetworkId, decimals = 18)
|
||||
|
||||
coEvery { feeRepository.getEthereumFeeWithoutGas(userWalletId, token) } returns Fee.Ethereum.EIP1559(
|
||||
maxFeePerGas = BigInteger.valueOf(1_000_000_000L),
|
||||
priorityFee = BigInteger.ONE,
|
||||
gasLimit = BigInteger.ZERO,
|
||||
amount = BigDecimal.ZERO.convertToSdkAmount(cryptoStatus),
|
||||
)
|
||||
coEvery {
|
||||
currenciesRepository.getNetworkCoin(
|
||||
userWalletId = userWalletId,
|
||||
networkId = token.network.id,
|
||||
derivationPath = token.network.derivationPath,
|
||||
)
|
||||
} returns nativeCoin
|
||||
coEvery { quotesRepository.getMultiQuoteSyncOrNull(setOf(nativeCoin.id.rawCurrencyId!!)) } returns null
|
||||
|
||||
val result = useCase(userWalletId, cryptoStatus)
|
||||
|
||||
assertThat(result.isLeft()).isTrue()
|
||||
val error = (result as Either.Left).value
|
||||
assertThat(error).isInstanceOf(IllegalStateException::class.java)
|
||||
assertThat(error.message).isEqualTo("Quotes for native coin are unavailable")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN empty quotes list WHEN invoke THEN returns error`() = runTest {
|
||||
val rawNetworkId = Blockchain.BSC.id
|
||||
val token = createToken(rawNetworkId = rawNetworkId, decimals = 8)
|
||||
val cryptoStatus = createStatus(token = token, fiatRate = BigDecimal("2.00"))
|
||||
val nativeCoin = createCoin(rawNetworkId = rawNetworkId, decimals = 18)
|
||||
|
||||
coEvery { feeRepository.getEthereumFeeWithoutGas(userWalletId, token) } returns Fee.Ethereum.EIP1559(
|
||||
maxFeePerGas = BigInteger.valueOf(1_000_000_000L),
|
||||
priorityFee = BigInteger.ONE,
|
||||
gasLimit = BigInteger.ZERO,
|
||||
amount = BigDecimal.ZERO.convertToSdkAmount(cryptoStatus),
|
||||
)
|
||||
coEvery {
|
||||
currenciesRepository.getNetworkCoin(
|
||||
userWalletId = userWalletId,
|
||||
networkId = token.network.id,
|
||||
derivationPath = token.network.derivationPath,
|
||||
)
|
||||
} returns nativeCoin
|
||||
coEvery { quotesRepository.getMultiQuoteSyncOrNull(setOf(nativeCoin.id.rawCurrencyId!!)) } returns emptySet()
|
||||
|
||||
val result = useCase(userWalletId, cryptoStatus)
|
||||
|
||||
assertThat(result.isLeft()).isTrue()
|
||||
val error = (result as Either.Left).value
|
||||
assertThat(error).isInstanceOf(IllegalStateException::class.java)
|
||||
assertThat(error.message).isEqualTo("Empty quotes list for native coin")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN native fiat rate non-positive WHEN invoke THEN returns error`() = runTest {
|
||||
val rawNetworkId = Blockchain.BSC.id
|
||||
val token = createToken(rawNetworkId = rawNetworkId, decimals = 8)
|
||||
val cryptoStatus = createStatus(token = token, fiatRate = BigDecimal("2.00"))
|
||||
val nativeCoin = createCoin(rawNetworkId = rawNetworkId, decimals = 18)
|
||||
|
||||
coEvery { feeRepository.getEthereumFeeWithoutGas(userWalletId, token) } returns Fee.Ethereum.EIP1559(
|
||||
maxFeePerGas = BigInteger.valueOf(1_000_000_000L),
|
||||
priorityFee = BigInteger.ONE,
|
||||
gasLimit = BigInteger.ZERO,
|
||||
amount = BigDecimal.ZERO.convertToSdkAmount(cryptoStatus),
|
||||
)
|
||||
coEvery {
|
||||
currenciesRepository.getNetworkCoin(
|
||||
userWalletId = userWalletId,
|
||||
networkId = token.network.id,
|
||||
derivationPath = token.network.derivationPath,
|
||||
)
|
||||
} returns nativeCoin
|
||||
coEvery {
|
||||
quotesRepository.getMultiQuoteSyncOrNull(setOf(nativeCoin.id.rawCurrencyId!!))
|
||||
} returns setOf(
|
||||
QuoteStatus(
|
||||
rawCurrencyId = nativeCoin.id.rawCurrencyId!!,
|
||||
value = QuoteStatus.Data(
|
||||
source = StatusSource.ACTUAL,
|
||||
fiatRate = BigDecimal.ZERO, // non-positive
|
||||
priceChange = BigDecimal.ZERO,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val result = useCase(userWalletId, cryptoStatus)
|
||||
|
||||
assertThat(result.isLeft()).isTrue()
|
||||
val error = (result as Either.Left).value
|
||||
assertThat(error).isInstanceOf(IllegalArgumentException::class.java)
|
||||
assertThat(error.message).isEqualTo("Native fiat rate must be > 0")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN token fiat rate non-positive WHEN invoke THEN returns error`() = runTest {
|
||||
val rawNetworkId = Blockchain.BSC.id
|
||||
val token = createToken(rawNetworkId = rawNetworkId, decimals = 8)
|
||||
val cryptoStatus = createStatus(token = token, fiatRate = BigDecimal.ZERO) // non-positive
|
||||
|
||||
coEvery { feeRepository.getEthereumFeeWithoutGas(userWalletId, token) } returns Fee.Ethereum.EIP1559(
|
||||
maxFeePerGas = BigInteger.ONE,
|
||||
priorityFee = BigInteger.ONE,
|
||||
gasLimit = BigInteger.ZERO,
|
||||
amount = BigDecimal.ZERO.convertToSdkAmount(
|
||||
createStatus(token = token, fiatRate = BigDecimal.ONE),
|
||||
),
|
||||
)
|
||||
|
||||
val result = useCase(userWalletId, cryptoStatus)
|
||||
|
||||
assertThat(result.isLeft()).isTrue()
|
||||
val error = (result as Either.Left).value
|
||||
assertThat(error).isInstanceOf(IllegalArgumentException::class.java)
|
||||
assertThat(error.message).isEqualTo("Fiat rate for token must be > 0")
|
||||
}
|
||||
|
||||
private fun createToken(rawNetworkId: String, decimals: Int): CryptoCurrency.Token {
|
||||
val derivationPath = Network.DerivationPath.None
|
||||
val network = Network(
|
||||
id = Network.ID(value = rawNetworkId, derivationPath = derivationPath),
|
||||
backendId = rawNetworkId,
|
||||
name = rawNetworkId,
|
||||
currencySymbol = rawNetworkId.take(3).uppercase(),
|
||||
derivationPath = derivationPath,
|
||||
isTestnet = false,
|
||||
standardType = Network.StandardType.Unspecified("UNSPECIFIED"),
|
||||
hasFiatFeeRate = true,
|
||||
canHandleTokens = true,
|
||||
transactionExtrasType = Network.TransactionExtrasType.NONE,
|
||||
nameResolvingType = Network.NameResolvingType.NONE,
|
||||
)
|
||||
|
||||
return CryptoCurrency.Token(
|
||||
id = CryptoCurrency.ID(
|
||||
prefix = CryptoCurrency.ID.Prefix.TOKEN_PREFIX,
|
||||
body = CryptoCurrency.ID.Body.NetworkId(rawNetworkId),
|
||||
suffix = CryptoCurrency.ID.Suffix.RawID(rawNetworkId),
|
||||
),
|
||||
network = network,
|
||||
name = "TEST_TOKEN",
|
||||
symbol = "TTK",
|
||||
decimals = decimals,
|
||||
iconUrl = null,
|
||||
isCustom = false,
|
||||
contractAddress = "0xToken",
|
||||
)
|
||||
}
|
||||
|
||||
private fun createCoin(rawNetworkId: String, decimals: Int): CryptoCurrency.Coin {
|
||||
val derivationPath = Network.DerivationPath.None
|
||||
val network = Network(
|
||||
id = Network.ID(value = rawNetworkId, derivationPath = derivationPath),
|
||||
backendId = rawNetworkId,
|
||||
name = rawNetworkId,
|
||||
currencySymbol = rawNetworkId.take(3).uppercase(),
|
||||
derivationPath = derivationPath,
|
||||
isTestnet = false,
|
||||
standardType = Network.StandardType.Unspecified("UNSPECIFIED"),
|
||||
hasFiatFeeRate = true,
|
||||
canHandleTokens = true,
|
||||
transactionExtrasType = Network.TransactionExtrasType.NONE,
|
||||
nameResolvingType = Network.NameResolvingType.NONE,
|
||||
)
|
||||
|
||||
return CryptoCurrency.Coin(
|
||||
id = CryptoCurrency.ID(
|
||||
prefix = CryptoCurrency.ID.Prefix.COIN_PREFIX,
|
||||
body = CryptoCurrency.ID.Body.NetworkId(rawNetworkId),
|
||||
suffix = CryptoCurrency.ID.Suffix.RawID(rawNetworkId),
|
||||
),
|
||||
network = network,
|
||||
name = "TEST_COIN",
|
||||
symbol = "TCN",
|
||||
decimals = decimals,
|
||||
iconUrl = null,
|
||||
isCustom = false,
|
||||
)
|
||||
}
|
||||
|
||||
private fun createStatus(token: CryptoCurrency.Token, fiatRate: BigDecimal?): CryptoCurrencyStatus {
|
||||
return CryptoCurrencyStatus(
|
||||
currency = token,
|
||||
value = CryptoCurrencyStatus.Custom(
|
||||
amount = BigDecimal.ZERO,
|
||||
fiatAmount = BigDecimal.ZERO,
|
||||
fiatRate = fiatRate,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
networkAddress = NetworkAddress.Single(
|
||||
defaultAddress = NetworkAddress.Address(
|
||||
value = "0x0000000000000000000000000000000000000000",
|
||||
type = NetworkAddress.Address.Type.Primary,
|
||||
),
|
||||
),
|
||||
sources = CryptoCurrencyStatus.Sources(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package com.tangem.domain.yield.supply.usecase
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.anyDecimals
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
|
|
@ -18,8 +18,8 @@ import io.mockk.coEvery
|
|||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.advanceTimeBy
|
||||
|
|
@ -49,6 +49,38 @@ class YieldSupplyGetRewardsBalanceUseCaseTest {
|
|||
assertThat(emissions).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN zero amount WHEN invoke THEN emit null balances`() = runTest {
|
||||
val network = createNetwork()
|
||||
val token = createToken(network)
|
||||
val status = CryptoCurrencyStatus(
|
||||
currency = token,
|
||||
value = CryptoCurrencyStatus.Custom(
|
||||
amount = BigDecimal.ZERO,
|
||||
fiatAmount = null,
|
||||
fiatRate = BigDecimal.ONE,
|
||||
priceChange = null,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
networkAddress = NetworkAddress.Single(
|
||||
NetworkAddress.Address(value = "0xabc", type = NetworkAddress.Address.Type.Primary),
|
||||
),
|
||||
sources = CryptoCurrencyStatus.Sources(),
|
||||
),
|
||||
)
|
||||
|
||||
val dispatcherProvider = testDispatcherProvider(this)
|
||||
val useCase = YieldSupplyGetRewardsBalanceUseCase(repository, dispatcherProvider)
|
||||
val appCurrency = AppCurrency.Default
|
||||
|
||||
val emissions = useCase(status, appCurrency).toList()
|
||||
assertThat(emissions).hasSize(1)
|
||||
assertThat(emissions[0].fiatBalance).isNull()
|
||||
assertThat(emissions[0].cryptoBalance).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN coin currency WHEN invoke THEN emit nothing`() = runTest {
|
||||
val network = createNetwork()
|
||||
|
|
|
|||
|
|
@ -291,6 +291,8 @@ internal class AddStakingNotificationsTransformer(
|
|||
}
|
||||
|
||||
private fun MutableList<NotificationUM>.addTonInitializeAccountNotification(prevState: StakingUiState) {
|
||||
if (prevState.actionType !is StakingActionCommonType.Enter) return
|
||||
|
||||
val isAccountInitialized = isAccountInitializedProvider.invoke()
|
||||
val cryptoCurrencyNetworkIdValue = cryptoCurrencyStatusProvider().currency.network.rawId
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.features.swap.v2.impl.sendviaswap.confirm.model
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplySendCallData
|
||||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressOperationType
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
|
|
@ -152,6 +154,13 @@ internal class SwapTransactionSender @AssistedInject constructor(
|
|||
return
|
||||
}
|
||||
|
||||
val ethereumCallData = (txData.extras as? EthereumTransactionExtras)?.callData
|
||||
val payInAddress = if (ethereumCallData is EthereumYieldSupplySendCallData) {
|
||||
ethereumCallData.destinationAddress
|
||||
} else {
|
||||
txData.destinationAddress
|
||||
}
|
||||
|
||||
sendTransactionUseCase(
|
||||
txData = txData,
|
||||
userWallet = userWallet,
|
||||
|
|
@ -169,6 +178,7 @@ internal class SwapTransactionSender @AssistedInject constructor(
|
|||
swapDataTransactionModel = swapTransaction,
|
||||
provider = provider,
|
||||
txHash = txHash,
|
||||
payInAddress = payInAddress,
|
||||
timestamp = timestamp,
|
||||
swapTxType = SwapTxType.SendWithSwap,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.swap.domain
|
|||
import android.util.Base64
|
||||
import arrow.core.Either
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.solana.SolanaTransactionHelper
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
|
|
@ -11,6 +12,7 @@ import com.tangem.blockchain.common.TransactionExtras
|
|||
import com.tangem.blockchain.common.smartcontract.SmartContractCallDataProviderFactory
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplySendCallData
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.blockchainsdk.utils.toNetworkId
|
||||
|
|
@ -883,6 +885,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
Timber.e(error, "Failed to create swap dex tx data")
|
||||
return SwapTransactionState.Error.UnknownError
|
||||
}
|
||||
|
||||
return handleSwapResult(
|
||||
provider = provider,
|
||||
networkId = networkId,
|
||||
|
|
@ -894,7 +897,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
amount = amount,
|
||||
derivationPath = derivationPath,
|
||||
txData = txData,
|
||||
payInAddress = txData.destinationAddress,
|
||||
payInAddress = getPayoutAddress(txData),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -1108,7 +1111,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
txId = exchangeDataCex.txId,
|
||||
fromNetwork = currencyToSend.currency.network.backendId,
|
||||
fromAddress = cexFromAddress,
|
||||
payInAddress = txData.destinationAddress,
|
||||
payInAddress = getPayoutAddress(txData),
|
||||
txHash = txHash,
|
||||
payInExtraId = exchangeDataCex.txExtraId,
|
||||
)
|
||||
|
|
@ -2349,6 +2352,15 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getPayoutAddress(txData: TransactionData.Uncompiled): String {
|
||||
val ethereumCallData = (txData.extras as? EthereumTransactionExtras)?.callData
|
||||
return if (ethereumCallData is EthereumYieldSupplySendCallData) {
|
||||
ethereumCallData.destinationAddress
|
||||
} else {
|
||||
txData.destinationAddress
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val INCREASE_GAS_LIMIT_FOR_DEX = 112 // 12%
|
||||
private const val INCREASE_GAS_LIMIT_FOR_SEND = 105 // 5%
|
||||
|
|
|
|||
|
|
@ -43,18 +43,31 @@ sealed class SwapEvents(
|
|||
params = mapOf("Send Token" to sendToken, "Receive Token" to receiveToken),
|
||||
)
|
||||
|
||||
class ButtonGivePermissionClicked : SwapEvents(event = "Button - Give permission")
|
||||
data class ButtonGivePermissionClicked(
|
||||
val sendToken: String,
|
||||
val receiveToken: String,
|
||||
val provider: SwapProvider,
|
||||
) : SwapEvents(
|
||||
event = "Button - Give permission",
|
||||
params = mapOf(
|
||||
"Send Token" to sendToken,
|
||||
"Receive Token" to receiveToken,
|
||||
"Provider" to provider.name,
|
||||
),
|
||||
)
|
||||
|
||||
data class ButtonPermissionApproveClicked(
|
||||
val sendToken: String,
|
||||
val receiveToken: String,
|
||||
val approveType: ApproveType,
|
||||
val provider: SwapProvider,
|
||||
) : SwapEvents(
|
||||
event = "Button - Permission Approve",
|
||||
params = mapOf(
|
||||
"Send Token" to sendToken,
|
||||
"Receive Token" to receiveToken,
|
||||
"Type" to if (approveType == ApproveType.LIMITED) "Current Transaction" else "Unlimited",
|
||||
"Provider" to provider.name,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -145,4 +158,17 @@ sealed class SwapEvents(
|
|||
data object Recommended : PromoState("Recommended")
|
||||
}
|
||||
}
|
||||
|
||||
data class NoticePermissionNeeded(
|
||||
val sendToken: String,
|
||||
val receiveToken: String,
|
||||
val provider: SwapProvider,
|
||||
) : SwapEvents(
|
||||
event = "Notice - Permission Needed",
|
||||
params = mapOf(
|
||||
"Send Token" to sendToken,
|
||||
"Receive Token" to receiveToken,
|
||||
"Provider" to provider.name,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -192,6 +192,7 @@ internal class SwapModel @Inject constructor(
|
|||
private val toTokenBalanceJobHolder = JobHolder()
|
||||
|
||||
private var isAmountChangedByUser: Boolean = false
|
||||
private var lastPermissionNotificationTokens: Pair<String, String>? = null
|
||||
|
||||
val currentScreen: SwapNavScreen
|
||||
get() = swapRouter.currentScreen
|
||||
|
|
@ -547,60 +548,101 @@ internal class SwapModel @Inject constructor(
|
|||
private fun setupLoadedState(provider: SwapProvider, state: SwapState, fromToken: CryptoCurrencyStatus) {
|
||||
when (state) {
|
||||
is SwapState.QuotesLoadedState -> {
|
||||
fillLoadedDataState(state, state.permissionState, state.swapDataModel)
|
||||
val loadedStates = dataState.lastLoadedSwapStates.getLastLoadedSuccessStates()
|
||||
val bestRatedProviderId = findBestQuoteProvider(loadedStates)?.providerId ?: provider.providerId
|
||||
uiState = stateBuilder.createQuotesLoadedState(
|
||||
uiStateHolder = uiState,
|
||||
quoteModel = state,
|
||||
fromToken = fromToken.currency,
|
||||
feeCryptoCurrencyStatus = dataState.feePaidCryptoCurrency,
|
||||
swapProvider = provider,
|
||||
bestRatedProviderId = bestRatedProviderId,
|
||||
isNeedBestRateBadge = dataState.lastLoadedSwapStates.consideredProvidersStates().size > 1,
|
||||
selectedFeeType = dataState.selectedFee?.feeType ?: FeeType.NORMAL,
|
||||
isReverseSwapPossible = isReverseSwapPossible(),
|
||||
needApplyFCARestrictions = userCountry.needApplyFCARestrictions(),
|
||||
hideFee = tangemPayInput?.isWithdrawal == true,
|
||||
)
|
||||
if (uiState.notifications.any { it is SwapNotificationUM.Error.UnableToCoverFeeWarning }) {
|
||||
analyticsEventHandler.send(
|
||||
SwapEvents.NoticeNotEnoughFee(
|
||||
token = initialCurrencyFrom.symbol,
|
||||
blockchain = fromToken.currency.network.name,
|
||||
),
|
||||
)
|
||||
}
|
||||
setupQuotesLoadedUiState(provider, state, fromToken)
|
||||
sendAnalyticsForNotifications(fromToken)
|
||||
updatePermissionNotificationState(state)
|
||||
}
|
||||
is SwapState.EmptyAmountState -> {
|
||||
val toTokenStatus = dataState.toCryptoCurrency
|
||||
uiState = stateBuilder.createQuotesEmptyAmountState(
|
||||
uiStateHolder = uiState,
|
||||
emptyAmountState = state,
|
||||
fromTokenStatus = fromToken,
|
||||
toTokenStatus = toTokenStatus,
|
||||
isReverseSwapPossible = isReverseSwapPossible(),
|
||||
toAccount = dataState.toAccount,
|
||||
)
|
||||
setupEmptyAmountUiState(state, fromToken)
|
||||
lastPermissionNotificationTokens = null
|
||||
}
|
||||
is SwapState.SwapError -> {
|
||||
singleTaskScheduler.cancelTask()
|
||||
uiState = stateBuilder.createQuotesErrorState(
|
||||
uiStateHolder = uiState,
|
||||
swapProvider = provider,
|
||||
fromToken = state.fromTokenInfo,
|
||||
toToken = dataState.toCryptoCurrency,
|
||||
expressDataError = state.error,
|
||||
includeFeeInAmount = state.includeFeeInAmount,
|
||||
isReverseSwapPossible = isReverseSwapPossible(),
|
||||
needApplyFCARestrictions = userCountry.needApplyFCARestrictions(),
|
||||
toAccount = dataState.toAccount,
|
||||
)
|
||||
sendErrorAnalyticsEvent(state.error, provider)
|
||||
setupErrorUiState(provider, state)
|
||||
lastPermissionNotificationTokens = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupQuotesLoadedUiState(
|
||||
provider: SwapProvider,
|
||||
state: SwapState.QuotesLoadedState,
|
||||
fromToken: CryptoCurrencyStatus,
|
||||
) {
|
||||
fillLoadedDataState(state, state.permissionState, state.swapDataModel)
|
||||
val loadedStates = dataState.lastLoadedSwapStates.getLastLoadedSuccessStates()
|
||||
val bestRatedProviderId = findBestQuoteProvider(loadedStates)?.providerId ?: provider.providerId
|
||||
uiState = stateBuilder.createQuotesLoadedState(
|
||||
uiStateHolder = uiState,
|
||||
quoteModel = state,
|
||||
fromToken = fromToken.currency,
|
||||
feeCryptoCurrencyStatus = dataState.feePaidCryptoCurrency,
|
||||
swapProvider = provider,
|
||||
bestRatedProviderId = bestRatedProviderId,
|
||||
isNeedBestRateBadge = dataState.lastLoadedSwapStates.consideredProvidersStates().size > 1,
|
||||
selectedFeeType = dataState.selectedFee?.feeType ?: FeeType.NORMAL,
|
||||
isReverseSwapPossible = isReverseSwapPossible(),
|
||||
needApplyFCARestrictions = userCountry.needApplyFCARestrictions(),
|
||||
hideFee = tangemPayInput?.isWithdrawal == true,
|
||||
)
|
||||
}
|
||||
|
||||
private fun sendAnalyticsForNotifications(fromToken: CryptoCurrencyStatus) {
|
||||
if (uiState.notifications.any { it is SwapNotificationUM.Error.UnableToCoverFeeWarning }) {
|
||||
analyticsEventHandler.send(
|
||||
SwapEvents.NoticeNotEnoughFee(
|
||||
token = initialCurrencyFrom.symbol,
|
||||
blockchain = fromToken.currency.network.name,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePermissionNotificationState(state: SwapState.QuotesLoadedState) {
|
||||
val fromTokenId = state.fromTokenInfo.cryptoCurrencyStatus
|
||||
.currency.id.value
|
||||
val toTokenId = state.toTokenInfo.cryptoCurrencyStatus
|
||||
.currency.id.value
|
||||
val currentTokenPair = Pair(fromTokenId, toTokenId)
|
||||
|
||||
when {
|
||||
uiState.notifications.none { it is SwapNotificationUM.Info.PermissionNeeded } -> {
|
||||
lastPermissionNotificationTokens = null
|
||||
}
|
||||
lastPermissionNotificationTokens != currentTokenPair -> {
|
||||
sendNoticePermissionNeededEvent()
|
||||
lastPermissionNotificationTokens = currentTokenPair
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupEmptyAmountUiState(state: SwapState.EmptyAmountState, fromToken: CryptoCurrencyStatus) {
|
||||
val toTokenStatus = dataState.toCryptoCurrency
|
||||
uiState = stateBuilder.createQuotesEmptyAmountState(
|
||||
uiStateHolder = uiState,
|
||||
emptyAmountState = state,
|
||||
fromTokenStatus = fromToken,
|
||||
toTokenStatus = toTokenStatus,
|
||||
isReverseSwapPossible = isReverseSwapPossible(),
|
||||
toAccount = dataState.toAccount,
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupErrorUiState(provider: SwapProvider, state: SwapState.SwapError) {
|
||||
singleTaskScheduler.cancelTask()
|
||||
uiState = stateBuilder.createQuotesErrorState(
|
||||
uiStateHolder = uiState,
|
||||
swapProvider = provider,
|
||||
fromToken = state.fromTokenInfo,
|
||||
toToken = dataState.toCryptoCurrency,
|
||||
expressDataError = state.error,
|
||||
includeFeeInAmount = state.includeFeeInAmount,
|
||||
isReverseSwapPossible = isReverseSwapPossible(),
|
||||
needApplyFCARestrictions = userCountry.needApplyFCARestrictions(),
|
||||
toAccount = dataState.toAccount,
|
||||
)
|
||||
sendErrorAnalyticsEvent(state.error, provider)
|
||||
}
|
||||
|
||||
private fun sendErrorAnalyticsEvent(error: ExpressDataError, provider: SwapProvider) {
|
||||
val receiveToken = dataState.toCryptoCurrency?.currency?.let { currency ->
|
||||
"${currency.network.backendId}:${currency.symbol}"
|
||||
|
|
@ -1342,7 +1384,7 @@ internal class SwapModel @Inject constructor(
|
|||
onReduceByAmount = ::onReduceAmountClicked,
|
||||
openPermissionBottomSheet = {
|
||||
singleTaskScheduler.cancelTask()
|
||||
analyticsEventHandler.send(SwapEvents.ButtonGivePermissionClicked())
|
||||
sendGivePermissionClickedEvent()
|
||||
uiState = stateBuilder.showPermissionBottomSheet(uiState) {
|
||||
startLoadingQuotesFromLastState(isSilent = true)
|
||||
analyticsEventHandler.send(SwapEvents.ButtonPermissionCancelClicked())
|
||||
|
|
@ -1603,19 +1645,46 @@ internal class SwapModel @Inject constructor(
|
|||
}.map { currencyStatus -> currencyStatus.currency }.contains(chosen.currency)
|
||||
}
|
||||
|
||||
private fun sendNoticePermissionNeededEvent() {
|
||||
val sendTokenSymbol = dataState.fromCryptoCurrency?.currency?.symbol ?: return
|
||||
val receiveTokenSymbol = dataState.toCryptoCurrency?.currency?.symbol ?: return
|
||||
val provider = dataState.selectedProvider ?: return
|
||||
analyticsEventHandler.send(
|
||||
SwapEvents.NoticePermissionNeeded(
|
||||
sendToken = sendTokenSymbol,
|
||||
receiveToken = receiveTokenSymbol,
|
||||
provider = provider,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun sendGivePermissionClickedEvent() {
|
||||
val sendTokenSymbol = dataState.fromCryptoCurrency?.currency?.symbol ?: return
|
||||
val receiveTokenSymbol = dataState.toCryptoCurrency?.currency?.symbol ?: return
|
||||
val provider = dataState.selectedProvider ?: return
|
||||
analyticsEventHandler.send(
|
||||
SwapEvents.ButtonGivePermissionClicked(
|
||||
sendToken = sendTokenSymbol,
|
||||
receiveToken = receiveTokenSymbol,
|
||||
provider = provider,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun sendPermissionApproveClickedEvent() {
|
||||
val sendTokenSymbol = dataState.fromCryptoCurrency?.currency?.symbol
|
||||
val receiveTokenSymbol = dataState.toCryptoCurrency?.currency?.symbol
|
||||
val approveType = uiState.permissionState.getApproveTypeOrNull()
|
||||
if (sendTokenSymbol != null && receiveTokenSymbol != null && approveType != null) {
|
||||
analyticsEventHandler.send(
|
||||
SwapEvents.ButtonPermissionApproveClicked(
|
||||
sendToken = sendTokenSymbol,
|
||||
receiveToken = receiveTokenSymbol,
|
||||
approveType = approveType,
|
||||
),
|
||||
)
|
||||
}
|
||||
val sendTokenSymbol = dataState.fromCryptoCurrency?.currency?.symbol ?: return
|
||||
val receiveTokenSymbol = dataState.toCryptoCurrency?.currency?.symbol ?: return
|
||||
val approveType = uiState.permissionState.getApproveTypeOrNull() ?: return
|
||||
val provider = dataState.selectedProvider ?: return
|
||||
|
||||
analyticsEventHandler.send(
|
||||
SwapEvents.ButtonPermissionApproveClicked(
|
||||
sendToken = sendTokenSymbol,
|
||||
receiveToken = receiveTokenSymbol,
|
||||
approveType = approveType,
|
||||
provider = provider,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateWalletBalance() {
|
||||
|
|
|
|||
|
|
@ -98,8 +98,16 @@ internal class TokenDetailsLoadedBalanceConverter(
|
|||
stakingCryptoAmount,
|
||||
currentState.selectedBalanceType,
|
||||
),
|
||||
displayYieldSupplyFiatBalance = (currentState as? TokenDetailsBalanceBlockState.Content)
|
||||
?.displayYieldSupplyFiatBalance,
|
||||
displayYieldSupplyFiatBalance = if (status.value.yieldSupplyStatus?.isActive == true) {
|
||||
(currentState as? TokenDetailsBalanceBlockState.Content)?.displayYieldSupplyFiatBalance
|
||||
} else {
|
||||
null
|
||||
},
|
||||
displayYieldSupplyCryptoBalance = if (status.value.yieldSupplyStatus?.isActive == true) {
|
||||
(currentState as? TokenDetailsBalanceBlockState.Content)?.displayYieldSupplyCryptoBalance
|
||||
} else {
|
||||
null
|
||||
},
|
||||
balanceSegmentedButtonConfig = currentState.balanceSegmentedButtonConfig,
|
||||
onBalanceSelect = clickIntents::onBalanceSelect,
|
||||
selectedBalanceType = currentState.selectedBalanceType,
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ dependencies {
|
|||
implementation(projects.domain.transaction)
|
||||
implementation(projects.domain.yieldSupply)
|
||||
implementation(projects.domain.yieldSupply.models)
|
||||
implementation(projects.domain.appTheme)
|
||||
implementation(projects.domain.appTheme.models)
|
||||
|
||||
/** Feature Apis */
|
||||
implementation(projects.features.details.api)
|
||||
|
|
|
|||
|
|
@ -13,12 +13,11 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.supplier.SingleAccountListSupplier
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
import com.tangem.domain.apptheme.GetAppThemeModeUseCase
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import com.tangem.domain.models.wallet.*
|
||||
import com.tangem.domain.nft.ObserveAndClearNFTCacheIfNeedUseCase
|
||||
import com.tangem.domain.notifications.GetIsHuaweiDeviceWithoutGoogleServicesUseCase
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
|
|
@ -100,6 +99,7 @@ internal class WalletModel @Inject constructor(
|
|||
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val tangemPayMainScreenCustomerInfoUseCase: TangemPayMainScreenCustomerInfoUseCase,
|
||||
private val getAppThemeModeUseCase: GetAppThemeModeUseCase,
|
||||
private val trackingContextProxy: TrackingContextProxy,
|
||||
private val singleAccountListSupplier: SingleAccountListSupplier,
|
||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
|
|
@ -114,17 +114,13 @@ internal class WalletModel @Inject constructor(
|
|||
|
||||
private val walletsUpdateJobHolder = JobHolder()
|
||||
private val refreshWalletJobHolder = JobHolder()
|
||||
private var needToRefreshWallet = false
|
||||
private val clearNFTCacheJobHolder = JobHolder()
|
||||
private val updateTangemPayJobHolder = JobHolder()
|
||||
|
||||
private var needToRefreshWallet = false
|
||||
private var expressTxStatusTaskScheduler = SingleTaskScheduler<Unit>()
|
||||
|
||||
init {
|
||||
if (!hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
analyticsEventsHandler.send(WalletScreenAnalyticsEvent.MainScreen.ScreenOpenedLegacy())
|
||||
}
|
||||
|
||||
updateMarketToggle()
|
||||
suggestToOpenMarkets()
|
||||
|
||||
|
|
@ -305,10 +301,14 @@ internal class WalletModel @Inject constructor(
|
|||
} else {
|
||||
null
|
||||
}
|
||||
val result = getAppThemeModeUseCase().firstOrNull()
|
||||
val theme = result?.getOrElse { AppThemeMode.FOLLOW_SYSTEM } ?: AppThemeMode.FOLLOW_SYSTEM
|
||||
analyticsEventsHandler.send(
|
||||
WalletScreenAnalyticsEvent.MainScreen.ScreenOpened(
|
||||
hasMobileWallet = hasMobileWallet,
|
||||
accountsCount = accountsCount,
|
||||
theme = theme.value,
|
||||
isImported = selectedWallet.isImported(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,18 +51,23 @@ sealed class WalletScreenAnalyticsEvent {
|
|||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent(category = "Main Screen", event = event, params = params) {
|
||||
|
||||
class ScreenOpenedLegacy : MainScreen(
|
||||
event = "Screen opened",
|
||||
)
|
||||
|
||||
data class ScreenOpened(
|
||||
private val hasMobileWallet: Boolean,
|
||||
private val accountsCount: Int?,
|
||||
val theme: String,
|
||||
val isImported: Boolean,
|
||||
) : MainScreen(
|
||||
event = "Screen opened",
|
||||
params = buildMap {
|
||||
put("Mobile Wallet", if (hasMobileWallet) "Yes" else "No")
|
||||
if (accountsCount != null) put("Accounts Count", accountsCount.toString())
|
||||
put("App Theme", theme)
|
||||
val seedPhrase = if (isImported) {
|
||||
"Seed Phrase"
|
||||
} else {
|
||||
"Seedless"
|
||||
}
|
||||
put("Wallet Type", seedPhrase)
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.analytics.utils
|
|||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isImported
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
|
||||
|
|
@ -32,11 +33,4 @@ internal class SelectedWalletAnalyticsSender @Inject constructor(
|
|||
|
||||
else -> WalletScreenAnalyticsEvent.MainScreen.WalletSelected(userWallet.isImported())
|
||||
}
|
||||
|
||||
private fun UserWallet.isImported(): Boolean {
|
||||
return when (this) {
|
||||
is UserWallet.Cold -> isImported
|
||||
is UserWallet.Hot -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -283,7 +283,7 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
|||
YieldSupplyActiveFeeContentTransformer(
|
||||
cryptoCurrencyStatus = cryptoStatus,
|
||||
appCurrency = appCurrency,
|
||||
feeValue = currentFee,
|
||||
feeValue = currentFee.value,
|
||||
maxNetworkFee = maxFee,
|
||||
analyticsHandler = analyticsHandler,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ internal class YieldSupplyNotificationsComponent(
|
|||
Modifier.padding(top = 16.dp)
|
||||
},
|
||||
containerColor = TangemTheme.colors.background.action,
|
||||
iconTint = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@ import java.math.BigDecimal
|
|||
data class YieldSupplyNotificationData(
|
||||
val feeValue: BigDecimal?,
|
||||
val feeError: GetFeeError?,
|
||||
val shouldShowHighFeeNotification: Boolean = false,
|
||||
)
|
||||
|
|
@ -74,6 +74,10 @@ internal class YieldSupplyNotificationsModel @Inject constructor(
|
|||
dustValue = null,
|
||||
onReload = params.callback::onFeeReload,
|
||||
)
|
||||
|
||||
if (data.shouldShowHighFeeNotification) {
|
||||
add(NotificationUM.Info.YieldSupplyHighNetworkFee)
|
||||
}
|
||||
}
|
||||
|
||||
if (notifications.any { it is NotificationUM.Error.TokenExceedsBalance }) {
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
|
|||
updatedTransactionList = updatedTransactionList,
|
||||
feeValue = feeSum,
|
||||
maxNetworkFee = maxFee,
|
||||
estimatedFeeValueInTokenCurrency = estimatedFee,
|
||||
estimatedFeeValueInTokenCurrency = estimatedFee.value,
|
||||
minAmount = minAmount,
|
||||
),
|
||||
)
|
||||
|
|
@ -198,6 +198,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
|
|||
data = YieldSupplyNotificationData(
|
||||
feeValue = feeSum,
|
||||
feeError = null,
|
||||
shouldShowHighFeeNotification = estimatedFee.isHighFee,
|
||||
),
|
||||
)
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue