Updated on 2026-08-14
This commit is contained in:
parent
4e28463b8a
commit
546bcc908f
24 changed files with 624 additions and 131 deletions
|
|
@ -7,9 +7,12 @@ internal class DateTimeAdapter : JsonAdapter<DateTime>() {
|
|||
|
||||
@FromJson
|
||||
override fun fromJson(reader: JsonReader): DateTime? {
|
||||
val dateString = reader.nextString() ?: return null
|
||||
|
||||
return DateTime.parse(dateString)
|
||||
return if (reader.peek() == JsonReader.Token.NULL) {
|
||||
reader.nextNull<DateTime>()
|
||||
} else {
|
||||
val dateString = reader.nextString()
|
||||
DateTime.parse(dateString)
|
||||
}
|
||||
}
|
||||
|
||||
@ToJson
|
||||
|
|
|
|||
|
|
@ -10,9 +10,13 @@ internal class LocalDateAdapter : JsonAdapter<LocalDate>() {
|
|||
|
||||
@FromJson
|
||||
override fun fromJson(reader: JsonReader): LocalDate? {
|
||||
return if (reader.peek() == JsonReader.Token.NULL) {
|
||||
reader.nextNull<LocalDate>()
|
||||
} else {
|
||||
val dateString = reader.nextString()
|
||||
return LocalDate.parse(dateString, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
@ToJson
|
||||
override fun toJson(writer: JsonWriter, value: LocalDate?) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.datasource.api.markets.models.response
|
|||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.joda.time.DateTime
|
||||
import java.math.BigDecimal
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
|
@ -26,6 +27,8 @@ data class TokenMarketInfoResponse(
|
|||
val insights: Insights?,
|
||||
@Json(name = "metrics")
|
||||
val metrics: Metrics?,
|
||||
@Json(name = "security_data")
|
||||
val securityData: SecurityData?,
|
||||
@Json(name = "links")
|
||||
val links: Links?,
|
||||
@Json(name = "price_performance")
|
||||
|
|
@ -144,6 +147,28 @@ data class TokenMarketInfoResponse(
|
|||
val allTime: Range?,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class SecurityData(
|
||||
@Json(name = "total_security_score")
|
||||
val totalSecurityScore: Float,
|
||||
@Json(name = "provider_data")
|
||||
val providerData: List<ProviderData>,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ProviderData(
|
||||
@Json(name = "provider_id")
|
||||
val providerId: String,
|
||||
@Json(name = "provider_name")
|
||||
val providerName: String,
|
||||
@Json(name = "link")
|
||||
val link: String?,
|
||||
@Json(name = "security_score")
|
||||
val securityScore: Float,
|
||||
@Json(name = "last_audit_date")
|
||||
val lastAuditDate: DateTime?,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Range(
|
||||
@Json(name = "low_price")
|
||||
|
|
|
|||
|
|
@ -568,7 +568,7 @@
|
|||
<string name="onramp_no_available_providers">Keine verfügbaren Anbieter für diese Währung</string>
|
||||
<string name="onramp_pay_with">Bezahlen mit</string>
|
||||
<string name="onramp_redirecting_to_provider_subtitle">Du kannst Deine Transaktion beim Drittanbieter %s abschließen.</string>
|
||||
<string name="onramp_redirecting_to_provider_title">Umleitung auf %s...</string>
|
||||
<string name="onramp_redirecting_to_provider_title">Umleitung auf %s …</string>
|
||||
<string name="onramp_residency_bottomsheet_country_not_supported">Unsere Dienstleistungen sind in diesem Land nicht verfügbar</string>
|
||||
<string name="onramp_residency_bottomsheet_country_subtitle">Änder oder bestätige bitte</string>
|
||||
<string name="onramp_residency_bottomsheet_title">Dein Wohnsitz wurde identifiziert als</string>
|
||||
|
|
|
|||
|
|
@ -180,6 +180,7 @@
|
|||
<string name="common_terms_of_use">Condiciones de uso</string>
|
||||
<string name="common_today">Hoy</string>
|
||||
<string name="common_transaction_failed">Transacción fallida</string>
|
||||
<string name="common_transaction_status">Estado de la transacción</string>
|
||||
<string name="common_transactions">Transacciones</string>
|
||||
<string name="common_transfer">Transferencia</string>
|
||||
<string name="common_understand">Entiendo</string>
|
||||
|
|
@ -187,6 +188,7 @@
|
|||
<string name="common_unreachable">Inaccesible</string>
|
||||
<string name="common_unstake">Termine el staking</string>
|
||||
<string name="common_week">semana</string>
|
||||
<string name="common_with">con</string>
|
||||
<string name="common_yes">Sí</string>
|
||||
<string name="contract_address_copied_message">Dirección del contract copiada</string>
|
||||
<string name="currency_subtitle_expanded">Redes disponibles</string>
|
||||
|
|
@ -427,6 +429,7 @@
|
|||
<string name="markets_token_details_fully_diluted_valuation_description">El valor teórico total de una criptomoneda si todas las monedas que podrían existir estuvieran en circulación, incluidas las que actualmente no circulan.</string>
|
||||
<string name="markets_token_details_fully_diluted_valuation_full">Valoración totalmente diluida</string>
|
||||
<string name="markets_token_details_genesis_date">Dato de Genesis</string>
|
||||
<string name="markets_token_details_genesis_date_description">Vacío</string>
|
||||
<string name="markets_token_details_high">Alto</string>
|
||||
<string name="markets_token_details_holders">Titulares</string>
|
||||
<string name="markets_token_details_holders_description">El cambio en el número de poseedores de tokens dentro de un período de tiempo específico</string>
|
||||
|
|
@ -437,6 +440,7 @@
|
|||
<string name="markets_token_details_liquidity_description">El cambio en la cantidad de liquidez disponible para el token durante el período de tiempo especificado</string>
|
||||
<string name="markets_token_details_liquidity_full">Liquidez</string>
|
||||
<string name="markets_token_details_liquidity_index">Índice de liquidez</string>
|
||||
<string name="markets_token_details_liquidity_index_description">Vacío</string>
|
||||
<string name="markets_token_details_listed_on">Listado en</string>
|
||||
<string name="markets_token_details_low">Bajo</string>
|
||||
<string name="markets_token_details_market_capitalization">Capital. de mercado</string>
|
||||
|
|
@ -453,6 +457,7 @@
|
|||
<string name="markets_token_details_price_performance">Rendimiento de precios</string>
|
||||
<string name="markets_token_details_repository">Repositorio</string>
|
||||
<string name="markets_token_details_security_score">Puntuación de seguridad</string>
|
||||
<string name="markets_token_details_security_score_description">La puntuación de seguridad de un token es una métrica que evalúa el nivel de seguridad de una blockchain o token en función de varios factores y se genera a partir de las fuentes que se enumeran a continuación.</string>
|
||||
<string name="markets_token_details_social">Social</string>
|
||||
<string name="markets_token_details_total_supply">Suministro total</string>
|
||||
<string name="markets_token_details_total_supply_description">La cantidad máxima de monedas o tokens que pueden existir para una criptomoneda en particular</string>
|
||||
|
|
@ -509,12 +514,12 @@
|
|||
<string name="onboarding_navbar_title_creating_backup">Creando un backup</string>
|
||||
<string name="onboarding_seed_button_read_more">Leer más sobre seed phrase</string>
|
||||
<plurals name="onboarding_seed_generate_message_words_count">
|
||||
<item quantity="one"></item>
|
||||
<item quantity="one">Vacío</item>
|
||||
<item quantity="other">Escriba estas %d palabras en el orden que se indica a continuación y guárdelas en un lugar seguro y secreto.</item>
|
||||
</plurals>
|
||||
<string name="onboarding_seed_generate_title">Su seed phrase</string>
|
||||
<plurals name="onboarding_seed_generate_words_count">
|
||||
<item quantity="one"></item>
|
||||
<item quantity="one">Vacío</item>
|
||||
<item quantity="other">%d palabras</item>
|
||||
</plurals>
|
||||
<string name="onboarding_seed_import_message">Para importar su billetera, ingrese su seed phrase en el campo de abajo</string>
|
||||
|
|
@ -566,12 +571,15 @@
|
|||
<string name="onramp_min_amount_restriction">La cantidad a comprar debe ser como mínimo %s</string>
|
||||
<string name="onramp_no_available_providers">No hay proveedores disponibles para esta moneda</string>
|
||||
<string name="onramp_pay_with">Pagar con</string>
|
||||
<string name="onramp_redirecting_to_provider_subtitle">Podrá completar su transacción en el proveedor externo, %s</string>
|
||||
<string name="onramp_redirecting_to_provider_title">Redirigiendo a %s...</string>
|
||||
<string name="onramp_residency_bottomsheet_country_not_supported">Nuestros servicios no están disponibles en este país</string>
|
||||
<string name="onramp_residency_bottomsheet_country_subtitle">Cámbielo o confírmelo</string>
|
||||
<string name="onramp_residency_bottomsheet_title">Su residencia ha sido identificada como</string>
|
||||
<string name="onramp_settings_residence">Residencia</string>
|
||||
<string name="onramp_settings_residence_description">Seleccione el país correcto para garantizar opciones de pago y servicios precisos.</string>
|
||||
<string name="onramp_settings_title">Ajustes</string>
|
||||
<string name="onramp_transaction_status_footer_text">Puede comprobar el estado de la transacción desde la página del token</string>
|
||||
<string name="onramp_via">Vía</string>
|
||||
<string name="organize_tokens_group">Agrupar</string>
|
||||
<string name="organize_tokens_sort_by_balance">Por saldo</string>
|
||||
|
|
@ -804,7 +812,7 @@
|
|||
<string name="staking_unbonding">Desunión</string>
|
||||
<string name="staking_unlocked_locked">Desbloquear</string>
|
||||
<string name="staking_unlocking">Desbloqueando</string>
|
||||
<string name="staking_unstake_amount_requirement_error">La cantidad para el staking debe ser al menos %s</string>
|
||||
<string name="staking_unstake_amount_requirement_error">La cantidad para el unstaking debe ser al menos %s</string>
|
||||
<string name="staking_unstake_amount_validation_error">El monto excede el saldo apostado</string>
|
||||
<string name="staking_unstaked">Sin staking</string>
|
||||
<string name="staking_unstaking">Unstaking</string>
|
||||
|
|
@ -884,6 +892,7 @@
|
|||
<string name="transaction_history_transaction_from_address">desde: %s</string>
|
||||
<string name="transaction_history_transaction_to_address">a: %s</string>
|
||||
<string name="transaction_history_transaction_validator">validador: %s</string>
|
||||
<string name="transfer_min_amount_error">Mínimo %s</string>
|
||||
<string name="transfer_notification_invalid_minimum_transaction_amount_text">El monto mínimo para realizar esta transacción es %1$s.</string>
|
||||
<string name="try_to_load_data_again_button_title">Inténtelo de nuevo</string>
|
||||
<string name="twin_error_same_card">Ha escaneado la misma tarjeta. Para crear una billetera gemela, necesite escanear la tarjeta con no. %d</string>
|
||||
|
|
@ -949,6 +958,9 @@
|
|||
<string name="wallet_network_group_title">%s red</string>
|
||||
<string name="wallet_notification_address_copied">La dirección se copió correctamente</string>
|
||||
<string name="wallet_notification_no_internet">Sin conexión a internet</string>
|
||||
<string name="wallet_promo_banner_button_title">Consíguelo ahora con un 10 %% de descuento</string>
|
||||
<string name="wallet_promo_banner_description">Accede a más de 13 000 criptomonedas. Compra, vende, intercambia y realiza staking con un solo toque.\nVincula hasta tres tarjetas para hacer copias de seguridad.</string>
|
||||
<string name="wallet_promo_banner_title">Descubre Tangem Wallet</string>
|
||||
<string name="wallet_settings_title">Ajusta de la wallet</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
<string name="warning_access_denied_message">Use %s o escanee una tarjeta/anillo para desbloquear el acceso a su billetera</string>
|
||||
|
|
|
|||
|
|
@ -884,6 +884,7 @@
|
|||
<string name="transaction_history_transaction_from_address">de : %s</string>
|
||||
<string name="transaction_history_transaction_to_address">à : %s</string>
|
||||
<string name="transaction_history_transaction_validator">validateur : %s</string>
|
||||
<string name="transfer_min_amount_error">Minimum %s</string>
|
||||
<string name="transfer_notification_invalid_minimum_transaction_amount_text">Le montant minimum pour effectuer cette transaction est %1$s.</string>
|
||||
<string name="try_to_load_data_again_button_title">Réessayez</string>
|
||||
<string name="twin_error_same_card">Vous avez scanné la même carte. Pour créer un portefeuille jumeau, vous devez scanner la carte portant le numéro %d</string>
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@
|
|||
<string name="common_terms_of_use">利用規約</string>
|
||||
<string name="common_today">今日</string>
|
||||
<string name="common_transaction_failed">取引が失敗しました</string>
|
||||
<string name="common_transaction_status">取引状況</string>
|
||||
<string name="common_transactions">取引</string>
|
||||
<string name="common_transfer">送金</string>
|
||||
<string name="common_understand">わかりました</string>
|
||||
|
|
@ -184,6 +185,7 @@
|
|||
<string name="common_unreachable">アクセスできません</string>
|
||||
<string name="common_unstake">ステーキング解除</string>
|
||||
<string name="common_week">週</string>
|
||||
<string name="common_with">で</string>
|
||||
<string name="common_yes">はい</string>
|
||||
<string name="contract_address_copied_message">コントラクトアドレスをコピーしました!</string>
|
||||
<string name="currency_subtitle_expanded">利用可能なネットワーク</string>
|
||||
|
|
@ -567,6 +569,7 @@
|
|||
<string name="onramp_settings_residence">住居</string>
|
||||
<string name="onramp_settings_residence_description">正確なお支払い方法とサービスを確保するため、正しい国を選択してください。</string>
|
||||
<string name="onramp_settings_title">設定</string>
|
||||
<string name="onramp_transaction_status_footer_text">トークンページから取引状況を確認できます</string>
|
||||
<string name="onramp_via">経由</string>
|
||||
<string name="organize_tokens_group">グループ</string>
|
||||
<string name="organize_tokens_sort_by_balance">残高順</string>
|
||||
|
|
@ -943,6 +946,9 @@
|
|||
<string name="wallet_network_group_title">%sネットワーク</string>
|
||||
<string name="wallet_notification_address_copied">アドレスがクリップボードにコピーされました</string>
|
||||
<string name="wallet_notification_no_internet">インターネット接続がありません</string>
|
||||
<string name="wallet_promo_banner_button_title">今すぐ10 %オフで購入</string>
|
||||
<string name="wallet_promo_banner_description">1.3万種類以上の暗号資産にアクセス。ワンタップで買付、売却、スワップ、ステーキングが可能です。\nバックアップ用に最大3枚のカードを連携できます。</string>
|
||||
<string name="wallet_promo_banner_title">Tangemウォレットを見る</string>
|
||||
<string name="wallet_settings_title">ウォレット設定</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
<string name="warning_access_denied_message">%sを使用するか、カード / リングをスキャンしてウォレットにアクセスしてください</string>
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@
|
|||
<string name="common_terms_of_use">Условиями использования</string>
|
||||
<string name="common_today">Сегодня</string>
|
||||
<string name="common_transaction_failed">Ошибка транзакции</string>
|
||||
<string name="common_transaction_status">Статус транзакции</string>
|
||||
<string name="common_transactions">Транзакции</string>
|
||||
<string name="common_transfer">Перевод</string>
|
||||
<string name="common_understand">Я понял</string>
|
||||
|
|
@ -190,6 +191,7 @@
|
|||
<string name="common_unreachable">Недоступно</string>
|
||||
<string name="common_unstake">Завершить стейкинг</string>
|
||||
<string name="common_week">неделю</string>
|
||||
<string name="common_with">с</string>
|
||||
<string name="common_yes">Да</string>
|
||||
<string name="contract_address_copied_message">Адрес контракта скопирован!</string>
|
||||
<string name="currency_subtitle_expanded">Доступные сети</string>
|
||||
|
|
@ -576,7 +578,10 @@
|
|||
<string name="onramp_currency_search">Поиск по валюте</string>
|
||||
<string name="onramp_max_amount_restriction">Сумма покупки не может быть больше, чем %s</string>
|
||||
<string name="onramp_min_amount_restriction">Сумма покупки должна составлять минимум %s</string>
|
||||
<string name="onramp_no_available_providers">Для данной валюты нет доступных провайдеров</string>
|
||||
<string name="onramp_pay_with">Оплата с</string>
|
||||
<string name="onramp_redirecting_to_provider_subtitle">Вы сможете завершить транзакцию через сервис стороннего провайдера, %s</string>
|
||||
<string name="onramp_redirecting_to_provider_title">Переход к %s ...</string>
|
||||
<string name="onramp_residency_bottomsheet_country_not_supported">Наши сервисы недоступны в данной стране</string>
|
||||
<string name="onramp_settings_title">Настройки</string>
|
||||
<string name="onramp_via">Через</string>
|
||||
|
|
@ -860,14 +865,14 @@
|
|||
<string name="toast_balances_shown">Балансы показаны</string>
|
||||
<string name="toast_undo">Отменить</string>
|
||||
<string name="token_button_unavailability_generic_description">Выбранная операция в данный момент недоступна. Попробуйте позже.</string>
|
||||
<string name="token_button_unavailability_reason_buy_unavailable">В данный момент покупка монеты %s недоступна. Следите за нашими обновлениями.</string>
|
||||
<string name="token_button_unavailability_reason_buy_unavailable">Покупка %s в данный момент не поддерживается ни одним провайдером. Мы работаем над добавлением новых возможностей. Следите за нашими новостями.</string>
|
||||
<string name="token_button_unavailability_reason_empty_balance_sell">У вас нет средств для продажи. Пополните счет, чтобы иметь возможность продать с него средства.</string>
|
||||
<string name="token_button_unavailability_reason_empty_balance_send">У вас нет средств для отправки. Пополните счет, чтобы иметь возможность отправить с него средства.</string>
|
||||
<string name="token_button_unavailability_reason_not_exchangeable">В данный момент обмен монеты %s недоступен. Следите за нашими обновлениями.</string>
|
||||
<string name="token_button_unavailability_reason_not_exchangeable">Обмен %s в данный момент не поддерживается ни одним провайдером. Мы работаем над добавлением новых возможностей. Следите за нашими новостями.</string>
|
||||
<string name="token_button_unavailability_reason_pending_transaction_sell">Продажа средств станет доступной после завершения транзакции(-ий) в сети %s</string>
|
||||
<string name="token_button_unavailability_reason_pending_transaction_send">Отправка средств станет доступной после завершения транзакции(-ий) в сети %s</string>
|
||||
<string name="token_button_unavailability_reason_sell_unavailable">В данный момент продажа %s недоступна. Следите за нашими обновлениями.</string>
|
||||
<string name="token_button_unavailability_reason_staking_unavailable">В данный момент стейкинг монеты %s недоступен. Следите за нашими обновлениями.</string>
|
||||
<string name="token_button_unavailability_reason_sell_unavailable">Продажа %s в данный момент не поддерживается ни одним провайдером. Мы работаем над добавлением новых возможностей. Следите за нашими новостями.</string>
|
||||
<string name="token_button_unavailability_reason_staking_unavailable">Стейкинг %s в данный момент не поддерживается ни одним провайдером. Мы работаем над добавлением новых возможностей. Следите за нашими новостями.</string>
|
||||
<string name="token_details_generate_xpub">Сгенерировать XPUB</string>
|
||||
<string name="token_details_hide_alert_hide">Скрыть</string>
|
||||
<string name="token_details_hide_alert_message">Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно через страницу управления токенами.</string>
|
||||
|
|
@ -893,6 +898,7 @@
|
|||
<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="transfer_min_amount_error">Минимум %s</string>
|
||||
<string name="transfer_notification_invalid_minimum_transaction_amount_text">Минимальная сумма транзакции равна %1$s.</string>
|
||||
<string name="try_to_load_data_again_button_title">Попробовать снова</string>
|
||||
<string name="twin_error_same_card">Вы отсканировали ту же карту. Для создания twin-кошелька вам необходимо отсканировать карту с номером %d</string>
|
||||
|
|
@ -958,6 +964,9 @@
|
|||
<string name="wallet_network_group_title">Сеть %s</string>
|
||||
<string name="wallet_notification_address_copied">Адрес скопирован в буфер обмена</string>
|
||||
<string name="wallet_notification_no_internet">Нет соединения с интернетом</string>
|
||||
<string name="wallet_promo_banner_button_title">Получить с 10%% скидкой</string>
|
||||
<string name="wallet_promo_banner_description">Получите доступ к более чем 13 000 криптовалют. Покупайте, продавайте, обменяйте и стейкайте в один клик. Свяжите до трех карт для резервного копирования. </string>
|
||||
<string name="wallet_promo_banner_title">Откройте Tangem Wallet </string>
|
||||
<string name="wallet_settings_title">Настройки кошелька</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
<string name="warning_access_denied_message">Используйте %s или отсканируйте карту/кольцо, чтобы разблокировать доступ к вашему кошельку</string>
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@
|
|||
<string name="common_terms_of_use">Умовами використання</string>
|
||||
<string name="common_today">Сьогодні</string>
|
||||
<string name="common_transaction_failed">Помилка транзакції</string>
|
||||
<string name="common_transaction_status">Статус транзакції</string>
|
||||
<string name="common_transactions">Транзакції</string>
|
||||
<string name="common_transfer">Переказ</string>
|
||||
<string name="common_understand">Я зрозумів</string>
|
||||
|
|
@ -193,6 +194,7 @@
|
|||
<string name="common_unreachable">Недоступно</string>
|
||||
<string name="common_unstake">Скасувати стейкінг</string>
|
||||
<string name="common_week">тиждень</string>
|
||||
<string name="common_with">з</string>
|
||||
<string name="common_yes">Так</string>
|
||||
<string name="contract_address_copied_message">Адреса контракту скопійована!</string>
|
||||
<string name="currency_subtitle_expanded">Доступні мережі</string>
|
||||
|
|
@ -465,6 +467,7 @@
|
|||
<string name="markets_token_details_price_performance">Цінова ефективність</string>
|
||||
<string name="markets_token_details_repository">Репозиторій</string>
|
||||
<string name="markets_token_details_security_score">Оцінка безпеки</string>
|
||||
<string name="markets_token_details_security_score_description">Оцінка безпеки токена – це метрика, яка оцінює рівень безпеки блокчейну або токена на основі різних факторів і складається з джерел, перелічених нижче.</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>
|
||||
|
|
@ -521,7 +524,7 @@
|
|||
<string name="onboarding_navbar_title_creating_backup">Резервна копія</string>
|
||||
<string name="onboarding_seed_button_read_more">Дізнатися більше про seed-фразу</string>
|
||||
<plurals name="onboarding_seed_generate_message_words_count">
|
||||
<item quantity="one">Запишіть це %d слово у порядку, вказаному нижче, та збережіть його у надійному місці.</item>
|
||||
<item quantity="one"></item>
|
||||
<item quantity="few">Запишіть ці %d слова у порядку, вказаному нижче, та збережіть їх у надійному місці.</item>
|
||||
<item quantity="many">Запишіть ці %d слів у порядку, вказаному нижче, та збережіть їх у надійному місці.</item>
|
||||
<item quantity="other">Запишіть ці %d слів у порядку, вказаному нижче, та збережіть їх у надійному місці.</item>
|
||||
|
|
@ -578,12 +581,18 @@
|
|||
<string name="onramp_country_search">Пошук за країною</string>
|
||||
<string name="onramp_country_unavailable">Недоступно</string>
|
||||
<string name="onramp_currency_search">Пошук по валюті</string>
|
||||
<string name="onramp_max_amount_restriction">Сума покупки не може бути більше ніж %s</string>
|
||||
<string name="onramp_min_amount_restriction">Сума покупки повинна бути не менше %s</string>
|
||||
<string name="onramp_no_available_providers">Для данної валюти немає доступних провайдерів</string>
|
||||
<string name="onramp_pay_with">Оплата з</string>
|
||||
<string name="onramp_redirecting_to_provider_subtitle">Ви зможете завершити транзакцію у стороннього постачальника, %s</string>
|
||||
<string name="onramp_redirecting_to_provider_title">Перенаправлення на %s...</string>
|
||||
<string name="onramp_residency_bottomsheet_country_not_supported">Наші сервіси недоступні в цій країні</string>
|
||||
<string name="onramp_residency_bottomsheet_country_subtitle">Змінити або підтвердити</string>
|
||||
<string name="onramp_residency_bottomsheet_title">Ваше місце проживання визначено як</string>
|
||||
<string name="onramp_settings_residence_description">Будь ласка, виберіть правильну країну, щоб забезпечити точні способи оплати та послуги.</string>
|
||||
<string name="onramp_settings_title">Параметри</string>
|
||||
<string name="onramp_transaction_status_footer_text">Ви можете перевірити статус транзакції на сторінці токена</string>
|
||||
<string name="onramp_via">Через</string>
|
||||
<string name="organize_tokens_group">Групами</string>
|
||||
<string name="organize_tokens_sort_by_balance">За балансом</string>
|
||||
|
|
@ -820,6 +829,7 @@
|
|||
<string name="staking_unbonding">Розблокування</string>
|
||||
<string name="staking_unlocked_locked">Розблокувати</string>
|
||||
<string name="staking_unlocking">Розблокування</string>
|
||||
<string name="staking_unstake_amount_requirement_error">Сума для виведення зі стейкінгу повинна бути не менше %s</string>
|
||||
<string name="staking_unstake_amount_validation_error">Сума перевищує баланс стейкінгу</string>
|
||||
<string name="staking_unstaked">Вивід зі стейкінгу</string>
|
||||
<string name="staking_unstaking">Зняти зі стейкінгу</string>
|
||||
|
|
@ -849,7 +859,7 @@
|
|||
<string name="swapping_alert_cex_description_with_slippage">У суму входить:\n- комісія провайдера\n- мережева комісія за відправку %1$s з біржі назад на адресу користувача. \n\nПроскакування провайдера становить до %2$s</string>
|
||||
<string name="swapping_alert_dex_description">Сума включає комісію постачальника послуг.</string>
|
||||
<string name="swapping_alert_dex_description_with_slippage">Сума включає комісію провайдера послуг. \n\nПроскакування провайдера до %s</string>
|
||||
<string name="swapping_alert_title">Комісії</string>
|
||||
<string name="swapping_alert_title">Інформація</string>
|
||||
<string name="swapping_approve_information_text">Всі децентралізовані біржі вимагають схвалення, щоб запобігти доступу смарт-контрактів до вашого гаманця без вашого дозволу. За задумом смарт-контракти не можуть отримати доступ до ваших токенів без вашого схвалення. \"Розблоковуючи\" свої токени, ви дозволяєте смарт-контракту 1inch витрачати ваші активи. Майнери мережі отримують плату за газ (сплачену вами), щоб зафіксувати цю дію в блокчейні. Ви можете обміняти свій токен після того, як дасте дозвіл.</string>
|
||||
<string name="swapping_approve_information_title">Підтвердити</string>
|
||||
<string name="swapping_fee_estimation_error_text">Помилка при розрахунку комісії. Будь ласка, надішліть відгук до служби підтримки.</string>
|
||||
|
|
@ -899,6 +909,7 @@
|
|||
<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="transfer_min_amount_error">Мінімум %s</string>
|
||||
<string name="transfer_notification_invalid_minimum_transaction_amount_text">Мінімальна сума транзакції становить %1$s.</string>
|
||||
<string name="try_to_load_data_again_button_title">Спробуйте знову</string>
|
||||
<string name="twin_error_same_card">Ви відсканували одну й ту саму картку. Для створення twin-гаманця вам потрібно відсканувати картку з номером %d</string>
|
||||
|
|
|
|||
|
|
@ -180,6 +180,7 @@
|
|||
<string name="common_terms_of_use">Terms of Use</string>
|
||||
<string name="common_today">Today</string>
|
||||
<string name="common_transaction_failed">Transaction failed</string>
|
||||
<string name="common_transaction_status">Transaction status</string>
|
||||
<string name="common_transactions">Transactions</string>
|
||||
<string name="common_transfer">Transfer</string>
|
||||
<string name="common_understand">I understand</string>
|
||||
|
|
@ -187,6 +188,7 @@
|
|||
<string name="common_unreachable">Unreachable</string>
|
||||
<string name="common_unstake">Unstake</string>
|
||||
<string name="common_week">week</string>
|
||||
<string name="common_with">with</string>
|
||||
<string name="common_yes">Yes</string>
|
||||
<string name="contract_address_copied_message">Contract address copied!</string>
|
||||
<string name="currency_subtitle_expanded">Available networks</string>
|
||||
|
|
@ -575,6 +577,7 @@
|
|||
<string name="onramp_settings_residence">Residence</string>
|
||||
<string name="onramp_settings_residence_description">Please select the correct country to ensure accurate payment options and services.</string>
|
||||
<string name="onramp_settings_title">Settings</string>
|
||||
<string name="onramp_transaction_status_footer_text">You can check the transaction status from the token page</string>
|
||||
<string name="onramp_via">Via</string>
|
||||
<string name="organize_tokens_group">Group</string>
|
||||
<string name="organize_tokens_sort_by_balance">By balance</string>
|
||||
|
|
@ -853,14 +856,14 @@
|
|||
<string name="toast_balances_shown">Balances shown</string>
|
||||
<string name="toast_undo">Undo</string>
|
||||
<string name="token_button_unavailability_generic_description">This operation is currently unavailable. Please try again later.</string>
|
||||
<string name="token_button_unavailability_reason_buy_unavailable">Buying %s is not available at the moment. Please check our updates.</string>
|
||||
<string name="token_button_unavailability_reason_buy_unavailable">Buying %s is not supported by current providers, but we are working to add more options.</string>
|
||||
<string name="token_button_unavailability_reason_empty_balance_sell">You do not have funds to sell. Top up your account to be able to sell funds from it.</string>
|
||||
<string name="token_button_unavailability_reason_empty_balance_send">You do not have funds to send. Top up your account to be able to send funds from it.</string>
|
||||
<string name="token_button_unavailability_reason_not_exchangeable">Swapping %s is not available at the moment. Please check our updates.</string>
|
||||
<string name="token_button_unavailability_reason_not_exchangeable">Swapping %s is not supported by current providers, but we are working to add more options.</string>
|
||||
<string name="token_button_unavailability_reason_pending_transaction_sell">Selling funds will be available once the pending transaction(s) in network %s is complete</string>
|
||||
<string name="token_button_unavailability_reason_pending_transaction_send">Sending funds will be available once the pending transaction(s) in network %s is complete</string>
|
||||
<string name="token_button_unavailability_reason_sell_unavailable">Selling %s is not available at the moment. Please check our updates.</string>
|
||||
<string name="token_button_unavailability_reason_staking_unavailable">Staking %s is not available at the moment. Please check our updates.</string>
|
||||
<string name="token_button_unavailability_reason_sell_unavailable">Selling %s is not supported by current providers, but we are working to add more options.</string>
|
||||
<string name="token_button_unavailability_reason_staking_unavailable">Staking %s is not supported by current providers, but we are working to add more options.</string>
|
||||
<string name="token_details_generate_xpub">Generate XPUB</string>
|
||||
<string name="token_details_hide_alert_hide">Hide</string>
|
||||
<string name="token_details_hide_alert_message">You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page.</string>
|
||||
|
|
@ -953,6 +956,9 @@
|
|||
<string name="wallet_network_group_title">%s network</string>
|
||||
<string name="wallet_notification_address_copied">Address was copied to clipboard</string>
|
||||
<string name="wallet_notification_no_internet">No internet connection</string>
|
||||
<string name="wallet_promo_banner_button_title">Get now with 10%% off</string>
|
||||
<string name="wallet_promo_banner_description">Access 13,000+ cryptocurrencies. Buy, sell, swap, and stake with a single tap.\nLink up to three cards for a backup.</string>
|
||||
<string name="wallet_promo_banner_title">Discover Tangem Wallet</string>
|
||||
<string name="wallet_settings_title">Wallet settings</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
<string name="warning_access_denied_message">Use %s or scan a card/ring to unlock access to your wallet</string>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ data class TangemDimens internal constructor(
|
|||
val radius26: Dp = 26.dp,
|
||||
val radius28: Dp = 28.dp,
|
||||
val radius36: Dp = 36.dp,
|
||||
val radius40: Dp = 40.dp,
|
||||
// endregion Radius
|
||||
// region Size
|
||||
val size0: Dp = 0.dp,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package com.tangem.data.markets.converters
|
||||
|
||||
import android.net.Uri
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.blockchainsdk.utils.isSupportedInApp
|
||||
import com.tangem.datasource.api.markets.models.response.TokenMarketInfoResponse
|
||||
import com.tangem.domain.markets.BuildConfig
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.domain.markets.TokenQuotes
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
|
@ -11,6 +13,9 @@ import java.math.BigDecimal
|
|||
|
||||
internal object TokenMarketInfoConverter : Converter<TokenMarketInfoResponse, TokenMarketInfo> {
|
||||
|
||||
private const val PROD_IMAGE_HOST = "https://s3.eu-central-1.amazonaws.com/tangem.api/security_provider/"
|
||||
private const val DEV_IMAGE_HOST = "https://s3.eu-central-1.amazonaws.com/tangem.api.dev/security_provider/"
|
||||
|
||||
override fun convert(value: TokenMarketInfoResponse): TokenMarketInfo {
|
||||
return with(value) {
|
||||
TokenMarketInfo(
|
||||
|
|
@ -23,6 +28,7 @@ internal object TokenMarketInfoConverter : Converter<TokenMarketInfoResponse, To
|
|||
fullDescription = fullDescription,
|
||||
insights = insights?.convert(),
|
||||
metrics = metrics?.convert(),
|
||||
securityData = securityData?.convert(),
|
||||
links = links?.convert(),
|
||||
pricePerformance = pricePerformance?.convert(),
|
||||
exchangesAmount = exchangesAmount,
|
||||
|
|
@ -105,6 +111,31 @@ internal object TokenMarketInfoConverter : Converter<TokenMarketInfoResponse, To
|
|||
)
|
||||
}
|
||||
|
||||
private fun TokenMarketInfoResponse.SecurityData.convert(): TokenMarketInfo.SecurityData {
|
||||
return TokenMarketInfo.SecurityData(
|
||||
totalSecurityScore = totalSecurityScore,
|
||||
providerData = providerData.map { it.convert() },
|
||||
)
|
||||
}
|
||||
|
||||
private fun TokenMarketInfoResponse.ProviderData.convert(): TokenMarketInfo.ProviderData {
|
||||
return TokenMarketInfo.ProviderData(
|
||||
providerId = providerId,
|
||||
providerName = providerName,
|
||||
urlData = link?.convertToUrlData(),
|
||||
securityScore = securityScore,
|
||||
lastAuditDate = lastAuditDate,
|
||||
iconUrl = "${getImageHost()}large/$providerId.png",
|
||||
)
|
||||
}
|
||||
|
||||
private fun String.convertToUrlData(): TokenMarketInfo.ProviderUrlData {
|
||||
return TokenMarketInfo.ProviderUrlData(
|
||||
fullUrl = this,
|
||||
rootHost = this.extractMainDomainOrNull(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun TokenMarketInfoResponse.Links.convert(): TokenMarketInfo.Links {
|
||||
return TokenMarketInfo.Links(
|
||||
officialLinks = officialLinks?.convert(),
|
||||
|
|
@ -139,4 +170,27 @@ internal object TokenMarketInfoConverter : Converter<TokenMarketInfoResponse, To
|
|||
high = high,
|
||||
)
|
||||
}
|
||||
|
||||
private fun String.extractMainDomainOrNull(): String? {
|
||||
return runCatching {
|
||||
val uri = Uri.parse(this)
|
||||
val host = uri.host ?: return null
|
||||
|
||||
val parts = host.split(".")
|
||||
|
||||
if (parts.size >= 2) {
|
||||
parts.takeLast(2).joinToString(".")
|
||||
} else {
|
||||
host
|
||||
}
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
private fun getImageHost(): String {
|
||||
return if (BuildConfig.TESTER_MENU_ENABLED) {
|
||||
DEV_IMAGE_HOST
|
||||
} else {
|
||||
PROD_IMAGE_HOST
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.domain.markets
|
||||
|
||||
import org.joda.time.DateTime
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class TokenMarketInfo(
|
||||
|
|
@ -12,6 +13,7 @@ data class TokenMarketInfo(
|
|||
val fullDescription: String?,
|
||||
val insights: Insights?,
|
||||
val metrics: Metrics?,
|
||||
val securityData: SecurityData?,
|
||||
val links: Links?,
|
||||
val pricePerformance: PricePerformance?,
|
||||
val exchangesAmount: Int?,
|
||||
|
|
@ -51,6 +53,25 @@ data class TokenMarketInfo(
|
|||
val fullyDilutedValuation: BigDecimal?,
|
||||
)
|
||||
|
||||
data class SecurityData(
|
||||
val totalSecurityScore: Float,
|
||||
val providerData: List<ProviderData>,
|
||||
)
|
||||
|
||||
data class ProviderData(
|
||||
val providerId: String,
|
||||
val providerName: String,
|
||||
val urlData: ProviderUrlData?,
|
||||
val iconUrl: String,
|
||||
val securityScore: Float,
|
||||
val lastAuditDate: DateTime?,
|
||||
)
|
||||
|
||||
data class ProviderUrlData(
|
||||
val fullUrl: String,
|
||||
val rootHost: String?,
|
||||
)
|
||||
|
||||
data class Links(
|
||||
val officialLinks: List<Link>?,
|
||||
val social: List<Link>?,
|
||||
|
|
|
|||
|
|
@ -88,6 +88,9 @@ internal class MarketsTokenDetailsModel @Inject constructor(
|
|||
// === Analytics ===
|
||||
analyticsEventHandler.send(analyticsEventBuilder.linkClicked(linkTitle = link.title))
|
||||
},
|
||||
onSecurityScoreProviderLinkClick = {
|
||||
urlOpener.openUrl(it)
|
||||
},
|
||||
// === Analytics ===
|
||||
onPricePerformanceIntervalChanged = {
|
||||
analyticsEventHandler.send(
|
||||
|
|
|
|||
|
|
@ -1,35 +1,57 @@
|
|||
package com.tangem.features.markets.details.impl.model.converters
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.ui.extensions.pluralReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.features.markets.details.impl.ui.state.InfoBottomSheetContent
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.features.markets.details.impl.model.formatter.MarketsDateTimeFormatters
|
||||
import com.tangem.features.markets.details.impl.ui.state.SecurityScoreBottomSheetContent
|
||||
import com.tangem.features.markets.details.impl.ui.state.SecurityScoreUM
|
||||
import com.tangem.features.markets.impl.R
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
// TODO implement when backend is ready
|
||||
@Stable
|
||||
internal class SecurityScoreConverter(
|
||||
private val onInfoClick: (InfoBottomSheetContent) -> Unit,
|
||||
) : Converter<Unit, SecurityScoreUM> {
|
||||
private val onInfoClick: (SecurityScoreBottomSheetContent) -> Unit,
|
||||
private val onSecurityScoreProviderLinkClick: (String) -> Unit,
|
||||
) : Converter<TokenMarketInfo.SecurityData, SecurityScoreUM> {
|
||||
|
||||
override fun convert(value: Unit): SecurityScoreUM {
|
||||
return with(value) {
|
||||
SecurityScoreUM(
|
||||
score = 4.7f,
|
||||
description = "Based on 3 ratings",
|
||||
override fun convert(value: TokenMarketInfo.SecurityData): SecurityScoreUM {
|
||||
val ratingsCount = value.providerData.size
|
||||
return SecurityScoreUM(
|
||||
score = value.totalSecurityScore,
|
||||
description = pluralReference(
|
||||
id = R.plurals.markets_token_details_based_on_ratings,
|
||||
count = ratingsCount,
|
||||
formatArgs = wrappedList(ratingsCount),
|
||||
),
|
||||
onInfoClick = {
|
||||
onInfoClick(
|
||||
InfoBottomSheetContent(
|
||||
SecurityScoreBottomSheetContent(
|
||||
title = resourceReference(R.string.markets_token_details_security_score),
|
||||
body = stringReference("markets_token_details_security_score_description"),
|
||||
// FIXME
|
||||
// resourceReference(R.string.markets_token_details_security_score_description)
|
||||
description = resourceReference(R.string.markets_token_details_security_score_description),
|
||||
providers = value.providerData.map {
|
||||
SecurityScoreBottomSheetContent.SecurityScoreProviderUM(
|
||||
name = it.providerName,
|
||||
lastAuditDate = it.lastAuditDate?.let { date ->
|
||||
MarketsDateTimeFormatters.formatAsDate(date.millis)
|
||||
},
|
||||
score = it.securityScore,
|
||||
urlData = it.urlData?.let {
|
||||
urlData ->
|
||||
SecurityScoreBottomSheetContent.SecurityScoreProviderUrlData(
|
||||
fullUrl = urlData.fullUrl,
|
||||
rootHost = urlData.rootHost,
|
||||
)
|
||||
},
|
||||
iconUrl = it.iconUrl,
|
||||
)
|
||||
},
|
||||
onProviderLinkClick = onSecurityScoreProviderLinkClick,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package com.tangem.features.markets.details.impl.model.converters
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.markets.PriceChangeInterval
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.features.markets.details.impl.ui.state.InfoBottomSheetContent
|
||||
import com.tangem.features.markets.details.impl.ui.state.LinksUM
|
||||
import com.tangem.features.markets.details.impl.ui.state.ListedOnUM
|
||||
import com.tangem.features.markets.details.impl.ui.state.MarketsTokenDetailsUM
|
||||
|
|
@ -12,11 +12,13 @@ import com.tangem.utils.Provider
|
|||
import com.tangem.utils.converter.Converter
|
||||
|
||||
@Stable
|
||||
@Suppress("LongParameterList")
|
||||
internal class TokenMarketInfoConverter(
|
||||
private val appCurrency: Provider<AppCurrency>,
|
||||
private val onInfoClick: (InfoBottomSheetContent) -> Unit,
|
||||
private val onInfoClick: (TangemBottomSheetConfigContent) -> Unit,
|
||||
private val onListedOnClick: (Int) -> Unit,
|
||||
onLinkClick: (LinksUM.Link) -> Unit,
|
||||
onSecurityScoreProviderLinkClick: (String) -> Unit,
|
||||
onPricePerformanceIntervalChanged: (PriceChangeInterval) -> Unit,
|
||||
onInsightsIntervalChanged: (PriceChangeInterval) -> Unit,
|
||||
) : Converter<TokenMarketInfo, MarketsTokenDetailsUM.InformationBlocks> {
|
||||
|
|
@ -27,9 +29,10 @@ internal class TokenMarketInfoConverter(
|
|||
onIntervalChanged = onInsightsIntervalChanged,
|
||||
)
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
// TODO second markets iteration
|
||||
private val securityScoreConverter = SecurityScoreConverter(onInfoClick = onInfoClick)
|
||||
private val securityScoreConverter = SecurityScoreConverter(
|
||||
onInfoClick = onInfoClick,
|
||||
onSecurityScoreProviderLinkClick = onSecurityScoreProviderLinkClick,
|
||||
)
|
||||
private val pricePerformanceConverter = PricePerformanceConverter(
|
||||
appCurrency = appCurrency,
|
||||
onIntervalChanged = onPricePerformanceIntervalChanged,
|
||||
|
|
@ -46,7 +49,7 @@ internal class TokenMarketInfoConverter(
|
|||
val exchangesAmount = value.exchangesAmount
|
||||
return MarketsTokenDetailsUM.InformationBlocks(
|
||||
insights = value.insights?.let { insightsConverter.convert(it) },
|
||||
securityScore = null,
|
||||
securityScore = value.securityData?.let { securityScoreConverter.convert(it) },
|
||||
metrics = value.metrics?.let { metricsConverter.convert(it) },
|
||||
pricePerformance = value.pricePerformance?.let {
|
||||
pricePerformanceConverter.convert(
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ internal object MarketsDateTimeFormatters {
|
|||
R.string.common_range_with_space,
|
||||
wrappedList(
|
||||
stringReference(
|
||||
startTimestamp.formatAsDateTime(MarketsDateTimeFormatters.dateTimeMMMFormatter),
|
||||
startTimestamp.formatAsDateTime(dateTimeMMMFormatter),
|
||||
),
|
||||
resourceReference(R.string.common_now),
|
||||
),
|
||||
|
|
@ -68,7 +68,7 @@ internal object MarketsDateTimeFormatters {
|
|||
R.string.common_range_with_space,
|
||||
wrappedList(
|
||||
stringReference(
|
||||
startTimestamp.formatAsDateTime(MarketsDateTimeFormatters.dateFormatter),
|
||||
startTimestamp.formatAsDateTime(dateFormatter),
|
||||
),
|
||||
resourceReference(R.string.common_now),
|
||||
),
|
||||
|
|
@ -89,7 +89,7 @@ internal object MarketsDateTimeFormatters {
|
|||
R.string.common_range_with_space,
|
||||
wrappedList(
|
||||
stringReference(
|
||||
markerTimestamp.toLong().formatAsDateTime(MarketsDateTimeFormatters.dateTimeMMMFormatter),
|
||||
markerTimestamp.toLong().formatAsDateTime(dateTimeMMMFormatter),
|
||||
),
|
||||
resourceReference(R.string.common_now),
|
||||
),
|
||||
|
|
@ -103,7 +103,7 @@ internal object MarketsDateTimeFormatters {
|
|||
R.string.common_range_with_space,
|
||||
wrappedList(
|
||||
stringReference(
|
||||
markerTimestamp.toLong().formatAsDateTime(MarketsDateTimeFormatters.dateFormatter),
|
||||
markerTimestamp.toLong().formatAsDateTime(dateFormatter),
|
||||
),
|
||||
resourceReference(R.string.common_now),
|
||||
),
|
||||
|
|
@ -128,10 +128,14 @@ internal object MarketsDateTimeFormatters {
|
|||
fun getDefaultDateTimeString(interval: PriceChangeInterval, currentTimestamp: Long): TextReference {
|
||||
return formatDateByInterval(
|
||||
interval = interval,
|
||||
startTimestamp = MarketsDateTimeFormatters.getStartTimestampByInterval(
|
||||
startTimestamp = getStartTimestampByInterval(
|
||||
interval = interval,
|
||||
currentTimestamp = currentTimestamp,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun formatAsDate(timestamp: Long): String {
|
||||
return timestamp.formatAsDateTime(dateFormatter)
|
||||
}
|
||||
}
|
||||
|
|
@ -37,6 +37,7 @@ import com.tangem.core.ui.extensions.stringReference
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.markets.PriceChangeInterval
|
||||
import com.tangem.features.markets.details.impl.ui.components.*
|
||||
import com.tangem.features.markets.details.impl.ui.components.ExchangesBottomSheet
|
||||
import com.tangem.features.markets.details.impl.ui.components.InfoBottomSheet
|
||||
import com.tangem.features.markets.details.impl.ui.components.MarketTokenDetailsChart
|
||||
|
|
@ -44,6 +45,7 @@ import com.tangem.features.markets.details.impl.ui.components.tokenMarketDetails
|
|||
import com.tangem.features.markets.details.impl.ui.state.ExchangesBottomSheetContent
|
||||
import com.tangem.features.markets.details.impl.ui.state.InfoBottomSheetContent
|
||||
import com.tangem.features.markets.details.impl.ui.state.MarketsTokenDetailsUM
|
||||
import com.tangem.features.markets.details.impl.ui.state.SecurityScoreBottomSheetContent
|
||||
import com.tangem.features.markets.impl.R
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
|
|
@ -72,6 +74,7 @@ internal fun MarketsTokenDetailsContent(
|
|||
|
||||
when (state.bottomSheetConfig.content) {
|
||||
is InfoBottomSheetContent -> InfoBottomSheet(config = state.bottomSheetConfig)
|
||||
is SecurityScoreBottomSheetContent -> SecurityScoreBottomSheet(config = state.bottomSheetConfig)
|
||||
is ExchangesBottomSheetContent -> ExchangesBottomSheet(config = state.bottomSheetConfig)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
package com.tangem.features.markets.details.impl.ui.components
|
||||
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawWithCache
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.BlendMode
|
||||
import androidx.compose.ui.graphics.CompositingStrategy
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.markets.impl.R
|
||||
import kotlin.math.round
|
||||
|
||||
private const val STARS_COUNT = 5
|
||||
|
||||
@Composable
|
||||
internal fun ScoreStarsBlock(
|
||||
score: Float,
|
||||
horizontalSpacing: Dp,
|
||||
scoreTextStyle: TextStyle,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val rounded = score.roundTo1decimal()
|
||||
val percentage = rounded / STARS_COUNT
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(horizontalSpacing),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = rounded.toString(),
|
||||
style = scoreTextStyle,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
Stars(fraction = percentage)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
@Composable
|
||||
private fun Stars(@FloatRange(0.0, 1.0) fraction: Float = 0f) {
|
||||
val grayColor = TangemTheme.colors.icon.inactive
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
repeat(times = 5) { i ->
|
||||
Box(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size16),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.requiredSize(16.dp)
|
||||
.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)
|
||||
.drawWithCache {
|
||||
onDrawWithContent {
|
||||
val starFraction = ((fraction - i * 0.2) / 0.2).coerceIn(0.0, 1.0)
|
||||
val starFractionFloat = starFraction
|
||||
.toFloat()
|
||||
.roundTo1decimal()
|
||||
|
||||
drawContent()
|
||||
drawRect(
|
||||
color = grayColor,
|
||||
topLeft = Offset(x = size.width * starFractionFloat, y = 0f),
|
||||
size = Size(size.width * (1 - starFractionFloat), size.height),
|
||||
blendMode = BlendMode.SrcIn,
|
||||
)
|
||||
}
|
||||
},
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_star_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun Float.roundTo1decimal(): Float {
|
||||
return round(this * 10) / 10
|
||||
}
|
||||
|
|
@ -1,42 +1,28 @@
|
|||
package com.tangem.features.markets.details.impl.ui.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawWithCache
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.BlendMode
|
||||
import androidx.compose.ui.graphics.CompositingStrategy
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.components.block.information.InformationBlock
|
||||
import com.tangem.core.ui.components.text.TooltipText
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.PreviewShimmerContainer
|
||||
import com.tangem.features.markets.details.impl.ui.state.SecurityScoreUM
|
||||
import com.tangem.features.markets.impl.R
|
||||
import kotlin.math.round
|
||||
|
||||
private const val STARS_COUNT = 5
|
||||
|
||||
@Composable
|
||||
internal fun SecurityScoreBlock(state: SecurityScoreUM, modifier: Modifier = Modifier) {
|
||||
val rounded = state.score.roundTo1decimal()
|
||||
val percentage = rounded / STARS_COUNT
|
||||
InformationBlock(
|
||||
modifier = modifier,
|
||||
title = {
|
||||
|
|
@ -51,7 +37,7 @@ internal fun SecurityScoreBlock(state: SecurityScoreUM, modifier: Modifier = Mod
|
|||
)
|
||||
|
||||
Text(
|
||||
text = state.description,
|
||||
text = state.description.resolveReference(),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
maxLines = 1,
|
||||
|
|
@ -60,72 +46,18 @@ internal fun SecurityScoreBlock(state: SecurityScoreUM, modifier: Modifier = Mod
|
|||
}
|
||||
},
|
||||
action = {
|
||||
Row(
|
||||
ScoreStarsBlock(
|
||||
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing6),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = rounded.toString(),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
score = state.score,
|
||||
scoreTextStyle = TangemTheme.typography.body1,
|
||||
horizontalSpacing = TangemTheme.dimens.spacing8,
|
||||
)
|
||||
Stars(fraction = percentage)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
@Composable
|
||||
private fun Stars(@FloatRange(0.0, 1.0) fraction: Float = 0f) {
|
||||
val grayColor = TangemTheme.colors.icon.inactive
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
repeat(times = 5) { i ->
|
||||
Box(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size16),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.requiredSize(13.dp)
|
||||
.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)
|
||||
.drawWithCache {
|
||||
onDrawWithContent {
|
||||
val starFraction = ((fraction - i * 0.2) / 0.2).coerceIn(0.0, 1.0)
|
||||
val starFractionFloat = starFraction
|
||||
.toFloat()
|
||||
.roundTo1decimal()
|
||||
|
||||
drawContent()
|
||||
drawRect(
|
||||
color = grayColor,
|
||||
topLeft = Offset(x = size.width * starFractionFloat, y = 0f),
|
||||
size = Size(size.width * (1 - starFractionFloat), size.height),
|
||||
blendMode = BlendMode.SrcIn,
|
||||
)
|
||||
}
|
||||
},
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_star_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun Float.roundTo1decimal(): Float {
|
||||
return round(this * 10) / 10
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun SecurityScorePlaceHolder(modifier: Modifier = Modifier) {
|
||||
private fun SecurityScorePlaceHolder(modifier: Modifier = Modifier) {
|
||||
InformationBlock(
|
||||
modifier = modifier,
|
||||
title = {
|
||||
|
|
@ -177,7 +109,7 @@ private fun ContentPreview() {
|
|||
SecurityScoreBlock(
|
||||
state = SecurityScoreUM(
|
||||
score = 3.5f,
|
||||
description = "Based on 3 ratings",
|
||||
description = stringReference("Based on 3 ratings"),
|
||||
onInfoClick = {},
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,191 @@
|
|||
package com.tangem.features.markets.details.impl.ui.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.ripple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetTitle
|
||||
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
|
||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.markets.details.impl.ui.preview.SecurityScorePreviewData
|
||||
import com.tangem.features.markets.impl.R
|
||||
import com.tangem.features.markets.details.impl.ui.state.SecurityScoreBottomSheetContent
|
||||
|
||||
@Composable
|
||||
internal fun SecurityScoreBottomSheet(config: TangemBottomSheetConfig) {
|
||||
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
|
||||
|
||||
TangemBottomSheet<SecurityScoreBottomSheetContent>(
|
||||
config = config,
|
||||
containerColor = TangemTheme.colors.background.secondary,
|
||||
addBottomInsets = false,
|
||||
title = { TangemBottomSheetTitle(title = it.title) },
|
||||
content = { content ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
Text(
|
||||
text = content.description.resolveReference(),
|
||||
style = TangemTheme.typography.body2.copy(
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
),
|
||||
)
|
||||
|
||||
SpacerH12()
|
||||
content.providers.fastForEachIndexed { index, provider ->
|
||||
DividerContainer(
|
||||
modifier = Modifier
|
||||
.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = content.providers.lastIndex,
|
||||
addDefaultPadding = false,
|
||||
)
|
||||
.background(TangemTheme.colors.background.action),
|
||||
showDivider = index != content.providers.lastIndex,
|
||||
) {
|
||||
SecurityScoreProviderRow(
|
||||
providerUM = provider,
|
||||
onLinkClick = content.onProviderLinkClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SpacerH16()
|
||||
SpacerH(bottomBarHeight)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SecurityScoreProviderRow(
|
||||
providerUM: SecurityScoreBottomSheetContent.SecurityScoreProviderUM,
|
||||
onLinkClick: (String) -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = TangemTheme.dimens.spacing12)
|
||||
.heightIn(min = TangemTheme.dimens.size68),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
SubcomposeAsyncImage(
|
||||
modifier = Modifier
|
||||
.size(size = TangemTheme.dimens.size40)
|
||||
.clip(TangemTheme.shapes.roundedCorners8),
|
||||
model = ImageRequest.Builder(context = LocalContext.current)
|
||||
.data(providerUM.iconUrl)
|
||||
.crossfade(enable = true)
|
||||
.allowHardware(false)
|
||||
.build(),
|
||||
loading = { RectangleShimmer(radius = TangemTheme.dimens.radius8) },
|
||||
error = { RectangleShimmer(radius = TangemTheme.dimens.radius8) },
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.padding(start = TangemTheme.dimens.spacing12),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
|
||||
) {
|
||||
Text(
|
||||
text = providerUM.name,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
providerUM.lastAuditDate?.let {
|
||||
Text(
|
||||
text = providerUM.lastAuditDate,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SpacerWMax()
|
||||
|
||||
Column(
|
||||
horizontalAlignment = Alignment.End,
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
|
||||
modifier = Modifier.clickable(
|
||||
enabled = providerUM.urlData != null,
|
||||
indication = ripple(bounded = false),
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
onClick = { providerUM.urlData?.let { onLinkClick(it.fullUrl) } },
|
||||
),
|
||||
) {
|
||||
ScoreStarsBlock(
|
||||
score = providerUM.score,
|
||||
scoreTextStyle = TangemTheme.typography.body2,
|
||||
horizontalSpacing = TangemTheme.dimens.spacing3,
|
||||
)
|
||||
|
||||
UrlBlock(providerUM)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UrlBlock(providerUM: SecurityScoreBottomSheetContent.SecurityScoreProviderUM) {
|
||||
val urlData = providerUM.urlData
|
||||
val rootHost = urlData?.rootHost
|
||||
if (urlData != null && rootHost != null) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
|
||||
) {
|
||||
Text(
|
||||
text = urlData.rootHost,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.size16),
|
||||
painter = painterResource(id = R.drawable.ic_arrow_top_right_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun SecurityScoreBottomSheetPreview() {
|
||||
TangemThemePreview {
|
||||
SecurityScoreBottomSheet(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShow = true,
|
||||
onDismissRequest = {},
|
||||
content = SecurityScorePreviewData.bottomSheetContent,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package com.tangem.features.markets.details.impl.ui.preview
|
||||
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.features.markets.details.impl.ui.state.SecurityScoreBottomSheetContent
|
||||
|
||||
internal object SecurityScorePreviewData {
|
||||
|
||||
val bottomSheetContent = SecurityScoreBottomSheetContent(
|
||||
title = stringReference("Security score"),
|
||||
description = stringReference(
|
||||
"Security score of a token is a metric that assesses the " +
|
||||
"security level of a blockchain or token based on various factors and is compiled from " +
|
||||
"the sources listed below.",
|
||||
),
|
||||
providers = listOf(
|
||||
SecurityScoreBottomSheetContent.SecurityScoreProviderUM(
|
||||
name = "Moralis",
|
||||
lastAuditDate = "21.10.2024",
|
||||
score = 4.9F,
|
||||
urlData = SecurityScoreBottomSheetContent.SecurityScoreProviderUrlData(
|
||||
fullUrl = "https://moralis.com/",
|
||||
rootHost = "moralis.com",
|
||||
),
|
||||
iconUrl = "",
|
||||
),
|
||||
SecurityScoreBottomSheetContent.SecurityScoreProviderUM(
|
||||
name = "Certik",
|
||||
lastAuditDate = "10.07.2024",
|
||||
score = 4.6F,
|
||||
urlData = SecurityScoreBottomSheetContent.SecurityScoreProviderUrlData(
|
||||
fullUrl = "https://certik.com/",
|
||||
rootHost = "certik.com",
|
||||
),
|
||||
iconUrl = "",
|
||||
),
|
||||
SecurityScoreBottomSheetContent.SecurityScoreProviderUM(
|
||||
name = "Cyberscope",
|
||||
lastAuditDate = "25.06.2023",
|
||||
score = 4.5F,
|
||||
urlData = SecurityScoreBottomSheetContent.SecurityScoreProviderUrlData(
|
||||
fullUrl = "https://cyberscope.com/",
|
||||
rootHost = "cyberscope.com",
|
||||
),
|
||||
iconUrl = "",
|
||||
),
|
||||
SecurityScoreBottomSheetContent.SecurityScoreProviderUM(
|
||||
name = "TokenInsight",
|
||||
lastAuditDate = "17.01.2022",
|
||||
score = 4.0F,
|
||||
urlData = SecurityScoreBottomSheetContent.SecurityScoreProviderUrlData(
|
||||
fullUrl = "https://tokeninsight.com/",
|
||||
rootHost = "tokeninsight.com",
|
||||
),
|
||||
iconUrl = "",
|
||||
),
|
||||
|
||||
),
|
||||
onProviderLinkClick = {},
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.tangem.features.markets.details.impl.ui.state
|
||||
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
internal data class SecurityScoreBottomSheetContent(
|
||||
val title: TextReference,
|
||||
val description: TextReference,
|
||||
val providers: List<SecurityScoreProviderUM>,
|
||||
val onProviderLinkClick: (String) -> Unit,
|
||||
) : TangemBottomSheetConfigContent {
|
||||
|
||||
data class SecurityScoreProviderUM(
|
||||
val name: String,
|
||||
val lastAuditDate: String?,
|
||||
val score: Float,
|
||||
val urlData: SecurityScoreProviderUrlData?,
|
||||
val iconUrl: String?,
|
||||
)
|
||||
|
||||
data class SecurityScoreProviderUrlData(
|
||||
val fullUrl: String,
|
||||
val rootHost: String?,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
package com.tangem.features.markets.details.impl.ui.state
|
||||
|
||||
import androidx.annotation.FloatRange
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
internal data class SecurityScoreUM(
|
||||
@FloatRange(from = 0.0, to = 5.0) val score: Float,
|
||||
val description: String,
|
||||
val description: TextReference,
|
||||
val onInfoClick: () -> Unit,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue