Updated on 2026-08-14

This commit is contained in:
Tangem 2024-09-23 19:01:10 +03:00
commit c61e317229
25 changed files with 370 additions and 207 deletions

View file

@ -104,8 +104,8 @@ data class TokenMarketInfoResponse(
val marketCap: BigDecimal?,
@Json(name = "volume_24h")
val volume24h: BigDecimal?,
@Json(name = "total_supply")
val totalSupply: BigDecimal?,
@Json(name = "max_supply")
val maxSupply: BigDecimal?,
@Json(name = "fully_diluted_valuation")
val fullyDilutedValuation: BigDecimal?,
)

View file

@ -414,7 +414,8 @@
<string name="markets_token_details_market_rating_description">Position im Krypto-Rating zwischen allen Coins basierend auf der Marktkapitalisierung</string>
<string name="markets_token_details_market_rating_full">Marktbewertung</string>
<string name="markets_token_details_max_supply">Maximale Versorgung</string>
<string name="markets_token_details_max_supply_description">Leer</string>
<string name="markets_token_details_max_supply_description">Die maximale Anzahl von Coins oder Tokens, die jemals für eine bestimmte Kryptowährung existieren können</string>
<string name="markets_token_details_max_supply_full">Maximale Versorgung</string>
<string name="markets_token_details_metrics">Metriken</string>
<string name="markets_token_details_official_links">Offizielle Links</string>
<string name="markets_token_details_price_performance">Preisleistung</string>
@ -700,6 +701,7 @@
<string name="staking_notification_earn_rewards_text_period_week">Mit dem Staking kannst Du %1$s verdienen. Deine Staking-Belohnungen erhältst Du jede Woche.</string>
<string name="staking_notification_earn_rewards_text_weekly">Sicher staken und wöchentliche Belohnungen verdienen.</string>
<string name="staking_notification_earn_rewards_title">Verdiene Staking-Belohnungen</string>
<string name="staking_notification_network_error_text">Aufgrund von Netzwerkproblemen ist Staking derzeit nicht verfügbar. Bitte versuche es später erneut.</string>
<string name="staking_notification_new_validator_funds_transfer">Beim Staking im %1$s -Netzwerk mit einem neuen Validator werden alle zuvor eingesetzten Kryptos automatisch an diesen Validator übertragen</string>
<string name="staking_notification_restake_rewards_text">Reinvestiert Deine verdienten Prämien in Deinen Einsatzbetrag und erhöht so den potenziellen Gewinn.</string>
<string name="staking_notification_unlock_text">Entsperre dein Geld, um es aus dem Staking-Prozess abzuheben. Das Freischalten nimmt %s.</string>

View file

@ -75,8 +75,8 @@
<string name="common_approval">Aprobación</string>
<string name="common_approve">Aprobar</string>
<string name="common_attention">Atención</string>
<string name="common_balance">Soldo: %s</string>
<string name="common_balance_title">Soldo</string>
<string name="common_balance">Saldo: %s</string>
<string name="common_balance_title">Saldo</string>
<string name="common_biometric_authentication">autenticación biométrica</string>
<string name="common_biometrics">biometría</string>
<string name="common_buy">Comprar</string>
@ -103,7 +103,7 @@
<string name="common_enable">Activar</string>
<string name="common_enabled">Activado</string>
<string name="common_error">Error</string>
<string name="common_exchange">Intercambie</string>
<string name="common_exchange">Intercambiar</string>
<string name="common_explore">Explore</string>
<string name="common_explore_transaction_history">Explore historial de transacciones</string>
<string name="common_explorer">Explorador(a)</string>
@ -211,7 +211,7 @@
<string name="details_row_description_flip_to_hide">Gire la pantalla de su dispositivo hacia abajo para ocultar y mostrar rápidamente los saldos</string>
<string name="details_row_subtitle_signed_hashes_format">%s hashes</string>
<string name="details_row_title_cid">ID de la tarjeta</string>
<string name="details_row_title_contact_to_support">Contacta con el equipo de soporte</string>
<string name="details_row_title_contact_to_support">Contactar con el equipo de soporte</string>
<string name="details_row_title_create_backup">Vincular más tarjetas</string>
<string name="details_row_title_currency">Moneda de la aplicación</string>
<string name="details_row_title_flip_to_hide">Girar para ocultar saldos</string>
@ -351,7 +351,7 @@
<string name="markets_common_my_portfolio">Mi portafolio</string>
<string name="markets_common_title">Mercado</string>
<string name="markets_generate_addresses_notification">Para generar direcciones para las redes seleccionadas, debe escanear su tarjeta Tangem</string>
<string name="markets_hint">Para agregar tokens, abra esta página o toque la barra de búsqueda</string>
<string name="markets_hint">Para agregar tokens, abra esta página o pulse sobre la barra de búsqueda</string>
<string name="markets_insights_info_description_message">Los datos de este apartado proceden de las siguientes redes: %s</string>
<string name="markets_loading_error_title">No se pueden cargar los datos…</string>
<string name="markets_loading_no_data_title">Sin datos</string>
@ -363,11 +363,11 @@
<string name="markets_search_token_no_result_title">Sin resultado</string>
<string name="markets_select_network">Seleccione una red</string>
<string name="markets_select_wallet">Seleccione una billetera</string>
<string name="markets_selector_interval_1m_title">1 mo</string>
<string name="markets_selector_interval_1y_title">1 año</string>
<string name="markets_selector_interval_1m_title">1m</string>
<string name="markets_selector_interval_1y_title">1a</string>
<string name="markets_selector_interval_24h_title">24h</string>
<string name="markets_selector_interval_3m_title">3mos</string>
<string name="markets_selector_interval_6m_title">6mos</string>
<string name="markets_selector_interval_3m_title">3m</string>
<string name="markets_selector_interval_6m_title">6m</string>
<string name="markets_selector_interval_7d_title">7d</string>
<string name="markets_selector_interval_all_title">Todo</string>
<string name="markets_sort_by_experienced_buyers_title">Compradores experimentados</string>
@ -413,6 +413,8 @@
<string name="markets_token_details_market_rating_description">Posición en la clasificación de criptomonedas entre todas las monedas según la capitalización de mercado</string>
<string name="markets_token_details_market_rating_full">Evaluación de mercado</string>
<string name="markets_token_details_max_supply">Suministro máximo</string>
<string name="markets_token_details_max_supply_description">La cantidad máxima de monedas o tokens que pueden existir para una criptomoneda en particular</string>
<string name="markets_token_details_max_supply_full">Suministro máximo</string>
<string name="markets_token_details_metrics">Métrica</string>
<string name="markets_token_details_official_links">Enlaces oficiales</string>
<string name="markets_token_details_price_performance">Rendimiento de precios</string>

View file

@ -413,6 +413,8 @@
<string name="markets_token_details_market_rating_description">Position dans le classement des crypto-monnaies entre toutes les pièces en fonction de la capitalisation boursière</string>
<string name="markets_token_details_market_rating_full">Évaluation du marché</string>
<string name="markets_token_details_max_supply">Approvisionnement maximal</string>
<string name="markets_token_details_max_supply_description">Le nombre maximal de pièces ou de jetons pouvant exister pour une crypto-monnaie particulière</string>
<string name="markets_token_details_max_supply_full">Approvisionnement maximal</string>
<string name="markets_token_details_metrics">Métriques</string>
<string name="markets_token_details_official_links">Official links</string>
<string name="markets_token_details_price_performance">Performance des prix</string>

View file

@ -39,7 +39,7 @@
<string name="biometric_lockout_warning_title">試行回数が多すぎます</string>
<string name="biometric_unavailable_warning">お使いの携帯電話で生体認証が無効になっているため、アプリにウォレットを保存できません。ウォレットを保存するには、携帯電話の設定で生体認証機能を有効にしてください。</string>
<string name="button_start_backup_process">バックアップ処理を開始する</string>
<string name="buy_token_description">銀行カードまたは銀行口座から</string>
<string name="buy_token_description">銀行カードまたはその他の支払い方法を使用する</string>
<plurals name="card_label_card_count">
<item quantity="other">%d カード</item>
</plurals>
@ -101,7 +101,7 @@
<string name="common_enable">有効にする</string>
<string name="common_enabled">有効</string>
<string name="common_error">エラー</string>
<string name="common_exchange">交換</string>
<string name="common_exchange">スワップ</string>
<string name="common_explore">移動する</string>
<string name="common_explore_transaction_history">取引履歴を調べる</string>
<string name="common_explorer">エクスプローラー</string>
@ -273,7 +273,7 @@
<string name="express_token_list_empty_search">トークンが見つかりません。別のリクエストをお試しください。</string>
<string name="express_transaction_id">ID: %s</string>
<string name="express_transaction_id_copied">取引IDをコピーしました</string>
<string name="exсhange_token_description">ウォレット内の別の通貨から</string>
<string name="exсhange_token_description">ポートフォリオ内のアセットをこのトークンと交換する</string>
<string name="feedback_data_collection_message">以下の情報はオプションです。共有したくない場合は消去できます。</string>
<string name="feedback_preface_rate_negative">どのような機能が不足しているかを教えください。解決できるよう尽力致します。</string>
<string name="feedback_preface_scan_failed">お持ちのカードについて教えてください</string>
@ -409,6 +409,8 @@
<string name="markets_token_details_market_rating_description">時価総額に基づくすべてのコイン間の暗号資産評価における位置</string>
<string name="markets_token_details_market_rating_full">市場格付け</string>
<string name="markets_token_details_max_supply">最大供給量</string>
<string name="markets_token_details_max_supply_description">特定の暗号資産に存在しうるコインまたはトークンの最大数</string>
<string name="markets_token_details_max_supply_full">最大供給量</string>
<string name="markets_token_details_metrics">指標</string>
<string name="markets_token_details_official_links">公式リンク</string>
<string name="markets_token_details_price_performance">値動き</string>
@ -522,7 +524,7 @@
<string name="qr_scanner_camera_denied_title">カメラへのアクセスが拒否されました</string>
<string name="receive_bottom_sheet_warning_message">%3$sネットワーク上の%1$s ( %2$s )</string>
<string name="receive_bottom_sheet_warning_message_full">このアドレスには%sのみを送金してください。他のトークンを送信すると、取り返しのつかない損失が発生します。</string>
<string name="receive_token_description">QRコードを表示するか、アドレスを共有してください</string>
<string name="receive_token_description">ウォレットや取引所から資金を送金する</string>
<string name="referral_button_participate">参加する</string>
<string name="referral_error_failed_to_load_info">紹介プログラムに関する情報を読み込めませんでした。しばらくしてからもう一度お試しください。</string>
<string name="referral_error_failed_to_load_info_with_reason">紹介プログラムに関する情報を読み込めませんでした。エラー コード: %s 。しばらくしてからもう一度お試しください。</string>
@ -570,7 +572,7 @@
<string name="scan_card_settings_message">カードをスキャンして設定を変更します。変更はスキャンしたカードにのみ影響し、ウォレットに関連付けられている他のカードには影響しません。</string>
<string name="scan_card_settings_title">カードを準備してください!</string>
<string name="send_additional_field_already_included">入力したアドレスにすでに含まれています</string>
<string name="send_alert_fee_too_high_text">手数料額が推奨額の%s倍となっています。カスタム設定が正しいことを再度確認してください。</string>
<string name="send_alert_fee_too_high_text">手数料額が推奨額の%s倍となっています。設定を再度確認し、調整してください。</string>
<string name="send_alert_fee_too_low_text">推奨手数料を下回る手数料が指定されたため、取引に遅れが生じる可能性があります。続行しますか?</string>
<string name="send_alert_transaction_failed_text">理由: %1$s \nコード: %2$s</string>
<string name="send_alert_transaction_failed_title">取引は完了していません</string>
@ -605,7 +607,7 @@
<string name="send_notification_exceed_balance_title">合計が残高を超えています</string>
<string name="send_notification_existential_deposit_text">セキュリティリスクを防ぐため、ブロックチェーン上にアカウントを維持するには、少なくとも%s の残高が必要です。この金額は残高に残り、引き出すことはできません。</string>
<string name="send_notification_existential_deposit_title">アカウント維持に必要な最低残高</string>
<string name="send_notification_fee_too_high_text">手数料額が推奨額の%s倍となっています。カスタム設定が正しいことを再度確認してください。</string>
<string name="send_notification_fee_too_high_text">手数料額が推奨額の%s倍となっています。設定を再度確認し、調整してください。</string>
<string name="send_notification_fee_too_high_title">カスタム手数料が高くなっています</string>
<string name="send_notification_high_fee_text">%1$sネットワークの特殊性により、残高全体を転送する場合の手数料は高くなります。手数料を削減するには、 %2$sを残します。</string>
<string name="send_notification_high_fee_title">手数料が高くなっています</string>
@ -690,6 +692,7 @@
<string name="staking_notification_earn_rewards_text_period_week">ステーキングにより%1$sを獲得できます。ステーキング報酬は毎週受け取れます。</string>
<string name="staking_notification_earn_rewards_text_weekly">安全にステーキングして、報酬を毎週獲得しましょう</string>
<string name="staking_notification_earn_rewards_title">ステーキング報酬を獲得</string>
<string name="staking_notification_network_error_text">ネットワークの状態により、現在ステーキングはご利用いただけません。しばらくしてからもう一度お試しください。</string>
<string name="staking_notification_new_validator_funds_transfer">新しいバリデーターで%1$sネットワークにステーキングすると、以前にステーキングされた資金はすべてこのバリデーターに自動的に転送されます。</string>
<string name="staking_notification_restake_rewards_text">獲得した報酬をステーキングに再投資し、潜在的な収益を増やします。</string>
<string name="staking_notification_unlock_text">資金をステーキングから引き出すには、ロックを解除してください。ロック解除には%sかかります。</string>
@ -706,14 +709,14 @@
<string name="staking_revote">再投票</string>
<string name="staking_reward_claiming_auto">自動</string>
<string name="staking_reward_claiming_manual">手動</string>
<string name="staking_reward_schedule_block">ブロック</string>
<string name="staking_reward_schedule_day"></string>
<string name="staking_reward_schedule_block">ブロック</string>
<string name="staking_reward_schedule_day"></string>
<string name="staking_reward_schedule_each_day">毎日</string>
<string name="staking_reward_schedule_epoch">エポック</string>
<string name="staking_reward_schedule_era">時代</string>
<string name="staking_reward_schedule_hour"></string>
<string name="staking_reward_schedule_month"></string>
<string name="staking_reward_schedule_week"></string>
<string name="staking_reward_schedule_epoch">エポック</string>
<string name="staking_reward_schedule_era">時代</string>
<string name="staking_reward_schedule_hour">毎時間</string>
<string name="staking_reward_schedule_month"></string>
<string name="staking_reward_schedule_week"></string>
<string name="staking_rewards">報酬</string>
<string name="staking_stake_locked">ステーキングはロックされています</string>
<string name="staking_stake_more">もっとステーキングする</string>

View file

@ -15,6 +15,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_default_fee">Комиссия по-умолчанию</string>
<string name="app_settings_default_fee_footer">Подключите функцию комиссии по умолчанию и при формировании транзакции на отправку средств комиссия будет выставлена автоматически, а экран комиссии пропущен. Вы всегда сможете на него вернуться.</string>
<string name="app_settings_enable_biometrics_description">Перейдите в настройки, чтобы включить биометрическую аутентификацию в приложении Tangem</string>
<string name="app_settings_enable_biometrics_title">Включите биометрическую аутентификацию</string>
@ -178,6 +179,7 @@
<string name="custom_token_contract_address_input_title">Адрес контракта</string>
<string name="custom_token_creation_error_invalid_contract_address">Адрес контракта некорректен</string>
<string name="custom_token_creation_error_network_not_selected">Пожалуйста, выберите сеть</string>
<string name="custom_token_creation_error_token_already_exist_message">Этот токен уже добавлен в список</string>
<string name="custom_token_creation_error_token_already_exist_title">Токен уже существует</string>
<string name="custom_token_creation_error_wrong_decimals">Десятичное число должно быть действительным целым числом, до %d</string>
<string name="custom_token_custom_derivation">Своя деривация</string>
@ -358,7 +360,7 @@
<string name="markets_loading_error_title">Невозможно загрузить данные</string>
<string name="markets_loading_no_data_title">Нет данных</string>
<string name="markets_quick_actions">Быстрые действия</string>
<string name="markets_search_header_title">Искать на маркете</string>
<string name="markets_search_header_title">Поиск на рынке</string>
<string name="markets_search_result_title">Результат</string>
<string name="markets_search_see_tokens_under_100k">Токены с капитализацией меньше 100к USD</string>
<string name="markets_search_show_tokens">Показать токены</string>
@ -416,7 +418,9 @@
<string name="markets_token_details_market_rating">Рейтинг</string>
<string name="markets_token_details_market_rating_description">Позиция в рейтинге криптовалют среди всех монет на основе рыночной капитализации.</string>
<string name="markets_token_details_market_rating_full">Рейтинг</string>
<string name="markets_token_details_max_supply">Максимальный объем</string>
<string name="markets_token_details_max_supply">Макс. объем</string>
<string name="markets_token_details_max_supply_description">Максимальное количество монет или токенов, которое может когда-либо существовать для выбранной криптовалюты</string>
<string name="markets_token_details_max_supply_full">Максимальный объем</string>
<string name="markets_token_details_metrics">Метрики</string>
<string name="markets_token_details_official_links">Официальные ссылки</string>
<string name="markets_token_details_price_performance">Динамика цены</string>
@ -424,7 +428,7 @@
<string name="markets_token_details_security_score">Оценка безопасности</string>
<string name="markets_token_details_social">Социальные</string>
<string name="markets_token_details_total_supply">Общ. предл.</string>
<string name="markets_token_details_total_supply_description">Максимальное количество монет или токенов, которое может когда-либо существовать для выбранной криптовалюты.</string>
<string name="markets_token_details_total_supply_description">Максимальное количество монет или токенов, которое может когда-либо существовать для выбранной криптовалюты</string>
<string name="markets_token_details_total_supply_full">Общее предложение</string>
<string name="markets_token_details_trading_volume">Объем торгов (24ч)</string>
<string name="markets_token_details_trading_volume_24h_description">Общая сумма криптовалюты, которая была продана за последние 24 часа, показывающая уровень активности и ликвидности на рынке.</string>
@ -536,7 +540,7 @@
<string name="qr_scanner_camera_denied_title">Доступ к камере запрещен</string>
<string name="receive_bottom_sheet_warning_message">%1$s (%2$s) в сети %3$s</string>
<string name="receive_bottom_sheet_warning_message_full">Отправляйте только %s на этот адрес. Использование другой сети может привести к утрате средств.</string>
<string name="receive_token_description">Переводите средства с другого кошелька или биржи</string>
<string name="receive_token_description">Переводите средства с любого кошелька или биржи</string>
<string name="referral_button_participate">Участвовать</string>
<string name="referral_error_failed_to_load_info">Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже.</string>
<string name="referral_error_failed_to_load_info_with_reason">Не удалось загрузить информацию по реферальной программе. Код ошибки: %s. Пожалуйста, попробуйте позже.</string>
@ -597,6 +601,7 @@
<string name="send_amount_label">Сумма</string>
<string name="send_bitcoin_custom_fee_footer">Вы можете установить комиссию за транзакцию, изменив значение в поле Satoshi per vByte.</string>
<string name="send_custom_amount_fee_footer">Комиссия, которая будет взята за вашу транзакцию. Вы можете выставить своё собственное значение.</string>
<string name="send_custom_evm_max_fee">Максимальная комиссия</string>
<string name="send_custom_evm_max_fee_footer">Это стоимость, которую вы готовы заплатить за каждую единицу газа. Чем выше цена газа, тем быстрее ваша транзакция будет обработана. (Приоритетная комиссия включена)</string>
<string name="send_custom_evm_priority_fee">Приоритетная комиссия</string>
<string name="send_custom_evm_priority_fee_footer">Комиссия, которую пользователь может заплатить майнерам или валидаторам за ускорение включения его транзакции в блок.</string>
@ -685,7 +690,7 @@
<string name="staking_details_minimum_requirement">Минимальное количество</string>
<string name="staking_details_no_rewards_to_claim">Нет вознаграждений к получению</string>
<string name="staking_details_reward_claiming">Способ вознаграждения</string>
<string name="staking_details_reward_claiming_info">Способ получения вознаграждений за стейкинг. Он может быть автоматическим, при котором вознаграждение само зачисляется вам на адрес или в ручную, когда вознаграждение нужно вывести, создав транзакцию на её получение.</string>
<string name="staking_details_reward_claiming_info">Способ получения вознаграждений за стейкинг. Оно может зачисляться автоматически на ваш адрес или вручную, когда вознаграждение нужно вывести, создав транзакцию на её получение.</string>
<string name="staking_details_reward_schedule">Период вознагражения</string>
<string name="staking_details_reward_schedule_info">Это период, определяющий, когда участники стейкинга получат свои вознаграждения.</string>
<string name="staking_details_rewards_to_claim">Вознаграждение для получения: %s</string>
@ -725,14 +730,14 @@
<string name="staking_revote">Переголосовать</string>
<string name="staking_reward_claiming_auto">Авто</string>
<string name="staking_reward_claiming_manual">Вручную</string>
<string name="staking_reward_schedule_block">Блок</string>
<string name="staking_reward_schedule_day">День</string>
<string name="staking_reward_schedule_block">За блок</string>
<string name="staking_reward_schedule_day">Ежедневно</string>
<string name="staking_reward_schedule_each_day">Каждый день</string>
<string name="staking_reward_schedule_epoch">Эпоха</string>
<string name="staking_reward_schedule_era">Эра</string>
<string name="staking_reward_schedule_hour">Час</string>
<string name="staking_reward_schedule_epoch">За эпоху</string>
<string name="staking_reward_schedule_era">За эру</string>
<string name="staking_reward_schedule_hour">Ежечасно</string>
<string name="staking_reward_schedule_month">Месяц</string>
<string name="staking_reward_schedule_week">Неделя</string>
<string name="staking_reward_schedule_week">Еженедельно</string>
<string name="staking_rewards">Вознаграждения</string>
<string name="staking_stake_locked">Стейкинг закрыт</string>
<string name="staking_stake_more">Застейкать еще</string>
@ -815,6 +820,7 @@
<string name="transaction_history_operation">Операция</string>
<string name="transaction_history_transaction_from_address">от: %s</string>
<string name="transaction_history_transaction_to_address">на: %s</string>
<string name="transaction_history_transaction_validator">валидатор: %s</string>
<string name="try_to_load_data_again_button_title">Попробовать снова</string>
<string name="twin_error_same_card">Вы отсканировали ту же карту. Для создания twin-кошелька вам необходимо отсканировать карту с номером %d</string>
<string name="twin_error_wrong_twin">Вы отсканировали не ту twin-карту. Пожалуйста, попробуйте отсканировать другую</string>

View file

@ -418,7 +418,8 @@
<string name="markets_token_details_market_rating">Рейтинг</string>
<string name="markets_token_details_market_rating_description">Позиція в крипторейтингу між усіма монетами на основі ринкової капіталізації</string>
<string name="markets_token_details_market_rating_full">Рейтинг</string>
<string name="markets_token_details_max_supply">Максимальна пропозиція</string>
<string name="markets_token_details_max_supply_description">Максимальна кількість монет або токенів, яка може коли-небудь існувати для певної криптовалюти</string>
<string name="markets_token_details_max_supply_full">Максимальна пропозиція</string>
<string name="markets_token_details_metrics">Метрики</string>
<string name="markets_token_details_official_links">Офіційні посилання</string>
<string name="markets_token_details_price_performance">Цінова ефективність</string>

View file

@ -413,6 +413,8 @@
<string name="markets_token_details_market_rating_description">Position in crypto rating between all coins based on market capitalization</string>
<string name="markets_token_details_market_rating_full">Market rating</string>
<string name="markets_token_details_max_supply">Max supply</string>
<string name="markets_token_details_max_supply_description">The maximum number of coins or tokens that can ever exist for a particular cryptocurrency</string>
<string name="markets_token_details_max_supply_full">Max supply</string>
<string name="markets_token_details_metrics">Metrics</string>
<string name="markets_token_details_official_links">Official links</string>
<string name="markets_token_details_price_performance">Price performance</string>
@ -528,7 +530,7 @@
<string name="qr_scanner_camera_denied_title">Camera access denied</string>
<string name="receive_bottom_sheet_warning_message">%1$s (%2$s) on %3$s network</string>
<string name="receive_bottom_sheet_warning_message_full">Send only %s to this address. Sending any other currency will result in its irreversible loss.</string>
<string name="receive_token_description">Transfer funds from another wallet or exchange</string>
<string name="receive_token_description">Transfer funds from any wallet or exchange</string>
<string name="referral_button_participate">Participate</string>
<string name="referral_error_failed_to_load_info">Failed to load the information about the referral program. Please try again later.</string>
<string name="referral_error_failed_to_load_info_with_reason">Failed to load the information about the referral program. Error code: %s. Please try again later.</string>
@ -715,14 +717,14 @@
<string name="staking_revote">Revote</string>
<string name="staking_reward_claiming_auto">Auto</string>
<string name="staking_reward_claiming_manual">Manual</string>
<string name="staking_reward_schedule_block">Block</string>
<string name="staking_reward_schedule_day">Day</string>
<string name="staking_reward_schedule_block">Per Block</string>
<string name="staking_reward_schedule_day">Daily</string>
<string name="staking_reward_schedule_each_day">Daily</string>
<string name="staking_reward_schedule_epoch">Epoch</string>
<string name="staking_reward_schedule_era">Era</string>
<string name="staking_reward_schedule_hour">Hour</string>
<string name="staking_reward_schedule_month">Month</string>
<string name="staking_reward_schedule_week">Week</string>
<string name="staking_reward_schedule_epoch">Per Epoch</string>
<string name="staking_reward_schedule_era">Per Era</string>
<string name="staking_reward_schedule_hour">Hourly</string>
<string name="staking_reward_schedule_month">Monthly</string>
<string name="staking_reward_schedule_week">Weekly</string>
<string name="staking_rewards">Rewards</string>
<string name="staking_stake_locked">Stake locked</string>
<string name="staking_stake_more">Stake more</string>
@ -805,6 +807,7 @@
<string name="transaction_history_operation">Operation</string>
<string name="transaction_history_transaction_from_address">from: %s</string>
<string name="transaction_history_transaction_to_address">to: %s</string>
<string name="transaction_history_transaction_validator">validator: %s</string>
<string name="try_to_load_data_again_button_title">Try again</string>
<string name="twin_error_same_card">You\'ve scanned the same card. To create a twin wallet you need to scan the card with number %d</string>
<string name="twin_error_wrong_twin">You\'ve scanned wrong twin card. Please try another one</string>

View file

@ -207,8 +207,8 @@ class TangemSheetState(
absVelocityThreshold = 0.5f,
),
confirmValueChange = confirmValueChange,
positionalThreshold = { with(density) { 56.dp.toPx() } },
velocityThreshold = { with(density) { 125.dp.toPx() } },
positionalThreshold = { with(density) { 156.dp.toPx() } },
velocityThreshold = { with(density) { 225.dp.toPx() } },
)
internal val offset: Float

View file

@ -25,6 +25,7 @@ fun TangemTheme(
dimens: TangemDimens = TangemTheme.dimens,
vibratorHapticManager: VibratorHapticManager? = null,
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
overrideSystemBarColors: Boolean = true,
content: @Composable () -> Unit,
) {
val themeColors = if (isDark) darkThemeColors() else lightThemeColors()
@ -32,14 +33,18 @@ fun TangemTheme(
.also { it.update(themeColors) }
val shapes = remember { TangemShapes(dimens) }
val systemUiController = rememberSystemUiController()
SideEffect {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
darkIcons = !isDark,
isNavigationBarContrastEnforced = false,
)
// we don't want to override system bar colors in case of fragment bottom sheets for example
if (overrideSystemBarColors) {
val systemUiController = rememberSystemUiController()
SideEffect {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
darkIcons = !isDark,
isNavigationBarContrastEnforced = false,
)
}
}
val view = LocalView.current

View file

@ -52,7 +52,11 @@ abstract class ComposeBottomSheetFragment : BottomSheetDialogFragment(), Compose
override fun getTheme(): Int = R.style.AppTheme_TransparentBottomSheetDialog
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return createComposeView(inflater.context, requireActivity())
return createComposeView(
context = inflater.context,
activity = requireActivity(),
overrideSystemBarColors = false,
)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

View file

@ -50,9 +50,14 @@ internal interface ComposeScreen {
* Creates a [ComposeView] with the defined content for the Compose screen.
*
* @param context The context.
* @param overrideSystemBarColors Whether to override the system bar colors to make them transparent.
* @return A [ComposeView] instance with the defined screen content.
*/
internal fun ComposeScreen.createComposeView(context: Context, activity: Activity): ComposeView {
internal fun ComposeScreen.createComposeView(
context: Context,
activity: Activity,
overrideSystemBarColors: Boolean = true,
): ComposeView {
return ComposeView(context).apply {
setContent {
val appThemeMode by uiDependencies.appThemeModeHolder.appThemeMode
@ -63,6 +68,7 @@ internal fun ComposeScreen.createComposeView(context: Context, activity: Activit
windowSize = windowSize,
vibratorHapticManager = uiDependencies.vibratorHapticManager,
snackbarHostState = uiDependencies.globalSnackbarHostState,
overrideSystemBarColors = overrideSystemBarColors,
) {
ScreenContent(modifier = screenModifier)
}

View file

@ -5,6 +5,7 @@ import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.utils.StringsSigns.DASH_SIGN
import com.tangem.utils.StringsSigns.LOWER_SIGN
import com.tangem.utils.StringsSigns.TILDE_SIGN
import com.tangem.utils.extensions.isNotWhitespace
import timber.log.Timber
import java.math.BigDecimal
import java.math.RoundingMode
@ -20,8 +21,6 @@ object BigDecimalFormatter {
private const val CAN_BE_LOWER_SIGN = LOWER_SIGN
private val FORMAT_THRESHOLD = BigDecimal("0.01")
private const val TEMP_CURRENCY_CODE = "USD"
private val FIAT_FORMAT_THRESHOLD = BigDecimal("0.01")
private val CRYPTO_FEE_FORMAT_THRESHOLD = BigDecimal("0.000001")
@ -29,6 +28,12 @@ object BigDecimalFormatter {
private const val FIAT_MARKET_EXTENDED_DIGITS = 6
private const val FRACTIONAL_PART_LENGTH_AFTER_LEADING_ZEROES = 4
private val usdCurrency = Currency.getInstance("USD")
@Deprecated(
"Use formatCryptoAmount2",
replaceWith = ReplaceWith("formatCryptoAmount2"),
)
fun formatCryptoAmount(
cryptoAmount: BigDecimal?,
cryptoCurrency: String,
@ -53,6 +58,30 @@ object BigDecimalFormatter {
}
}
// Migrate to this method from formatCryptoAmount ([REDACTED_TASK_KEY])
fun formatCryptoAmount2(
cryptoAmount: BigDecimal?,
cryptoCurrency: String,
decimals: Int,
locale: Locale = Locale.getDefault(),
): String {
if (cryptoAmount == null) return EMPTY_BALANCE_SIGN
val formatter = NumberFormat.getCurrencyInstance(locale).apply {
currency = usdCurrency
maximumFractionDigits = decimals.coerceAtMost(maximumValue = 8)
minimumFractionDigits = 2
isGroupingUsed = true
roundingMode = RoundingMode.HALF_UP
}
return formatter.format(cryptoAmount)
.replaceFiatSymbolWithCrypto(
fiatCurrencySymbol = usdCurrency.symbol,
cryptoCurrencySymbol = cryptoCurrency,
)
}
fun formatCryptoAmountShorted(
cryptoAmount: BigDecimal?,
cryptoCurrency: String,
@ -305,7 +334,7 @@ object BigDecimalFormatter {
.getOrElse { e ->
// Currency code is not valid ISO 4217 code
if (e is IllegalArgumentException) {
Currency.getInstance(TEMP_CURRENCY_CODE)
usdCurrency
} else {
throw e
}
@ -316,7 +345,7 @@ object BigDecimalFormatter {
* Adds a proper currency sign for the provided formatted [amount]
* ex. '10.0k" -> "$10.0k", "string" -> "$string"
*/
fun addCurrencySymbolToStringAmount(
private fun addCurrencySymbolToStringAmount(
amount: String,
fiatCurrencyCode: String,
fiatCurrencySymbol: String,
@ -338,6 +367,32 @@ object BigDecimalFormatter {
return formatted
}
/**
* Adds a proper currency sign for the provided formatted [amount]
* ex. '10.0k" -> "ETH 10.0k", "string" -> "ETH string"
*/
private fun addCryptoCurrencySymbolToStringAmount(
amount: String,
cryptoCurrencySymbol: String,
locale: Locale = Locale.getDefault(),
): String {
val sampleAmount = BigDecimal.TEN
val formatter = NumberFormat.getCurrencyInstance(locale).apply {
maximumFractionDigits = 0
minimumFractionDigits = 0
currency = usdCurrency
}
val formatted = formatter.format(sampleAmount)
.replace(sampleAmount.toString(), amount)
return formatted.replaceFiatSymbolWithCrypto(
fiatCurrencySymbol = usdCurrency.symbol,
cryptoCurrencySymbol = cryptoCurrencySymbol,
)
}
/**
* "123456.6" -> "$123.457K"
* "12345.6" -> "$123.046K"
@ -380,6 +435,45 @@ object BigDecimalFormatter {
)
}
/**
* "123456.6" -> "ETH 123.457K"
* "12345.6" -> "123.046K ETH"
* Negative amount is not supported
* @param threeDigitsMethod if true, will format the amount always with 3 significant digits
* @param scale the number of digits to the right of the decimal point
*/
fun formatCompactCryptoAmount(
amount: BigDecimal?,
cryptoCurrencySymbol: String,
threeDigitsMethod: Boolean = false,
decimals: Int = 0,
locale: Locale = Locale.getDefault(),
): String {
if (amount == null) return EMPTY_BALANCE_SIGN
if (amount < BigDecimal.ONE) {
return formatCryptoAmount2(
cryptoAmount = amount,
cryptoCurrency = cryptoCurrencySymbol,
decimals = decimals,
locale = locale,
)
}
val rawAmount = formatCompactAmount(
amount = amount,
locale = locale,
threeDigitsMethod = threeDigitsMethod,
scale = decimals,
)
return addCryptoCurrencySymbolToStringAmount(
amount = rawAmount,
cryptoCurrencySymbol = cryptoCurrencySymbol,
locale = locale,
)
}
/**
* "123456.6" -> "123.457K"
* "12345.6" -> "123.046K"
@ -413,14 +507,61 @@ object BigDecimalFormatter {
return formatter.format(amount.setScale(scale, RoundingMode.HALF_UP))
} else {
val value = amount.setScale(scale, RoundingMode.HALF_UP)
val scaledAmount = amount.setScale(scale, RoundingMode.HALF_UP)
val digitsCount = scaledAmount.longValueExact().toString().count()
val digitsToFormat = 5 - when (digitsCount % 3) {
0 -> 0
1 -> 2
else -> 1
}
val formatter = CompactDecimalFormat.getInstance(
locale,
CompactDecimalFormat.CompactStyle.SHORT,
)
).apply {
minimumSignificantDigits = 2
maximumSignificantDigits = digitsToFormat
}
return formatter.format(value)
return formatter.format(amount.setScale(scale, RoundingMode.HALF_UP))
}
}
// Replaces fiat currency symbol with crypto currency symbol
// with respect to the position of the symbol and whitespace
private fun String.replaceFiatSymbolWithCrypto(fiatCurrencySymbol: String, cryptoCurrencySymbol: String): String {
val str = this
if (str.isEmpty()) return str
return buildString {
when {
str.endsWith(fiatCurrencySymbol) -> {
val withoutSymbol = str.dropLast(fiatCurrencySymbol.length)
val last = withoutSymbol.lastOrNull() ?: return cryptoCurrencySymbol
append(withoutSymbol)
if (last.isNotWhitespace()) {
append("\u2009")
}
append(cryptoCurrencySymbol)
}
str.startsWith(fiatCurrencySymbol) -> {
append(cryptoCurrencySymbol)
val withoutSymbol = str.drop(fiatCurrencySymbol.length)
val first = withoutSymbol.firstOrNull()
?: return cryptoCurrencySymbol
if (first.isNotWhitespace()) {
append("\u2009")
}
append(withoutSymbol)
}
else -> append(str)
}
}
}

View file

@ -1,63 +0,0 @@
package com.tangem.core.ui.utils
import java.math.BigDecimal
import java.math.RoundingMode
import java.util.Locale
internal object BigDecimalFormatterCompat {
/**
* Formats value as [BigDecimalFormatter.formatCompactFiatAmount] does using only "T","B","M","K" suffixes
* Used for < API24 compatibility
*/
@Suppress("MagicNumber", "UnnecessaryParentheses")
fun formatCompactFiatAmountNoLocaleContext(
amount: BigDecimal,
fiatCurrencyCode: String,
fiatCurrencySymbol: String,
locale: Locale = Locale.getDefault(),
): String {
val formatted = formatCompactAmountNoLocaleContext(amount)
return BigDecimalFormatter.addCurrencySymbolToStringAmount(
amount = formatted,
fiatCurrencyCode = fiatCurrencyCode,
fiatCurrencySymbol = fiatCurrencySymbol,
locale = locale,
)
}
/**
* Formats value as [BigDecimalFormatter.formatCompactAmount] does using only "T","B","M","K" suffixes
* Used for < API24 compatibility
*/
@Suppress("MagicNumber", "UnnecessaryParentheses")
fun formatCompactAmountNoLocaleContext(amount: BigDecimal): String {
val value = amount.setScale(0, RoundingMode.HALF_UP).longValueExact()
val formatted = when {
value > 1_000_000_000_000L -> {
val trillion = value / 1_000_000_000_000
val billion = (value % 1_000_000_000_000) / 1_000_000_000
"$trillion.${billion}T"
}
value > 1_000_000_000L -> {
val billion = value / 1_000_000_000
val million = (value % 1_000_000_000) / 1_000_000
"$billion.${million}B"
}
value > 1_000_000L -> {
val million = value / 1_000_000
val thousand = (value % 1_000_000) / 1_000
"$million.${thousand}M"
}
value > 1_000L -> {
val thousand = value / 1_000
"${thousand}K"
}
else -> return value.toString()
}
return formatted
}
}

View file

@ -8,5 +8,6 @@ object StringsSigns {
const val DASH_SIGN = ""
const val LOWER_SIGN = "<"
const val TILDE_SIGN = "~"
const val INFINITY_SIGN = ""
const val NON_BREAKING_SPACE = '\u00A0'
}

View file

@ -99,7 +99,7 @@ internal object TokenMarketInfoConverter : Converter<TokenMarketInfoResponse, To
circulatingSupply = circulatingSupply,
marketCap = marketCap,
volume24h = volume24h,
totalSupply = totalSupply,
maxSupply = maxSupply,
fullyDilutedValuation = fullyDilutedValuation,
)
}

View file

@ -46,7 +46,7 @@ data class TokenMarketInfo(
val circulatingSupply: BigDecimal?,
val marketCap: BigDecimal?,
val volume24h: BigDecimal?,
val totalSupply: BigDecimal?,
val maxSupply: BigDecimal?,
val fullyDilutedValuation: BigDecimal?,
)

View file

@ -1,20 +1,43 @@
package com.tangem.domain.staking.model.stakekit.action
enum class StakingActionType(val type: String) {
STAKE("Stake"),
UNSTAKE("Unstake"),
CLAIM_REWARDS("Claim Rewards"),
RESTAKE_REWARDS("Restake Rewards"),
WITHDRAW("Withdraw"),
RESTAKE("Restake"),
CLAIM_UNSTAKED("Claim Unstaked"),
UNLOCK_LOCKED("Unlock Locked"),
STAKE_LOCKED("Stake Locked"),
VOTE("Vote"),
REVOKE("Revoke"),
VOTE_LOCKED("Vote Locked"),
REVOTE("Revote"),
REBOND("Rebond"),
MIGRATE("Migrate"),
UNKNOWN("Unknown"),
enum class StakingActionType {
STAKE,
UNSTAKE,
CLAIM_REWARDS,
RESTAKE_REWARDS,
WITHDRAW,
RESTAKE,
CLAIM_UNSTAKED,
UNLOCK_LOCKED,
STAKE_LOCKED,
VOTE,
REVOKE,
VOTE_LOCKED,
REVOTE,
REBOND,
MIGRATE,
UNKNOWN,
;
companion object {
val StakingActionType.asAnalyticName
get() = when (this) {
STAKE -> "Stake"
UNSTAKE -> "Unstake"
CLAIM_REWARDS -> "Claim Rewards"
RESTAKE_REWARDS -> "Restake Rewards"
WITHDRAW -> "Withdraw"
RESTAKE -> "Restake"
CLAIM_UNSTAKED -> "Claim Unstaked"
UNLOCK_LOCKED -> "Unlock Locked"
STAKE_LOCKED -> "Stake Locked"
VOTE -> "Vote"
REVOKE -> "Revoke"
VOTE_LOCKED -> "Vote Locked"
REVOTE -> "Revote"
REBOND -> "Rebond"
MIGRATE -> "Migrate"
UNKNOWN -> "Unknown"
}
}
}

View file

@ -18,6 +18,7 @@ import java.math.BigDecimal
@Stable
internal class MetricsConverter(
private val appCurrency: Provider<AppCurrency>,
private val tokenSymbol: String,
private val onInfoClick: (InfoBottomSheetContent) -> Unit,
) : Converter<TokenMarketInfo.Metrics, MetricsUM> {
@ -99,12 +100,12 @@ internal class MetricsConverter(
},
),
InfoPointUM(
title = resourceReference(R.string.markets_token_details_total_supply),
value = totalSupply.formatAmount(crypto = true),
title = resourceReference(R.string.markets_token_details_max_supply),
value = maxSupply.formatMaxSupply(),
onInfoClick = {
onInfoClick(
InfoBottomSheetContent(
title = resourceReference(R.string.markets_token_details_total_supply_full),
title = resourceReference(R.string.markets_token_details_max_supply_full),
body = resourceReference(R.string.markets_token_details_total_supply_description),
),
)
@ -115,13 +116,26 @@ internal class MetricsConverter(
}
}
private fun BigDecimal?.formatMaxSupply(): String {
when (this) {
null -> return StringsSigns.DASH_SIGN
BigDecimal.ZERO -> return StringsSigns.INFINITY_SIGN
}
return this.formatAmount(crypto = true)
}
private fun BigDecimal?.formatAmount(crypto: Boolean = false): String {
if (this == null) return StringsSigns.DASH_SIGN
return if (crypto) {
BigDecimalFormatter.formatCompactAmount(amount = this)
BigDecimalFormatter.formatCompactCryptoAmount(
amount = this,
cryptoCurrencySymbol = tokenSymbol,
)
} else {
val currency = appCurrency()
BigDecimalFormatter.formatCompactFiatAmount(
amount = this,
fiatCurrencyCode = currency.code,

View file

@ -12,8 +12,8 @@ import com.tangem.utils.converter.Converter
@Stable
internal class TokenMarketInfoConverter(
appCurrency: Provider<AppCurrency>,
onInfoClick: (InfoBottomSheetContent) -> Unit,
private val appCurrency: Provider<AppCurrency>,
private val onInfoClick: (InfoBottomSheetContent) -> Unit,
onLinkClick: (LinksUM.Link) -> Unit,
onPricePerformanceIntervalChanged: (PriceChangeInterval) -> Unit,
onInsightsIntervalChanged: (PriceChangeInterval) -> Unit,
@ -28,7 +28,6 @@ internal class TokenMarketInfoConverter(
@Suppress("UnusedPrivateMember")
// TODO second markets iteration
private val securityScoreConverter = SecurityScoreConverter(onInfoClick = onInfoClick)
private val metricsConverter = MetricsConverter(appCurrency = appCurrency, onInfoClick = onInfoClick)
private val pricePerformanceConverter = PricePerformanceConverter(
appCurrency = appCurrency,
onIntervalChanged = onPricePerformanceIntervalChanged,
@ -36,6 +35,12 @@ internal class TokenMarketInfoConverter(
private val linksConverter = LinksConverter(onLinkClick = onLinkClick)
override fun convert(value: TokenMarketInfo): MarketsTokenDetailsUM.InformationBlocks {
val metricsConverter = MetricsConverter(
tokenSymbol = value.symbol,
appCurrency = appCurrency,
onInfoClick = onInfoClick,
)
return MarketsTokenDetailsUM.InformationBlocks(
insights = value.insights?.let { insightsConverter.convert(it) },
securityScore = null,

View file

@ -28,6 +28,7 @@ import kotlinx.collections.immutable.persistentListOf
internal fun LinksBlock(state: LinksUM, modifier: Modifier = Modifier) {
InformationBlock(
modifier = modifier,
contentHorizontalPadding = 0.dp,
title = {
Text(
text = stringResource(id = R.string.markets_token_details_links),
@ -81,7 +82,7 @@ private fun SubBlock(
showDivider = !lastBlock,
) {
Column(
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing12),
modifier = Modifier.padding(TangemTheme.dimens.spacing12),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
) {
Text(
@ -111,6 +112,7 @@ private fun SubBlock(
fun LinksBlockPlaceholder(modifier: Modifier = Modifier) {
InformationBlock(
modifier = modifier,
contentHorizontalPadding = 0.dp,
title = {
TextShimmer(
modifier = Modifier.fillMaxWidth(),
@ -134,7 +136,7 @@ private fun SubBlockPlaceholder(modifier: Modifier = Modifier, lastBlock: Boolea
showDivider = !lastBlock,
) {
Column(
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing12),
modifier = Modifier.padding(TangemTheme.dimens.spacing12),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
) {
TextShimmer(

View file

@ -3,6 +3,7 @@ package com.tangem.features.markets.portfolio.impl.model
import com.tangem.common.ui.userwallet.converter.UserWalletItemUMConverter
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.core.ui.components.rows.model.BlockchainRowUM
import com.tangem.domain.markets.TokenMarketInfo
import com.tangem.domain.markets.TokenMarketParams
@ -45,47 +46,51 @@ internal class AddToPortfolioBSContentUMFactory(
fun create(
portfolioData: PortfolioData,
portfolioUIData: PortfolioUIData,
selectedWallet: UserWallet,
alreadyAddedNetworks: Set<String>,
selectedWallet: UserWallet?,
alreadyAddedNetworks: Set<String>?,
): TangemBottomSheetConfig {
return TangemBottomSheetConfig(
isShow = portfolioUIData.portfolioBSVisibilityModel.addToPortfolioBSVisibility,
onDismissRequest = { onAddToPortfolioVisibilityChange(false) },
content = AddToPortfolioBSContentUM(
selectedWallet = selectedWallet.toSelectedUserWalletItemUM(),
selectNetworkUM = SelectNetworkUMConverter(
networksWithToggle = portfolioUIData.addToPortfolioData.associateWithToggle(
userWalletId = selectedWallet.walletId,
alreadyAddedNetworkIds = alreadyAddedNetworks,
),
alreadyAddedNetworks = alreadyAddedNetworks,
onNetworkSwitchClick = onNetworkSwitchClick,
).convert(value = token),
isScanCardNotificationVisible = portfolioUIData.hasMissedDerivations,
continueButtonEnabled = portfolioUIData.addToPortfolioData.isUserAddedNetworks(
userWalletId = selectedWallet.walletId,
),
onContinueButtonClick = {
val alreadyAddedNetworkIds = portfolioData.walletsWithCurrencies[selectedWallet].orEmpty()
.map { it.status.currency.network.backendId }
.toSet()
onContinueClick(
selectedWallet.walletId,
portfolioUIData.addToPortfolioData.getAddedNetworks(
content = if (selectedWallet != null && alreadyAddedNetworks != null) {
AddToPortfolioBSContentUM(
selectedWallet = selectedWallet.toSelectedUserWalletItemUM(),
selectNetworkUM = SelectNetworkUMConverter(
networksWithToggle = portfolioUIData.addToPortfolioData.associateWithToggle(
userWalletId = selectedWallet.walletId,
alreadyAddedNetworkIds = alreadyAddedNetworkIds,
alreadyAddedNetworkIds = alreadyAddedNetworks,
),
)
},
walletSelectorConfig = crateWalletSelectorBSConfig(
isShow = portfolioUIData.portfolioBSVisibilityModel.walletSelectorBSVisibility,
portfolioData = portfolioData,
selectedWalletId = selectedWallet.walletId,
),
isWalletBlockVisible = portfolioData.walletsWithCurrencies
.filterKeys(UserWallet::isMultiCurrency).size > 1,
),
alreadyAddedNetworks = alreadyAddedNetworks,
onNetworkSwitchClick = onNetworkSwitchClick,
).convert(value = token),
isScanCardNotificationVisible = portfolioUIData.hasMissedDerivations,
continueButtonEnabled = portfolioUIData.addToPortfolioData.isUserAddedNetworks(
userWalletId = selectedWallet.walletId,
),
onContinueButtonClick = {
val alreadyAddedNetworkIds = portfolioData.walletsWithCurrencies[selectedWallet].orEmpty()
.map { it.status.currency.network.backendId }
.toSet()
onContinueClick(
selectedWallet.walletId,
portfolioUIData.addToPortfolioData.getAddedNetworks(
userWalletId = selectedWallet.walletId,
alreadyAddedNetworkIds = alreadyAddedNetworkIds,
),
)
},
walletSelectorConfig = crateWalletSelectorBSConfig(
isShow = portfolioUIData.portfolioBSVisibilityModel.walletSelectorBSVisibility,
portfolioData = portfolioData,
selectedWalletId = selectedWallet.walletId,
),
isWalletBlockVisible = portfolioData.walletsWithCurrencies
.filterKeys(UserWallet::isMultiCurrency).size > 1,
)
} else {
TangemBottomSheetConfigContent.Empty
},
)
}

View file

@ -30,9 +30,8 @@ internal class MyPortfolioUMFactory(
fun create(portfolioData: PortfolioData, portfolioUIData: PortfolioUIData): MyPortfolioUM {
val addToPortfolioData = portfolioUIData.addToPortfolioData
val hasAvailableNetworks = addToPortfolioData.availableNetworks?.isEmpty() == true
val isOnlySingleWalletsAdded = portfolioData.walletsWithCurrencies.keys.all { !it.isMultiCurrency }
if (hasAvailableNetworks || isOnlySingleWalletsAdded) return MyPortfolioUM.Unavailable
val isOnlyUnavailableNetworks = addToPortfolioData.availableNetworks?.isEmpty() == true
if (isOnlyUnavailableNetworks) return MyPortfolioUM.Unavailable
val walletsWithCurrencies = if (addToPortfolioData.availableNetworks == null) {
portfolioData.walletsWithCurrencies
@ -79,16 +78,13 @@ internal class MyPortfolioUMFactory(
val selectedWallet = portfolioData.walletsWithCurrencies.keys
.firstOrNull { it.walletId == portfolioUIData.selectedWalletId }
?: portfolioData.walletsWithCurrencies.keys.firstOrNull { it.isMultiCurrency }
?: error("walletsWithCurrencies don't contain selected wallet or any multi-currency wallet")
val availableNetworks = portfolioUIData.addToPortfolioData.availableNetworks.orEmpty()
val alreadyAddedNetworks = requireNotNull(
value = portfolioData.walletsWithCurrencies.filterAvailableNetworks(availableNetworks)[selectedWallet],
lazyMessage = { "walletsWithCurrencies don't contain ${selectedWallet.walletId}" },
)
.map { it.status.currency.network.backendId }
.toSet()
val alreadyAddedNetworks = portfolioData.walletsWithCurrencies
.filterAvailableNetworks(availableNetworks)[selectedWallet]
?.map { it.status.currency.network.backendId }
?.toSet()
return addToPortfolioBSContentUMFactory.create(
portfolioData = portfolioData,

View file

@ -3,6 +3,7 @@ package com.tangem.features.staking.impl.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
import com.tangem.domain.staking.model.stakekit.action.StakingActionType.Companion.asAnalyticName
internal sealed class StakingAnalyticsEvents(
event: String,
@ -47,7 +48,7 @@ internal sealed class StakingAnalyticsEvents(
params = mapOf(
AnalyticsParam.TOKEN_PARAM to token,
"Validator" to validator,
"Action" to action.type,
"Action" to action.asAnalyticName,
),
)
@ -60,7 +61,7 @@ internal sealed class StakingAnalyticsEvents(
params = mapOf(
AnalyticsParam.TOKEN_PARAM to token,
"Validator" to validator,
"Action" to action.type,
"Action" to action.asAnalyticName,
),
)
@ -143,7 +144,7 @@ internal sealed class StakingAnalyticsEvents(
event = "Errors",
params = mapOf(
AnalyticsParam.TOKEN_PARAM to token,
"ErrorType" to errorType,
AnalyticsParam.ERROR_DESCRIPTION to errorType,
),
)

View file

@ -8,7 +8,6 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideIn
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
@ -19,7 +18,6 @@ import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.*
import androidx.compose.material3.BottomSheetDefaults
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -46,7 +44,8 @@ import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.paging.compose.collectAsLazyPagingItems
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.core.ui.components.*
import com.tangem.core.ui.components.BottomFade
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.atoms.Hand
import com.tangem.core.ui.components.atoms.handComposableComponentHeight
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
@ -54,6 +53,7 @@ import com.tangem.core.ui.components.bottomsheets.chooseaddress.ChooseAddressBot
import com.tangem.core.ui.components.bottomsheets.chooseaddress.ChooseAddressBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheet
import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheetConfig
import com.tangem.core.ui.components.rememberIsKeyboardVisible
import com.tangem.core.ui.components.sheetscaffold.*
import com.tangem.core.ui.components.snackbar.CopiedTextSnackbar
import com.tangem.core.ui.components.snackbar.TangemSnackbar
@ -468,7 +468,11 @@ private inline fun BaseScaffoldWithMarkets(
}
BottomSheetScrim(
color = BottomSheetDefaults.ScrimColor,
color = if (state.showMarketsOnboarding) {
Color.Black.copy(alpha = .65f)
} else {
BottomSheetDefaults.ScrimColor
},
visible = bottomSheetState.targetValue == TangemSheetValue.Expanded ||
state.showMarketsOnboarding,
onDismissRequest = {
@ -575,7 +579,7 @@ internal fun MarketsHint(isVisible: Boolean, modifier: Modifier = Modifier) {
@Composable
private fun MarketsTooltipContent(modifier: Modifier = Modifier) {
val backgroundColor = TangemTheme.colors.background.primary
val backgroundColor = TangemTheme.colors.background.action
val cornerRadius = CornerRadius(x = 14.dp.toPx())
val tipDpSize = DpSize(width = 20.dp, height = 8.dp)