Updated on 2026-08-14

This commit is contained in:
Tangem 2025-06-05 21:52:04 +04:00
parent 37d7721d3e
commit 43c6359d2f
25 changed files with 390 additions and 78 deletions

View file

@ -18,5 +18,5 @@ data class EvmTransactionScanRequest(
data class RpcData( data class RpcData(
@Json(name = "jsonrpc") val jsonrpc: String = "2.0", @Json(name = "jsonrpc") val jsonrpc: String = "2.0",
@Json(name = "method") val method: String, @Json(name = "method") val method: String,
@Json(name = "params") val params: String, @Json(name = "params") val params: List<Map<String, String>>,
) )

View file

@ -5,7 +5,7 @@ import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class AccountSummaryResponse( data class AccountSummaryResponse(
@Json(name = "assets_diffs") val assetsDiffs: List<AssetDiff>, @Json(name = "assets_diffs") val assetsDiffs: List<AssetDiff>?,
@Json(name = "exposures") val exposures: List<Exposure>, @Json(name = "exposures") val exposures: List<Exposure>?,
@Json(name = "traces") val traces: List<Trace>?, @Json(name = "traces") val traces: List<Trace>?,
) )

View file

@ -11,7 +11,7 @@ data class Trace(
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class Exposed( data class Exposed(
@Json(name = "token_id") val tokenId: String, @Json(name = "token_id") val tokenId: String?,
@Json(name = "logo_url") val logoUrl: String?, @Json(name = "logo_url") val logoUrl: String?,
) )

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<resources> <resources>
<string name="_warning_stelar_token_required_min_coin_reserve">Erforderliche Mindest-XLM-Reserve %1$s</string>
<string name="action_buttons_buy_empty_search_message">Du kannst Deinen Token nicht finden? Gehe zum Bereich „Markt“ auf der Hauptseite und fügen diesen zum kaufen im Portfolio hinzu.</string> <string name="action_buttons_buy_empty_search_message">Du kannst Deinen Token nicht finden? Gehe zum Bereich „Markt“ auf der Hauptseite und fügen diesen zum kaufen im Portfolio hinzu.</string>
<string name="action_buttons_sell_empty_search_message">Du kannst Deinen Token nicht finden? Gehe zum Bereich „Markt“ auf der Hauptseite und fügen diesen zum verkaufen im Portfolio hinzu.</string> <string name="action_buttons_sell_empty_search_message">Du kannst Deinen Token nicht finden? Gehe zum Bereich „Markt“ auf der Hauptseite und fügen diesen zum verkaufen im Portfolio hinzu.</string>
<string name="action_buttons_sell_navigation_bar_title">Verkaufen</string> <string name="action_buttons_sell_navigation_bar_title">Verkaufen</string>
@ -337,6 +336,7 @@
<string name="express_more_providers_soon">Weitere Anbieter folgen in Kürze</string> <string name="express_more_providers_soon">Weitere Anbieter folgen in Kürze</string>
<string name="express_provider">Anbieter</string> <string name="express_provider">Anbieter</string>
<string name="express_provider_best_rate">Bester Preis</string> <string name="express_provider_best_rate">Bester Preis</string>
<string name="express_provider_fca_warning_list">Warnliste der FCA</string>
<string name="express_provider_max_amount">Verfügbar bis zu %s</string> <string name="express_provider_max_amount">Verfügbar bis zu %s</string>
<string name="express_provider_min_amount">Erhältlich bei %s</string> <string name="express_provider_min_amount">Erhältlich bei %s</string>
<string name="express_provider_not_available">Für dieses Paar nicht verfügbar</string> <string name="express_provider_not_available">Für dieses Paar nicht verfügbar</string>
@ -1222,6 +1222,8 @@
<string name="warning_express_notification_invalid_reserve_amount_title">Der zu erhaltende Betrag muss mindestens %s betragen</string> <string name="warning_express_notification_invalid_reserve_amount_title">Der zu erhaltende Betrag muss mindestens %s betragen</string>
<string name="warning_express_pair_unavailable_message">Dies kann passieren, weil der Anbieter derzeit nicht in der Lage ist, dein ausgewähltes Paar zu swappen. Bitte warte einen Moment und versuche es später erneut. (Code %s)</string> <string name="warning_express_pair_unavailable_message">Dies kann passieren, weil der Anbieter derzeit nicht in der Lage ist, dein ausgewähltes Paar zu swappen. Bitte warte einen Moment und versuche es später erneut. (Code %s)</string>
<string name="warning_express_pair_unavailable_title">Ausgewähltes Paar vorübergehend nicht verfügbar</string> <string name="warning_express_pair_unavailable_title">Ausgewähltes Paar vorübergehend nicht verfügbar</string>
<string name="warning_express_providers_fca_warning_description">Einige Anbieter sind nicht von der britischen Finanzaufsichtsbehörde (FCA) zugelassen. Sie sollten den Umgang mit ihnen vermeiden.</string>
<string name="warning_express_providers_fca_warning_title">Warnliste der FCA</string>
<string name="warning_express_refresh_required_title">Service vorübergehend nicht verfügbar</string> <string name="warning_express_refresh_required_title">Service vorübergehend nicht verfügbar</string>
<string name="warning_express_too_maximum_amount_title">Die Menge der zu tauschenden Token darf folgende Werte nicht überschreiten %s</string> <string name="warning_express_too_maximum_amount_title">Die Menge der zu tauschenden Token darf folgende Werte nicht überschreiten %s</string>
<string name="warning_express_too_minimal_amount_title">Der zu tauschende Betrag muss mindestens %s betragen</string> <string name="warning_express_too_minimal_amount_title">Der zu tauschende Betrag muss mindestens %s betragen</string>
@ -1273,6 +1275,7 @@
<string name="warning_some_networks_unreachable_message">Wischen Sie nach unten, um zu aktualisieren, oder versuchen Sie es später erneut.</string> <string name="warning_some_networks_unreachable_message">Wischen Sie nach unten, um zu aktualisieren, oder versuchen Sie es später erneut.</string>
<string name="warning_some_networks_unreachable_title">Einige Netzwerke sind nicht erreichbar</string> <string name="warning_some_networks_unreachable_title">Einige Netzwerke sind nicht erreichbar</string>
<string name="warning_some_token_balances_not_updated">Einige Token-Guthaben konnten nicht aktualisiert werden</string> <string name="warning_some_token_balances_not_updated">Einige Token-Guthaben konnten nicht aktualisiert werden</string>
<string name="warning_stelar_token_required_min_coin_reserve">Erforderliche Mindest-XLM-Reserve %1$s</string>
<string name="warning_stellar_token_trustline_button_title">Trustline öffnen</string> <string name="warning_stellar_token_trustline_button_title">Trustline öffnen</string>
<string name="warning_stellar_token_trustline_subtiile">Trustline-Untermenü öffnen</string> <string name="warning_stellar_token_trustline_subtiile">Trustline-Untermenü öffnen</string>
<string name="warning_stellar_token_trustline_tiile">Trustline-Titel öffnen</string> <string name="warning_stellar_token_trustline_tiile">Trustline-Titel öffnen</string>

View file

@ -1117,6 +1117,7 @@
<string name="warning_express_notification_invalid_reserve_amount_title">El monto a recibir debe ser de al menos %s</string> <string name="warning_express_notification_invalid_reserve_amount_title">El monto a recibir debe ser de al menos %s</string>
<string name="warning_express_pair_unavailable_message">Esto puede suceder porque el proveedor actualmente no puede operar con el par que usted seleccionó. Espere un momento e inténtelo de nuevo. (Código %s)</string> <string name="warning_express_pair_unavailable_message">Esto puede suceder porque el proveedor actualmente no puede operar con el par que usted seleccionó. Espere un momento e inténtelo de nuevo. (Código %s)</string>
<string name="warning_express_pair_unavailable_title">El par seleccionado no está disponible temporalmente</string> <string name="warning_express_pair_unavailable_title">El par seleccionado no está disponible temporalmente</string>
<string name="warning_express_providers_fca_warning_description">Algunos proveedores no están autorizados por la Autoridad de Conducta Financiera (FCA) del Reino Unido. Deberías evitar tratar con ellos.</string>
<string name="warning_express_refresh_required_title">Servicio no disponible temporalmente</string> <string name="warning_express_refresh_required_title">Servicio no disponible temporalmente</string>
<string name="warning_express_too_maximum_amount_title">La cantidad de tokens a intercambiar no debe exceder %s</string> <string name="warning_express_too_maximum_amount_title">La cantidad de tokens a intercambiar no debe exceder %s</string>
<string name="warning_express_too_minimal_amount_title">El monto a cambiar debe ser de al menos %s</string> <string name="warning_express_too_minimal_amount_title">El monto a cambiar debe ser de al menos %s</string>

View file

@ -323,6 +323,7 @@
<string name="express_more_providers_soon">D\'autres fournisseurs arriveront bientôt.\nRestez branchés !</string> <string name="express_more_providers_soon">D\'autres fournisseurs arriveront bientôt.\nRestez branchés !</string>
<string name="express_provider">Fournisseur</string> <string name="express_provider">Fournisseur</string>
<string name="express_provider_best_rate">Meilleur taux</string> <string name="express_provider_best_rate">Meilleur taux</string>
<string name="express_provider_fca_warning_list">Liste davertissement de la FCA</string>
<string name="express_provider_max_amount">Disponible jusqu\'à %s</string> <string name="express_provider_max_amount">Disponible jusqu\'à %s</string>
<string name="express_provider_min_amount">Disponible à partir de %s</string> <string name="express_provider_min_amount">Disponible à partir de %s</string>
<string name="express_provider_not_available">Indisponible pour cette paire</string> <string name="express_provider_not_available">Indisponible pour cette paire</string>
@ -1148,6 +1149,8 @@
<string name="warning_express_notification_invalid_reserve_amount_title">Le montant à recevoir doit être d\'au moins %s</string> <string name="warning_express_notification_invalid_reserve_amount_title">Le montant à recevoir doit être d\'au moins %s</string>
<string name="warning_express_pair_unavailable_message">Cela peut se produire car le fournisseur n\'est actuellement pas en mesure d\'échanger la paire que vous avez sélectionnée. Veuillez patienter un instant et réessayer. (Code %s)</string> <string name="warning_express_pair_unavailable_message">Cela peut se produire car le fournisseur n\'est actuellement pas en mesure d\'échanger la paire que vous avez sélectionnée. Veuillez patienter un instant et réessayer. (Code %s)</string>
<string name="warning_express_pair_unavailable_title">La paire sélectionnée est temporairement indisponible</string> <string name="warning_express_pair_unavailable_title">La paire sélectionnée est temporairement indisponible</string>
<string name="warning_express_providers_fca_warning_description">Certains fournisseurs ne sont pas autorisés par la Financial Conduct Authority (FCA) du Royaume-Uni. Vous devriez éviter de traiter avec eux.</string>
<string name="warning_express_providers_fca_warning_title">Liste davertissement de la FCA</string>
<string name="warning_express_refresh_required_title">Service temporairement indisponible</string> <string name="warning_express_refresh_required_title">Service temporairement indisponible</string>
<string name="warning_express_too_maximum_amount_title">Le nombre de jetons à échanger ne doit pas dépasser %s</string> <string name="warning_express_too_maximum_amount_title">Le nombre de jetons à échanger ne doit pas dépasser %s</string>
<string name="warning_express_too_minimal_amount_title">Le montant à échanger doit être d\'au moins %s</string> <string name="warning_express_too_minimal_amount_title">Le montant à échanger doit être d\'au moins %s</string>

View file

@ -267,6 +267,7 @@
<string name="details_row_subtitle_signed_hashes_format">%sハッシュ</string> <string name="details_row_subtitle_signed_hashes_format">%sハッシュ</string>
<string name="details_row_title_cid">デバイスID</string> <string name="details_row_title_cid">デバイスID</string>
<string name="details_row_title_contact_to_support">サポートへのお問い合わせ</string> <string name="details_row_title_contact_to_support">サポートへのお問い合わせ</string>
<string name="details_row_title_contact_to_support_chat">サポートチャットを開く</string>
<string name="details_row_title_create_backup">他のカードをリンクする</string> <string name="details_row_title_create_backup">他のカードをリンクする</string>
<string name="details_row_title_currency">アプリ通貨</string> <string name="details_row_title_currency">アプリ通貨</string>
<string name="details_row_title_flip_to_hide">フリップして残高を非表示にする</string> <string name="details_row_title_flip_to_hide">フリップして残高を非表示にする</string>
@ -856,6 +857,8 @@
<string name="send_validation_invalid_amount">無効な金額</string> <string name="send_validation_invalid_amount">無効な金額</string>
<string name="send_validation_invalid_fee">手数料が残高を超えています</string> <string name="send_validation_invalid_fee">手数料が残高を超えています</string>
<string name="send_validation_invalid_total">合計金額が残高を超えています</string> <string name="send_validation_invalid_total">合計金額が残高を超えています</string>
<string name="send_with_swap_notification_text">トークンを送信すれば、送信中に変換されます。受信者は必要なものをシームレスに受け取ります。</string>
<string name="send_with_swap_title">スワップして送信</string>
<string name="sent_transaction_sent_title">取引が送信されました</string> <string name="sent_transaction_sent_title">取引が送信されました</string>
<string name="settings_card_settings_footer">設定したいカードまたはリングをスキャンするために準備してください。</string> <string name="settings_card_settings_footer">設定したいカードまたはリングをスキャンするために準備してください。</string>
<string name="settings_forget_wallet">ウォレット削除</string> <string name="settings_forget_wallet">ウォレット削除</string>
@ -1068,6 +1071,8 @@
<string name="transaction_history_transaction_from_address">送金元: %s</string> <string name="transaction_history_transaction_from_address">送金元: %s</string>
<string name="transaction_history_transaction_to_address">送金先: %s</string> <string name="transaction_history_transaction_to_address">送金先: %s</string>
<string name="transaction_history_transaction_validator">バリデーター: %s</string> <string name="transaction_history_transaction_validator">バリデーター: %s</string>
<string name="transaction_notifications_warning_description">通知は有効になっていますが、デバイスの設定で通知を許可するまでは機能しません。</string>
<string name="transaction_notifications_warning_title">取引通知</string>
<string name="transfer_min_amount_error">最小%s</string> <string name="transfer_min_amount_error">最小%s</string>
<string name="transfer_notification_invalid_minimum_transaction_amount_text">最小取引金額は%1$sです。</string> <string name="transfer_notification_invalid_minimum_transaction_amount_text">最小取引金額は%1$sです。</string>
<string name="tron_will_be_send_token_fee_description">Tronネットワークの人気トークンの手数料は高い可能性があります。TRXをステーキングすると、取引コストを削減できる可能性があります。</string> <string name="tron_will_be_send_token_fee_description">Tronネットワークの人気トークンの手数料は高い可能性があります。TRXをステーキングすると、取引コストを削減できる可能性があります。</string>
@ -1234,6 +1239,7 @@
<string name="warning_rate_app_message">あなたのレビューは、Tangemウォレットをさらに良くするためのモチベーションになります</string> <string name="warning_rate_app_message">あなたのレビューは、Tangemウォレットをさらに良くするためのモチベーションになります</string>
<string name="warning_rate_app_title">Tangemを楽しんでいますか?</string> <string name="warning_rate_app_title">Tangemを楽しんでいますか?</string>
<string name="warning_receive_blocked_hedera_token_association_required_message">トークンを受け取る前に、トークンを関連付ける必要があります。</string> <string name="warning_receive_blocked_hedera_token_association_required_message">トークンを受け取る前に、トークンを関連付ける必要があります。</string>
<string name="warning_receive_blocked_stelar_token_trustline_required_message">トークンを受け取る前にトラストラインを開く必要があります</string>
<string name="warning_rent_fee_title">ネットワーク使用料が必要です</string> <string name="warning_rent_fee_title">ネットワーク使用料が必要です</string>
<string name="warning_seedphrase_action_required_title">対応が必要です</string> <string name="warning_seedphrase_action_required_title">対応が必要です</string>
<string name="warning_seedphrase_contacted_support">ウォレットの作成後、7日以内にアプリ経由でサポートに連絡しましたか連絡した場合、あるいは連絡したかわからない場合は、「はい」をクリックして指示に従ってください。</string> <string name="warning_seedphrase_contacted_support">ウォレットの作成後、7日以内にアプリ経由でサポートに連絡しましたか連絡した場合、あるいは連絡したかわからない場合は、「はい」をクリックして指示に従ってください。</string>
@ -1249,6 +1255,9 @@
<string name="warning_some_networks_unreachable_message">下にスワイプして更新するか、後でもう一度お試しください。</string> <string name="warning_some_networks_unreachable_message">下にスワイプして更新するか、後でもう一度お試しください。</string>
<string name="warning_some_networks_unreachable_title">一部のネットワークにアクセスできません</string> <string name="warning_some_networks_unreachable_title">一部のネットワークにアクセスできません</string>
<string name="warning_some_token_balances_not_updated">一部のトークン残高を更新できませんでした</string> <string name="warning_some_token_balances_not_updated">一部のトークン残高を更新できませんでした</string>
<string name="warning_stelar_token_required_min_coin_reserve">必要な最低XLMリザーブ %1$s</string>
<string name="warning_stellar_token_trustline_button_title">トラストラインを開く</string>
<string name="warning_stellar_token_trustline_tiile">トラストラインタイトルを開く</string>
<string name="warning_testnet_card_message">これはテストネットカードです。取引処理はできませんので、テストおよび開発目的でのみご利用ください。</string> <string name="warning_testnet_card_message">これはテストネットカードです。取引処理はできませんので、テストおよび開発目的でのみご利用ください。</string>
<string name="warning_testnet_card_title">テスト目的のみ</string> <string name="warning_testnet_card_title">テスト目的のみ</string>
<string name="warning_token_balance_not_updated">残高が古い可能性があります。ページを更新してください。</string> <string name="warning_token_balance_not_updated">残高が古い可能性があります。ページを更新してください。</string>

View file

@ -1246,6 +1246,9 @@
<string name="warning_some_networks_unreachable_message">Свайпните вниз для обновления или попробуйте позже.</string> <string name="warning_some_networks_unreachable_message">Свайпните вниз для обновления или попробуйте позже.</string>
<string name="warning_some_networks_unreachable_title">Некоторые сети недоступны</string> <string name="warning_some_networks_unreachable_title">Некоторые сети недоступны</string>
<string name="warning_some_token_balances_not_updated">Некоторые балансы токенов не удалось обновить</string> <string name="warning_some_token_balances_not_updated">Некоторые балансы токенов не удалось обновить</string>
<string name="warning_stellar_token_trustline_button_title">Открыть Trustline</string>
<string name="warning_stellar_token_trustline_subtiile">Согласно правилам сети, чтобы пополнить этот токен, необходимо сначала открыть Trustline — это позволит вашему кошельку принимать и хранить этот актив.</string>
<string name="warning_stellar_token_trustline_tiile">Откройте Trustline</string>
<string name="warning_testnet_card_message">Это Testnet карта. Он не может обрабатывать транзакции и используется только в целях тестирования и разработки.</string> <string name="warning_testnet_card_message">Это Testnet карта. Он не может обрабатывать транзакции и используется только в целях тестирования и разработки.</string>
<string name="warning_testnet_card_title">Только для целей тестирования</string> <string name="warning_testnet_card_title">Только для целей тестирования</string>
<string name="warning_token_balance_not_updated">Возможно, баланс устарел. Обновите страницу.</string> <string name="warning_token_balance_not_updated">Возможно, баланс устарел. Обновите страницу.</string>

View file

@ -329,6 +329,7 @@
<string name="express_more_providers_soon">Незабаром з\'являться нові провайдери.\nСлідкуйте за новинами!</string> <string name="express_more_providers_soon">Незабаром з\'являться нові провайдери.\nСлідкуйте за новинами!</string>
<string name="express_provider">Провайдер</string> <string name="express_provider">Провайдер</string>
<string name="express_provider_best_rate">Найкращий курс</string> <string name="express_provider_best_rate">Найкращий курс</string>
<string name="express_provider_fca_warning_list">Список попереджень FCA</string>
<string name="express_provider_max_amount">Доступно до %s</string> <string name="express_provider_max_amount">Доступно до %s</string>
<string name="express_provider_min_amount">Доступно від %s</string> <string name="express_provider_min_amount">Доступно від %s</string>
<string name="express_provider_not_available">Недоступно для цієї пари</string> <string name="express_provider_not_available">Недоступно для цієї пари</string>
@ -1140,6 +1141,8 @@
<string name="warning_express_notification_invalid_reserve_amount_title">Сума отримання не може бути меншою за %s</string> <string name="warning_express_notification_invalid_reserve_amount_title">Сума отримання не може бути меншою за %s</string>
<string name="warning_express_pair_unavailable_message">Це може статися тому, що провайдер наразі не може обміняти обрану пару. Будь ласка, зачекайте трохи та спробуйте ще раз. (Код %s)</string> <string name="warning_express_pair_unavailable_message">Це може статися тому, що провайдер наразі не може обміняти обрану пару. Будь ласка, зачекайте трохи та спробуйте ще раз. (Код %s)</string>
<string name="warning_express_pair_unavailable_title">Обрана пара тимчасово недоступна</string> <string name="warning_express_pair_unavailable_title">Обрана пара тимчасово недоступна</string>
<string name="warning_express_providers_fca_warning_description">Деякі провайдери не мають авторизації від Британського фінансового регулятора (FCA). Рекомендуємо уникати взаємодії з ними.</string>
<string name="warning_express_providers_fca_warning_title">Список попереджень FCA</string>
<string name="warning_express_refresh_required_title">Сервіс тимчасово недоступний</string> <string name="warning_express_refresh_required_title">Сервіс тимчасово недоступний</string>
<string name="warning_express_too_maximum_amount_title">Сума до обміну не повинна перевищувати %s</string> <string name="warning_express_too_maximum_amount_title">Сума до обміну не повинна перевищувати %s</string>
<string name="warning_express_too_minimal_amount_title">Сума для обміну має бути не менше %s</string> <string name="warning_express_too_minimal_amount_title">Сума для обміну має бути не менше %s</string>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<resources> <resources>
<string name="_warning_stelar_token_required_min_coin_reserve">Required minimum XLM reserve %1$s</string>
<string name="action_buttons_buy_empty_search_message">Cant find your token? Go to the Market section on the main page and add it to your portfolio for purchase</string> <string name="action_buttons_buy_empty_search_message">Cant find your token? Go to the Market section on the main page and add it to your portfolio for purchase</string>
<string name="action_buttons_sell_empty_search_message">Cant find your token? Go to the Market section on the main page and add it to your portfolio for selling.</string> <string name="action_buttons_sell_empty_search_message">Cant find your token? Go to the Market section on the main page and add it to your portfolio for selling.</string>
<string name="action_buttons_sell_navigation_bar_title">Sell</string> <string name="action_buttons_sell_navigation_bar_title">Sell</string>
@ -338,6 +337,7 @@
<string name="express_more_providers_soon">More providers will be available soon</string> <string name="express_more_providers_soon">More providers will be available soon</string>
<string name="express_provider">Provider</string> <string name="express_provider">Provider</string>
<string name="express_provider_best_rate">Best rate</string> <string name="express_provider_best_rate">Best rate</string>
<string name="express_provider_fca_warning_list">FCA Warning List</string>
<string name="express_provider_max_amount">Available up to %s</string> <string name="express_provider_max_amount">Available up to %s</string>
<string name="express_provider_min_amount">Available from %s</string> <string name="express_provider_min_amount">Available from %s</string>
<string name="express_provider_not_available">Unavailable for this pair</string> <string name="express_provider_not_available">Unavailable for this pair</string>
@ -864,6 +864,7 @@
<string name="send_summary_transaction_description_suffix_fee_covered">network fee will be covered by using %1$s energy</string> <string name="send_summary_transaction_description_suffix_fee_covered">network fee will be covered by using %1$s energy</string>
<string name="send_summary_transaction_description_suffix_fee_reduced">network fee will be reduced by spending %1$s energy</string> <string name="send_summary_transaction_description_suffix_fee_reduced">network fee will be reduced by spending %1$s energy</string>
<string name="send_summary_transaction_description_suffix_including">including a network fee of %1$s</string> <string name="send_summary_transaction_description_suffix_including">including a network fee of %1$s</string>
<string name="send_test_alert_title">asdflkdsl;kfasl;fn;lnf asdjfnasdk;jf dfk;jasdjf;kajsdnf</string>
<string name="send_transaction_success">Transaction has been successfully signed and sent to the blockchain node. Wallet balance will be updated in a while</string> <string name="send_transaction_success">Transaction has been successfully signed and sent to the blockchain node. Wallet balance will be updated in a while</string>
<string name="send_tron_account_activation_error">%1$s is an asset in the Tron network. To calculate the fee and make a transaction you need to deposit some Tron (TRX) in your account.</string> <string name="send_tron_account_activation_error">%1$s is an asset in the Tron network. To calculate the fee and make a transaction you need to deposit some Tron (TRX) in your account.</string>
<string name="send_validation_amount_exceeds_balance">Amount exceeds balance</string> <string name="send_validation_amount_exceeds_balance">Amount exceeds balance</string>
@ -1269,6 +1270,8 @@
<string name="warning_express_notification_invalid_reserve_amount_title">The amount to receive must be at least %s</string> <string name="warning_express_notification_invalid_reserve_amount_title">The amount to receive must be at least %s</string>
<string name="warning_express_pair_unavailable_message">This may occur because the provider is currently unable to exchange your selected pair. Please wait a moment and try again. (Code %s)</string> <string name="warning_express_pair_unavailable_message">This may occur because the provider is currently unable to exchange your selected pair. Please wait a moment and try again. (Code %s)</string>
<string name="warning_express_pair_unavailable_title">Selected pair temporarily unavailable</string> <string name="warning_express_pair_unavailable_title">Selected pair temporarily unavailable</string>
<string name="warning_express_providers_fca_warning_description">Some providers are not authorized by the UK Financial Conduct Authority. You should avoid dealing with them.</string>
<string name="warning_express_providers_fca_warning_title">FCA Warning List</string>
<string name="warning_express_refresh_required_title">Service temporarily unavailable</string> <string name="warning_express_refresh_required_title">Service temporarily unavailable</string>
<string name="warning_express_too_maximum_amount_title">The amount of tokens to be swapped must not exceed %s</string> <string name="warning_express_too_maximum_amount_title">The amount of tokens to be swapped must not exceed %s</string>
<string name="warning_express_too_minimal_amount_title">The amount to swap must be at least %s</string> <string name="warning_express_too_minimal_amount_title">The amount to swap must be at least %s</string>
@ -1304,7 +1307,7 @@
<string name="warning_rate_app_message">Your review keeps us motivated to make Tangem Wallet even better</string> <string name="warning_rate_app_message">Your review keeps us motivated to make Tangem Wallet even better</string>
<string name="warning_rate_app_title">Enjoying Tangem?</string> <string name="warning_rate_app_title">Enjoying Tangem?</string>
<string name="warning_receive_blocked_hedera_token_association_required_message">You must associate your token before receiving tokens</string> <string name="warning_receive_blocked_hedera_token_association_required_message">You must associate your token before receiving tokens</string>
<string name="warning_receive_blocked_stelar_token_trustline_required_message">You must open trustline before receiving tokens</string> <string name="warning_receive_blocked_stelar_token_trustline_required_message">You must open trustline for your token before receiving it</string>
<string name="warning_rent_fee_title">Network rent fee required</string> <string name="warning_rent_fee_title">Network rent fee required</string>
<string name="warning_seedphrase_action_required_title">Action required</string> <string name="warning_seedphrase_action_required_title">Action required</string>
<string name="warning_seedphrase_contacted_support">Did you contact support via the app within 7 days of creating your wallet? If yes, or if you\'re unsure, click \'Yes\' and follow the instructions.</string> <string name="warning_seedphrase_contacted_support">Did you contact support via the app within 7 days of creating your wallet? If yes, or if you\'re unsure, click \'Yes\' and follow the instructions.</string>
@ -1320,9 +1323,10 @@
<string name="warning_some_networks_unreachable_message">Swipe down to refresh or try again later.</string> <string name="warning_some_networks_unreachable_message">Swipe down to refresh or try again later.</string>
<string name="warning_some_networks_unreachable_title">Some networks are unreachable</string> <string name="warning_some_networks_unreachable_title">Some networks are unreachable</string>
<string name="warning_some_token_balances_not_updated">Some token balances could not be updated</string> <string name="warning_some_token_balances_not_updated">Some token balances could not be updated</string>
<string name="warning_stellar_token_trustline_button_title">Open trustline</string> <string name="warning_stelar_token_required_min_coin_reserve">Not enough %1$s. Top up your XLM account to associate this token</string>
<string name="warning_stellar_token_trustline_subtiile">Open trustline subtiile</string> <string name="warning_stellar_token_trustline_button_title">Enable Trustline</string>
<string name="warning_stellar_token_trustline_tiile">Open trustline title</string> <string name="warning_stellar_token_trustline_subtiile">According to network rules, you need to open a Trustline before depositing this token. It allows your wallet to accept and hold the asset.</string>
<string name="warning_stellar_token_trustline_tiile">Enable Trustline for this token</string>
<string name="warning_testnet_card_message">This is a Testnet card. It cannot process transactions and should only be used for testing and development purposes.</string> <string name="warning_testnet_card_message">This is a Testnet card. It cannot process transactions and should only be used for testing and development purposes.</string>
<string name="warning_testnet_card_title">For testing purposes only</string> <string name="warning_testnet_card_title">For testing purposes only</string>
<string name="warning_token_balance_not_updated">Balance may be outdated. Refresh the page.</string> <string name="warning_token_balance_not_updated">Balance may be outdated. Refresh the page.</string>
@ -1346,8 +1350,10 @@
<string name="wc_allow_to_spend">Allow to spend</string> <string name="wc_allow_to_spend">Allow to spend</string>
<string name="wc_common_address">Address</string> <string name="wc_common_address">Address</string>
<string name="wc_common_connect">Connect</string> <string name="wc_common_connect">Connect</string>
<string name="wc_common_loading">Loading</string>
<string name="wc_common_network">Network</string> <string name="wc_common_network">Network</string>
<string name="wc_common_networks">Networks</string> <string name="wc_common_networks">Networks</string>
<string name="wc_common_unlimited">Unlimited</string>
<string name="wc_common_wallet">Wallet</string> <string name="wc_common_wallet">Wallet</string>
<string name="wc_connected_networks">Connected networks</string> <string name="wc_connected_networks">Connected networks</string>
<string name="wc_connection_reqeust_can_view_balance">View your wallet balance and activity</string> <string name="wc_connection_reqeust_can_view_balance">View your wallet balance and activity</string>
@ -1364,6 +1370,7 @@
<string name="wc_disconnect_all_alert_desc">Text about discnected all dApps</string> <string name="wc_disconnect_all_alert_desc">Text about discnected all dApps</string>
<string name="wc_disconnect_all_alert_title">Disconect All dApps</string> <string name="wc_disconnect_all_alert_title">Disconect All dApps</string>
<string name="wc_estimated_wallet_changes">Estimated wallet changes</string> <string name="wc_estimated_wallet_changes">Estimated wallet changes</string>
<string name="wc_estimated_wallet_changes_not_simulated">The transaction couldn\'t be simulated. Please proceed with caution.</string>
<string name="wc_malicious_transaction">Malicious transaction</string> <string name="wc_malicious_transaction">Malicious transaction</string>
<string name="wc_missing_required_network_description">Add the %s network to your profile for this wallet</string> <string name="wc_missing_required_network_description">Add the %s network to your profile for this wallet</string>
<string name="wc_missing_required_network_title">The wallet has no required networks</string> <string name="wc_missing_required_network_title">The wallet has no required networks</string>

View file

@ -1,6 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="13dp" android:width="12dp"
android:height="13dp" android:height="12dp"
android:viewportWidth="13" android:viewportWidth="13"
android:viewportHeight="13"> android:viewportHeight="13">
<path <path

View file

@ -11,6 +11,7 @@ import com.tangem.datasource.api.common.blockaid.models.request.EvmTransactionSc
import com.tangem.datasource.api.common.blockaid.models.request.RpcData import com.tangem.datasource.api.common.blockaid.models.request.RpcData
import com.tangem.datasource.api.common.blockaid.models.request.SolanaTransactionScanRequest import com.tangem.datasource.api.common.blockaid.models.request.SolanaTransactionScanRequest
import com.tangem.datasource.api.common.blockaid.models.response.* import com.tangem.datasource.api.common.blockaid.models.response.*
import org.json.JSONArray
private const val SUCCESS_STATUS = "Success" private const val SUCCESS_STATUS = "Success"
private const val DOMAIN_CHECKED_STATUS = "hit" private const val DOMAIN_CHECKED_STATUS = "hit"
@ -43,20 +44,28 @@ internal object BlockAidMapper {
fun mapToEvmRequest(from: TransactionData): EvmTransactionScanRequest { fun mapToEvmRequest(from: TransactionData): EvmTransactionScanRequest {
return EvmTransactionScanRequest( return EvmTransactionScanRequest(
chain = from.chain, chain = from.chain.lowercase(),
accountAddress = from.accountAddress, accountAddress = from.accountAddress,
method = from.method, method = from.method,
data = RpcData( data = RpcData(
method = from.method, method = from.method,
params = (from.params as TransactionParams.Evm).params, params = parseParams((from.params as TransactionParams.Evm).params),
), ),
metadata = TransactionMetadata(from.domainUrl), metadata = TransactionMetadata(from.domainUrl),
) )
} }
private fun parseParams(rawParams: String): List<Map<String, String>> {
val jsonArray = JSONArray(rawParams)
return (0 until jsonArray.length()).map { index ->
val jsonObject = jsonArray.getJSONObject(index)
jsonObject.keys().asSequence().associateWith { key -> jsonObject.getString(key) }
}
}
fun mapToSolanaRequest(from: TransactionData): SolanaTransactionScanRequest { fun mapToSolanaRequest(from: TransactionData): SolanaTransactionScanRequest {
return SolanaTransactionScanRequest( return SolanaTransactionScanRequest(
chain = from.chain, chain = from.chain.lowercase(),
accountAddress = from.accountAddress, accountAddress = from.accountAddress,
metadata = TransactionMetadata(from.domainUrl), metadata = TransactionMetadata(from.domainUrl),
method = from.method, method = from.method,
@ -66,15 +75,19 @@ internal object BlockAidMapper {
private fun mapSimulationSuccessResult(from: AccountSummaryResponse): SimulationResult { private fun mapSimulationSuccessResult(from: AccountSummaryResponse): SimulationResult {
return when { return when {
from.assetsDiffs.isEmpty() && from.exposures.isNotEmpty() -> mapApproveTransaction(from.exposures) !from.assetsDiffs.isNullOrEmpty() -> mapSendReceiveTransaction(
from.assetsDiffs.isNotEmpty() && from.exposures.isEmpty() -> mapSendReceiveTransaction(from.assetsDiffs) from.assetsDiffs,
)
!from.exposures.isNullOrEmpty() -> mapApproveTransaction(
from.exposures,
)
!from.traces.isNullOrEmpty() -> mapNftSendReceiveTransaction(from.traces) !from.traces.isNullOrEmpty() -> mapNftSendReceiveTransaction(from.traces)
else -> SimulationResult.FailedToSimulate else -> SimulationResult.FailedToSimulate
} }
} }
private fun mapApproveTransaction(exposures: List<Exposure>): SimulationResult { private fun mapApproveTransaction(exposures: List<Exposure>?): SimulationResult {
val amounts = exposures.flatMap { exposure -> val amounts = exposures?.flatMap { exposure ->
val tokenInfo = TokenInfo( val tokenInfo = TokenInfo(
chainId = exposure.asset.chainId, chainId = exposure.asset.chainId,
logoUrl = exposure.asset.logoUrl, logoUrl = exposure.asset.logoUrl,
@ -86,25 +99,25 @@ internal object BlockAidMapper {
val approval = spender.approval?.hexToBigDecimal() val approval = spender.approval?.hexToBigDecimal()
spender.exposure.mapNotNull { detail -> spender.exposure.mapNotNull { detail ->
ApprovedAmount( ApprovedAmount(
approvedAmount = approval ?: detail.value.toBigDecimalOrNull() ?: return@mapNotNull null, approvedAmount = detail.value.toBigDecimalOrNull() ?: approval ?: return@mapNotNull null,
isUnlimited = isUnlimited, isUnlimited = isUnlimited,
tokenInfo = tokenInfo, tokenInfo = tokenInfo,
) )
} }
} }
} }
return if (amounts.isNotEmpty()) { return if (!amounts.isNullOrEmpty()) {
SimulationResult.Success(SimulationData.Approve(amounts)) SimulationResult.Success(SimulationData.Approve(amounts))
} else { } else {
SimulationResult.FailedToSimulate SimulationResult.FailedToSimulate
} }
} }
private fun mapSendReceiveTransaction(assetDiffs: List<AssetDiff>): SimulationResult { private fun mapSendReceiveTransaction(assetDiffs: List<AssetDiff>?): SimulationResult {
val sendInfo = arrayListOf<AmountInfo>() val sendInfo = arrayListOf<AmountInfo>()
val receiveInfo = arrayListOf<AmountInfo>() val receiveInfo = arrayListOf<AmountInfo>()
assetDiffs.forEach { diff -> assetDiffs?.forEach { diff ->
val token = TokenInfo( val token = TokenInfo(
chainId = diff.asset.chainId, chainId = diff.asset.chainId,
logoUrl = diff.asset.logoUrl, logoUrl = diff.asset.logoUrl,
@ -131,8 +144,10 @@ internal object BlockAidMapper {
} }
private fun mapNftSendReceiveTransaction(traces: List<Trace>?): SimulationResult { private fun mapNftSendReceiveTransaction(traces: List<Trace>?): SimulationResult {
val sendInfo = traces?.map { val sendInfo = traces?.mapNotNull {
AmountInfo.NonFungibleTokens(name = "${it.asset.name} #${it.exposed.tokenId}", logoUrl = it.exposed.logoUrl) it.exposed?.let { exposed ->
AmountInfo.NonFungibleTokens(name = "${it.asset.name} #${exposed.tokenId}", logoUrl = exposed.logoUrl)
}
} }
return if (!sendInfo.isNullOrEmpty()) { return if (!sendInfo.isNullOrEmpty()) {

View file

@ -5,6 +5,7 @@ import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
import com.tangem.domain.walletconnect.usecase.method.WcSignState import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase
import com.tangem.domain.walletconnect.usecase.method.WcTransactionUseCase
import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionUM import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
import com.tangem.utils.converter.Converter import com.tangem.utils.converter.Converter
@ -13,6 +14,7 @@ import javax.inject.Inject
internal class WcCommonTransactionUMConverter @Inject constructor( internal class WcCommonTransactionUMConverter @Inject constructor(
private val signTypedDataUMConverter: WcSignTypedDataUMConverter, private val signTypedDataUMConverter: WcSignTypedDataUMConverter,
private val signTransactionUMConverter: WcSignTransactionUMConverter, private val signTransactionUMConverter: WcSignTransactionUMConverter,
private val sendTransactionUMConverter: WcSendTransactionUMConverter,
) : Converter<WcCommonTransactionUMConverter.Input, WcCommonTransactionUM?> { ) : Converter<WcCommonTransactionUMConverter.Input, WcCommonTransactionUM?> {
override fun convert(value: Input): WcCommonTransactionUM? { override fun convert(value: Input): WcCommonTransactionUM? {
@ -38,7 +40,14 @@ internal class WcCommonTransactionUMConverter @Inject constructor(
else -> null else -> null
} }
} }
else -> TODO("[REDACTED_JIRA]") is WcTransactionUseCase -> sendTransactionUMConverter.convert(
WcSendTransactionUMConverter.Input(
useCase = value.useCase,
signState = value.signState,
actions = value.actions,
),
)
else -> null
} }
} }

View file

@ -0,0 +1,89 @@
package com.tangem.features.walletconnect.transaction.converter
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.walletconnect.model.WcEthMethod
import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.usecase.method.WcSignState
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
import com.tangem.domain.walletconnect.usecase.method.WcTransactionUseCase
import com.tangem.features.walletconnect.impl.R
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestBlockUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoItemUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoUM
import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionItemUM
import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionUM
import com.tangem.utils.converter.Converter
import kotlinx.collections.immutable.toImmutableList
import javax.inject.Inject
internal class WcSendTransactionUMConverter @Inject constructor(
private val appInfoContentUMConverter: WcTransactionAppInfoContentUMConverter,
private val networkInfoUMConverter: WcNetworkInfoUMConverter,
private val requestBlockUMConverter: WcTransactionRequestBlockUMConverter,
) : Converter<WcSendTransactionUMConverter.Input, WcSendTransactionUM?> {
override fun convert(value: Input): WcSendTransactionUM? = when (value.useCase.method) {
is WcEthMethod.SendTransaction,
is WcEthMethod.SignTransaction,
is WcSolanaMethod.SignAllTransaction,
is WcSolanaMethod.SignTransaction,
-> WcSendTransactionUM(
transaction = WcSendTransactionItemUM(
onDismiss = value.actions.onDismiss,
onSend = value.actions.onSign,
appInfo = appInfoContentUMConverter.convert(
WcTransactionAppInfoContentUMConverter.Input(
session = value.useCase.session,
onShowVerifiedAlert = value.actions.onShowVerifiedAlert,
),
),
walletName = value.useCase.session.wallet.name,
networkInfo = networkInfoUMConverter.convert(value.useCase.network),
address = value.useCase.walletAddress.toShortAddressText(),
estimatedWalletChanges = WcSendReceiveTransactionCheckResultsUM(),
isLoading = value.signState.domainStep == WcSignStep.Signing,
),
transactionRequestInfo = WcTransactionRequestInfoUM(
blocks = buildList {
add(
requestBlockUMConverter.convert(
WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest),
),
)
(value.useCase.method as? WcEthMethod.SendTransaction)?.transaction?.let { transaction ->
add(
WcTransactionRequestBlockUM(
info = buildList {
transaction.to?.let {
add(
WcTransactionRequestInfoItemUM(
title = resourceReference(R.string.wc_transaction_info_to_title),
description = it,
),
)
}
add(
WcTransactionRequestInfoItemUM(
title = resourceReference(R.string.send_from_wallet_android),
description = transaction.from,
),
)
}.toImmutableList(),
),
)
}
}.toImmutableList(),
onCopy = value.actions.onCopy,
),
)
else -> null
}
data class Input(
val useCase: WcTransactionUseCase,
val signState: WcSignState<*>,
val actions: WcTransactionActionsUM,
)
}

View file

@ -72,9 +72,6 @@ internal class WcSignTypedDataUMConverter @Inject constructor(
), ),
) )
private fun String.toShortAddressText() =
"${take(ADDRESS_FIRST_PART_LENGTH)}...${takeLast(ADDRESS_SECOND_PART_LENGTH)}"
data class Input( data class Input(
val useCase: WcMessageSignUseCase, val useCase: WcMessageSignUseCase,
val signState: WcSignState<*>, val signState: WcSignState<*>,
@ -82,3 +79,6 @@ internal class WcSignTypedDataUMConverter @Inject constructor(
val actions: WcTransactionActionsUM, val actions: WcTransactionActionsUM,
) )
} }
internal fun String.toShortAddressText() =
"${take(ADDRESS_FIRST_PART_LENGTH)}...${takeLast(ADDRESS_SECOND_PART_LENGTH)}"

View file

@ -3,6 +3,7 @@ package com.tangem.features.walletconnect.transaction.entity.blockaid
import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.TextReference
internal data class WcSendReceiveTransactionCheckResultsUM( internal data class WcSendReceiveTransactionCheckResultsUM(
val estimatedWalletChanges: WcEstimatedWalletChangesUM?, val estimatedWalletChanges: WcEstimatedWalletChangesUM? = null,
val notificationText: TextReference? = null, val notificationText: TextReference? = null,
val isLoading: Boolean = true,
) )

View file

@ -1,7 +1,7 @@
package com.tangem.features.walletconnect.transaction.entity.send package com.tangem.features.walletconnect.transaction.entity.send
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimatedWalletChangesUM import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionUM import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionUM
import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionAppInfoContentUM import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionAppInfoContentUM
@ -16,7 +16,7 @@ internal data class WcSendTransactionItemUM(
val onDismiss: () -> Unit, val onDismiss: () -> Unit,
val onSend: () -> Unit, val onSend: () -> Unit,
val appInfo: WcTransactionAppInfoContentUM, val appInfo: WcTransactionAppInfoContentUM,
val estimatedWalletChanges: WcEstimatedWalletChangesUM, val estimatedWalletChanges: WcSendReceiveTransactionCheckResultsUM?,
val walletName: String, val walletName: String,
val networkInfo: WcNetworkInfoUM, val networkInfo: WcNetworkInfoUM,
val networkFee: String? = null, val networkFee: String? = null,

View file

@ -9,6 +9,7 @@ import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router import com.tangem.core.decompose.navigation.Router
import com.tangem.core.ui.clipboard.ClipboardManager import com.tangem.core.ui.clipboard.ClipboardManager
import com.tangem.domain.core.lce.Lce
import com.tangem.domain.walletconnect.WcRequestUseCaseFactory import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
import com.tangem.domain.walletconnect.usecase.method.* import com.tangem.domain.walletconnect.usecase.method.*
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
@ -17,14 +18,15 @@ import com.tangem.features.walletconnect.transaction.entity.common.WcTransaction
import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionUM import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionUM
import com.tangem.features.walletconnect.transaction.routes.WcTransactionRoutes import com.tangem.features.walletconnect.transaction.routes.WcTransactionRoutes
import com.tangem.features.walletconnect.transaction.converter.WcCommonTransactionUMConverter import com.tangem.features.walletconnect.transaction.converter.WcCommonTransactionUMConverter
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
import com.tangem.features.walletconnect.transaction.ui.blockaid.WcSendAndReceiveBlockAidUiConverter
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@Suppress("LongParameterList")
@Stable @Stable
@ModelScoped @ModelScoped
internal class WcSendTransactionModel @Inject constructor( internal class WcSendTransactionModel @Inject constructor(
@ -34,6 +36,7 @@ internal class WcSendTransactionModel @Inject constructor(
private val clipboardManager: ClipboardManager, private val clipboardManager: ClipboardManager,
private val useCaseFactory: WcRequestUseCaseFactory, private val useCaseFactory: WcRequestUseCaseFactory,
private val converter: WcCommonTransactionUMConverter, private val converter: WcCommonTransactionUMConverter,
private val blockAidUiConverter: WcSendAndReceiveBlockAidUiConverter,
) : Model(), WcCommonTransactionModel { ) : Model(), WcCommonTransactionModel {
private val params = paramsContainer.require<WcTransactionModelParams>() private val params = paramsContainer.require<WcTransactionModelParams>()
@ -49,28 +52,49 @@ internal class WcSendTransactionModel @Inject constructor(
is WcTransactionUseCase, is WcTransactionUseCase,
is WcListTransactionUseCase, is WcListTransactionUseCase,
-> { -> {
useCase.invoke().onEach { signState -> observeTransactionData(useCase)
if (signingIsDone(signState)) return@onEach
val transactionUM = converter.convert(
WcCommonTransactionUMConverter.Input(
useCase = useCase,
signState = signState,
actions = WcTransactionActionsUM(
onShowVerifiedAlert = ::showVerifiedAlert,
onDismiss = { cancel(useCase) },
onSign = useCase::sign,
onCopy = { copyData(useCase.rawSdkRequest.request.params) },
),
),
) as? WcSendTransactionUM
_uiState.emit(transactionUM)
}
.launchIn(this)
} }
} }
} }
} }
private suspend fun observeSecurityData(useCase: WcSignUseCase<TransactionData>) {
(useCase as? BlockAidTransactionCheck)?.let {
useCase.securityStatus.collectLatest {
val blockAidState = when (it) {
is Lce.Content -> blockAidUiConverter.convert(it.content.result)
is Lce.Error -> WcSendReceiveTransactionCheckResultsUM(isLoading = false)
is Lce.Loading -> WcSendReceiveTransactionCheckResultsUM(isLoading = true)
}
val current = _uiState.value
_uiState.emit(
current?.copy(transaction = current.transaction.copy(estimatedWalletChanges = blockAidState)),
)
}
}
}
private fun CoroutineScope.observeTransactionData(useCase: WcSignUseCase<TransactionData>) {
useCase.invoke().onEach { signState ->
if (signingIsDone(signState)) return@onEach
val transactionUM = converter.convert(
WcCommonTransactionUMConverter.Input(
useCase = useCase,
signState = signState,
actions = WcTransactionActionsUM(
onShowVerifiedAlert = ::showVerifiedAlert,
onDismiss = { cancel(useCase) },
onSign = useCase::sign,
onCopy = { copyData(useCase.rawSdkRequest.request.params) },
),
),
) as? WcSendTransactionUM
_uiState.emit(transactionUM)
observeSecurityData(useCase)
}
.launchIn(this)
}
override fun dismiss() { override fun dismiss() {
_uiState.value?.transaction?.onDismiss?.invoke() ?: router.pop() _uiState.value?.transaction?.onDismiss?.invoke() ?: router.pop()
} }

View file

@ -78,7 +78,7 @@ internal fun WcSpendAllowanceItem(spendAllowance: WcSpendAllowanceUM, modifier:
Spacer(modifier = Modifier.width(TangemTheme.dimens.spacing8)) Spacer(modifier = Modifier.width(TangemTheme.dimens.spacing8))
Icon( Icon(
painter = painterResource(id = R.drawable.ic_edit_new_24), painter = painterResource(id = R.drawable.ic_edit_new_12),
contentDescription = null, contentDescription = null,
tint = TangemTheme.colors.icon.informative, tint = TangemTheme.colors.icon.informative,
) )

View file

@ -27,15 +27,20 @@ internal fun TransactionCheckResultsItem(item: WcSendReceiveTransactionCheckResu
Column( Column(
modifier = modifier modifier = modifier
.padding(12.dp)
.fillMaxWidth(), .fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(12.dp),
) { ) {
item.notificationText?.let { if (item.isLoading) {
WcTransactionCheckErrorItem(it.resolveReference()) WcEstimatedWalletChangesLoadingItem()
} } else {
item.estimatedWalletChanges?.let { if (item.notificationText != null) {
WcEstimatedWalletChangesItem(it) WcTransactionCheckErrorItem(item.notificationText.resolveReference())
}
if (item.estimatedWalletChanges != null) {
WcEstimatedWalletChangesItem(item.estimatedWalletChanges)
} else {
WcEstimatedWalletChangesNotLoadedItem()
}
} }
} }
} }
@ -59,6 +64,7 @@ private fun TransactionCheckResultsItemPreview(
private class TransactionCheckResultsItemProvider : PreviewParameterProvider<WcSendReceiveTransactionCheckResultsUM> { private class TransactionCheckResultsItemProvider : PreviewParameterProvider<WcSendReceiveTransactionCheckResultsUM> {
override val values = sequenceOf( override val values = sequenceOf(
WcSendReceiveTransactionCheckResultsUM( WcSendReceiveTransactionCheckResultsUM(
isLoading = false,
notificationText = TextReference.Str("The transaction approves erc20 tokens to a known malicious address"), notificationText = TextReference.Str("The transaction approves erc20 tokens to a known malicious address"),
estimatedWalletChanges = WcEstimatedWalletChangesUM( estimatedWalletChanges = WcEstimatedWalletChangesUM(
items = persistentListOf( items = persistentListOf(

View file

@ -0,0 +1,69 @@
package com.tangem.features.walletconnect.transaction.ui.blockaid
import android.content.res.Configuration
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.walletconnect.impl.R
import com.tangem.features.walletconnect.transaction.ui.common.WcSmallTitleItem
@Composable
internal fun WcEstimatedWalletChangesLoadingItem(modifier: Modifier = Modifier) {
Column(
modifier = modifier
.clip(RoundedCornerShape(14.dp))
.background(color = TangemTheme.colors.background.action)
.fillMaxWidth()
.animateContentSize(),
) {
WcSmallTitleItem(
textRex = R.string.wc_estimated_wallet_changes,
modifier = Modifier.padding(bottom = 16.dp),
)
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(bottom = 14.dp),
) {
CircularProgressIndicator(
color = TangemTheme.colors.icon.accent,
strokeWidth = 2.dp,
modifier = Modifier.size(24.dp),
)
Text(
modifier = modifier
.fillMaxWidth(),
text = stringResourceSafe(R.string.wc_common_loading),
color = TangemTheme.colors.text.disabled,
style = TangemTheme.typography.body2,
)
}
}
}
@Composable
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO)
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun WcEstimatedWalletChangesLoadingItems() {
TangemThemePreview {
Box(
modifier = Modifier
.background(TangemTheme.colors.background.tertiary),
) {
WcEstimatedWalletChangesLoadingItem()
}
}
}

View file

@ -0,0 +1,58 @@
package com.tangem.features.walletconnect.transaction.ui.blockaid
import android.content.res.Configuration
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.walletconnect.impl.R
import com.tangem.features.walletconnect.transaction.ui.common.WcSmallTitleItem
@Composable
internal fun WcEstimatedWalletChangesNotLoadedItem(modifier: Modifier = Modifier) {
Column(
modifier = modifier
.clip(RoundedCornerShape(14.dp))
.background(color = TangemTheme.colors.background.action)
.fillMaxWidth()
.animateContentSize(),
) {
WcSmallTitleItem(
textRex = R.string.wc_estimated_wallet_changes,
modifier = Modifier.padding(bottom = 16.dp),
)
Text(
modifier = modifier
.fillMaxWidth()
.padding(start = 12.dp, bottom = 14.dp),
text = stringResourceSafe(R.string.wc_estimated_wallet_changes_not_simulated),
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.body2,
)
}
}
@Composable
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO)
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun WcEstimatedWalletChangesNotLoadedItems() {
TangemThemePreview {
Box(
modifier = Modifier
.background(TangemTheme.colors.background.tertiary),
) {
WcEstimatedWalletChangesNotLoadedItem()
}
}
}

View file

@ -16,13 +16,15 @@ import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimated
import com.tangem.utils.converter.Converter import com.tangem.utils.converter.Converter
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import javax.inject.Inject
private const val DECIMALS_AMOUNT = 2 private const val DECIMALS_AMOUNT = 2
internal class WcSendAndReceiveBlockAidUiConverter : internal class WcSendAndReceiveBlockAidUiConverter @Inject constructor() :
Converter<CheckTransactionResult, WcSendReceiveTransactionCheckResultsUM> { Converter<CheckTransactionResult, WcSendReceiveTransactionCheckResultsUM> {
override fun convert(value: CheckTransactionResult): WcSendReceiveTransactionCheckResultsUM { override fun convert(value: CheckTransactionResult): WcSendReceiveTransactionCheckResultsUM {
return WcSendReceiveTransactionCheckResultsUM( return WcSendReceiveTransactionCheckResultsUM(
isLoading = false,
notificationText = when (value.validation) { notificationText = when (value.validation) {
ValidationResult.SAFE, ValidationResult.FAILED_TO_VALIDATE -> null ValidationResult.SAFE, ValidationResult.FAILED_TO_VALIDATE -> null
ValidationResult.UNSAFE -> TextReference.Str("") // TODO("Add text after approve with designer") ValidationResult.UNSAFE -> TextReference.Str("") // TODO("Add text after approve with designer")

View file

@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemTheme
@ -14,7 +15,7 @@ fun WcSmallTitleItem(@StringRes textRex: Int, modifier: Modifier = Modifier) {
Text( Text(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.padding(top = TangemTheme.dimens.spacing12, start = TangemTheme.dimens.spacing12), .padding(top = 12.dp, start = 12.dp),
text = stringResourceSafe(textRex), text = stringResourceSafe(textRex),
color = TangemTheme.colors.text.tertiary, color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.subtitle2, style = TangemTheme.typography.subtitle2,

View file

@ -20,6 +20,7 @@ import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetWithFooter import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetWithFooter
import com.tangem.core.ui.components.divider.DividerWithPadding import com.tangem.core.ui.components.divider.DividerWithPadding
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.res.TangemThemePreview
@ -28,10 +29,11 @@ import com.tangem.features.walletconnect.connections.ui.WcAppInfoItem
import com.tangem.features.walletconnect.impl.R import com.tangem.features.walletconnect.impl.R
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimatedWalletChangeUM import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimatedWalletChangeUM
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimatedWalletChangesUM import com.tangem.features.walletconnect.transaction.entity.blockaid.WcEstimatedWalletChangesUM
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM import com.tangem.features.walletconnect.transaction.entity.common.WcNetworkInfoUM
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionAppInfoContentUM import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionAppInfoContentUM
import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionItemUM import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionItemUM
import com.tangem.features.walletconnect.transaction.ui.blockaid.WcEstimatedWalletChangesItem import com.tangem.features.walletconnect.transaction.ui.blockaid.TransactionCheckResultsItem
import com.tangem.features.walletconnect.transaction.ui.common.WcSendTransactionItems import com.tangem.features.walletconnect.transaction.ui.common.WcSendTransactionItems
import com.tangem.features.walletconnect.transaction.ui.common.WcSmallTitleItem import com.tangem.features.walletconnect.transaction.ui.common.WcSmallTitleItem
import com.tangem.features.walletconnect.transaction.ui.common.WcTransactionRequestButtons import com.tangem.features.walletconnect.transaction.ui.common.WcTransactionRequestButtons
@ -89,7 +91,9 @@ internal fun WcSendTransactionModalBottomSheet(
) )
} }
Column(modifier = Modifier.padding(top = 16.dp)) { Column(modifier = Modifier.padding(top = 16.dp)) {
WcEstimatedWalletChangesItem(state.estimatedWalletChanges) if (state.estimatedWalletChanges != null) {
TransactionCheckResultsItem(state.estimatedWalletChanges)
}
Spacer(Modifier.height(16.dp)) Spacer(Modifier.height(16.dp))
WcSendTransactionItems( WcSendTransactionItems(
walletName = state.walletName, walletName = state.walletName,
@ -153,19 +157,24 @@ private class WcSendTransactionStateProvider : CollectionPreviewParameterProvide
verifiedState = VerifiedDAppState.Verified {}, verifiedState = VerifiedDAppState.Verified {},
appSubtitle = "react-app.walletconnect.com", appSubtitle = "react-app.walletconnect.com",
), ),
estimatedWalletChanges = WcEstimatedWalletChangesUM( estimatedWalletChanges = WcSendReceiveTransactionCheckResultsUM(
items = persistentListOf( notificationText = TextReference.Str(
WcEstimatedWalletChangeUM( "The transaction approves erc20 tokens to a known malicious address",
iconRes = R.drawable.ic_send_new_24, ),
title = resourceReference(R.string.common_send), estimatedWalletChanges = WcEstimatedWalletChangesUM(
description = "- 42 USDT", items = persistentListOf(
tokenIconUrl = "https://tangem.com", WcEstimatedWalletChangeUM(
), iconRes = R.drawable.ic_send_new_24,
WcEstimatedWalletChangeUM( title = resourceReference(R.string.common_send),
iconRes = R.drawable.ic_receive_new_24, description = "- 42 USDT",
title = resourceReference(R.string.common_receive), tokenIconUrl = "https://tangem.com",
description = "+ 1,131.46 MATIC", ),
tokenIconUrl = "https://tangem.com", WcEstimatedWalletChangeUM(
iconRes = R.drawable.ic_receive_new_24,
title = resourceReference(R.string.common_receive),
description = "+ 1,131.46 MATIC",
tokenIconUrl = "https://tangem.com",
),
), ),
), ),
), ),