Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-28 16:38:49 +03:00
commit 1c8b3ff14b
51 changed files with 514 additions and 267 deletions

@ -1 +1 @@
Subproject commit 7b792e100c14f64d3e44306c3a9b25a25d0cfc03
Subproject commit 16c0de5855d0a75e285a9c84e616dd020f7da4d1

View file

@ -112,13 +112,22 @@ object NotificationsFactory {
reserveAmount: BigDecimal?,
sendingAmount: BigDecimal,
cryptoCurrency: CryptoCurrency,
feeCryptoCurrency: CryptoCurrency?,
isAccountFunded: Boolean,
) {
if (!isAccountFunded && reserveAmount != null && reserveAmount > sendingAmount) {
val sendingCoinAmount = when (cryptoCurrency) {
is CryptoCurrency.Coin -> sendingAmount
is CryptoCurrency.Token -> BigDecimal.ZERO
}
if (feeCryptoCurrency == null && cryptoCurrency is CryptoCurrency.Token) {
// No need to show reserve amount warning if fee currency is unknown for token transfer
return
} else if (!isAccountFunded && reserveAmount != null && reserveAmount > sendingCoinAmount) {
add(
NotificationUM.Error.ReserveAmount(
reserveAmount.format {
crypto(cryptoCurrency)
crypto(feeCryptoCurrency ?: cryptoCurrency)
},
),
)

View file

@ -21,6 +21,7 @@ import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.currency.yieldSupplyKey
import com.tangem.domain.models.staking.YieldBalance
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.staking.utils.getTotalWithRewardsStakingBalance
import com.tangem.lib.crypto.BlockchainUtils
import com.tangem.utils.StringsSigns.DASH_SIGN
@ -41,7 +42,7 @@ import java.math.BigDecimal
class TokenItemStateConverter(
private val appCurrency: AppCurrency,
private val yieldModuleApyMap: Map<String, String> = emptyMap(),
private val stakingApyMap: Map<String, BigDecimal> = emptyMap(),
private val stakingApyMap: Map<String, List<Yield.Validator>> = emptyMap(),
private val iconStateProvider: (CryptoCurrencyStatus) -> CurrencyIconState = {
CryptoCurrencyToIconStateConverter().convert(it)
},
@ -156,7 +157,7 @@ class TokenItemStateConverter(
private fun createTitleState(
currencyStatus: CryptoCurrencyStatus,
yieldModuleApyMap: Map<String, String>,
stakingApyMap: Map<String, BigDecimal>,
stakingApyMap: Map<String, List<Yield.Validator>>,
): TokenItemState.TitleState {
return when (val value = currencyStatus.value) {
is CryptoCurrencyStatus.Loading,
@ -190,7 +191,7 @@ class TokenItemStateConverter(
private fun resolveEarnApy(
cryptoCurrencyStatus: CryptoCurrencyStatus,
yieldModuleApyMap: Map<String, String>,
stakingApyMap: Map<String, BigDecimal>,
stakingApyMap: Map<String, List<Yield.Validator>>,
): Pair<TextReference?, Boolean> {
val token = cryptoCurrencyStatus.currency as? CryptoCurrency.Token
if (token != null && yieldModuleApyMap.isNotEmpty()) {
@ -210,20 +211,41 @@ class TokenItemStateConverter(
}
if (stakingApyMap.isNotEmpty()) {
val stakingKey = cryptoCurrencyStatus.currency.stakingKey()
val stakingApy = stakingApyMap[stakingKey]?.format { percent(withPercentSign = false) }
if (stakingApy != null) {
val hasStakedBalance = cryptoCurrencyStatus.value.yieldBalance is YieldBalance.Data
val (stakingRate, hasStaked) = findStakingRate(
currencyStatus = cryptoCurrencyStatus,
stakingApyMap = stakingApyMap,
)
if (stakingRate != null) {
return resourceReference(
R.string.yield_module_earn_badge,
wrappedList(stakingApy),
) to hasStakedBalance
wrappedList(stakingRate.format { percent(withPercentSign = false) }),
) to hasStaked
}
}
return null to false
}
private fun findStakingRate(
currencyStatus: CryptoCurrencyStatus,
stakingApyMap: Map<String, List<Yield.Validator>>,
): Pair<BigDecimal?, Boolean> {
val stakingKey = currencyStatus.currency.stakingKey()
val validators = stakingApyMap[stakingKey] ?: return null to false
val yieldBalance = currencyStatus.value.yieldBalance
val hasStakedBalance = yieldBalance is YieldBalance.Data
val rate = if (hasStakedBalance) {
val validatorsByAddress = validators.associateBy { it.address }
yieldBalance.balance.items
.mapNotNull { it.validatorAddress }
.firstNotNullOfOrNull { address -> validatorsByAddress[address]?.rewardInfo?.rate }
?: validators.mapNotNull { it.rewardInfo?.rate }.maxOrNull()
} else {
validators.mapNotNull { it.rewardInfo?.rate }.maxOrNull()
}
return rate to hasStakedBalance
}
private fun createSubtitleState(
currencyStatus: CryptoCurrencyStatus,
appCurrency: AppCurrency,

View file

@ -7,4 +7,5 @@ import com.squareup.moshi.JsonClass
data class YieldSupplyChangeTokenStatusBody(
@Json(name = "tokenAddress") val tokenAddress: String,
@Json(name = "chainId") val chainId: Int,
@Json(name = "userAddress") val userAddress: String,
)

View file

@ -337,7 +337,7 @@
<string name="common_transaction_failed">Transaktion fehlgeschlagen</string>
<string name="common_transaction_status">Transaktionsstatus</string>
<string name="common_transactions">Transaktionen</string>
<string name="common_transfer">Überweisung</string>
<string name="common_transfer">Überweiseung</string>
<string name="common_unable_to_load">Die Daten konnten nicht geladen werden…</string>
<string name="common_understand">Ich verstehe</string>
<string name="common_unknown_error">Es ist ein Fehler aufgetreten. Bitte versuche es erneut.</string>
@ -1708,7 +1708,7 @@
<string name="yield_module_fee_policy_sheet_min_amount_note">Der Mindestbetrag wird aus der aktuellen Netzwerkgebühr berechnet, um sicherzustellen, dass er 4%% nicht überschreitet, was den Mindestbetrag %1$s (%2$s) ergibt.</string>
<string name="yield_module_fee_policy_sheet_min_amount_title">Mindestaufladung</string>
<string name="yield_module_fee_policy_sheet_title">Gebührenpolitik</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem erhebt außerdem eine Servicegebühr von 3% auf den erzielten Ertrag.</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem erhebt außerdem eine Servicegebühr von 15% auf den erzielten Ertrag.</string>
<string name="yield_module_high_fee_error">Deine Gelder werden automatisch an Aave überwiesen, sobald die Netzwerkgebühren niedriger sind oder Dein Guthaben den erforderlichen Mindestbetrag erreicht.</string>
<string name="yield_module_historical_returns">Historische Renditen</string>
<string name="yield_module_main_view_approve_notification_description">Die Freigabe für Deine Token im Yield-Modus wurde widerrufen. Öffne den Token, um die Berechtigung erneut zu erteilen.</string>
@ -1720,7 +1720,7 @@
<string name="yield_module_promo_screen_cash_out_subtitle">Senden, tauschen oder verkaufen Deine Gelder sofort, wann immer Du willst.</string>
<string name="yield_module_promo_screen_cash_out_title">Jederzeit Zugriff auf Dein Geld</string>
<string name="yield_module_promo_screen_how_it_works_button_title">Wie funktioniert das?</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave ist ein dezentrales Protokoll, das einen Gesamtwert von über 81,9 Milliarden US-Dollar verwaltet.</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave ist ein dezentrales Protokoll, das einen Gesamtwert von über 61 Milliarden US-Dollar verwaltet.</string>
<string name="yield_module_promo_screen_self_custodial_title">Dezentral und selbstverwahrend</string>
<string name="yield_module_promo_screen_terms_disclaimer">Durch die Nutzung dieses Dienstes erklärst Du Dich mit provider\n%1$s und %2$s einverstanden</string>
<string name="yield_module_promo_screen_title">Mit Aave verbinden</string>
@ -1743,11 +1743,9 @@
<string name="yield_module_stop_earning_sheet_fee_note">Die Netzwerkgebühr wird von dem Betrag, den Du abhebst, abgezogen.</string>
<string name="yield_module_supply_apr">Effektiver Jahreszins für Versorgung</string>
<string name="yield_module_token_details_earn_notification_apy">Effektiver Jahreszins</string>
<string name="yield_module_token_details_earn_notification_description">Lass Dein Geld arbeiten verdiene Zinsen auf Dein Guthaben.</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_subtitle">Zinsen fallen automatisch an</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_title">Ertragsmodus</string>
<string name="yield_module_token_details_earn_notification_processing">Bearbeitung Deiner Einzahlung</string>
<string name="yield_module_token_details_earn_notification_title">Lass dein Guthaben arbeiten</string>
<string name="yield_module_transfer_mode_automatic">Automatisch</string>
<string name="yield_module_unable_to_cover_fee_description">Einzahlung von %1$s %2$s zur Deckung der Netzwerkgebühr für Transaktionen</string>
<string name="yield_module_unable_to_cover_fee_title">Die Gebühr %s kann nicht gedeckt werden</string>

View file

@ -1509,7 +1509,7 @@
<string name="yield_module_fee_policy_sheet_min_amount_note">El monto mínimo se calcula a partir de la tarifa de red actual para garantizar que no exceda 4%%, lo que hace que el mínimo sea %1$s (%2$s).</string>
<string name="yield_module_fee_policy_sheet_min_amount_title">Recarga mínima</string>
<string name="yield_module_fee_policy_sheet_title">Política de tarifas</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem también cobra una comisión de servicio del 3% sobre el rendimiento obtenido.</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem también cobra una comisión de servicio del 15% sobre el rendimiento obtenido.</string>
<string name="yield_module_high_fee_error">Sus fondos se suministrarán automáticamente a Aave una vez que las comisiones de red sean más bajas o su saldo alcance el importe mínimo requerido.</string>
<string name="yield_module_historical_returns">Rendimientos históricos</string>
<string name="yield_module_main_view_approve_notification_description">Se ha revocado la autorización para su token en el modo Rendimiento. Abra el token para volver a conceder el permiso.</string>
@ -1521,7 +1521,7 @@
<string name="yield_module_promo_screen_cash_out_subtitle">Envíe, intercambie o venda sus fondos al instante, cuando quiera.</string>
<string name="yield_module_promo_screen_cash_out_title">Acceda a sus fondos en cualquier momento</string>
<string name="yield_module_promo_screen_how_it_works_button_title">¿Cómo funciona?</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave es un protocolo descentralizado que administra más de 81.9 billones de dólares en valor total.</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave es un protocolo descentralizado que administra más de 61 billones de dólares en valor total.</string>
<string name="yield_module_promo_screen_self_custodial_title">Descentralizado y autocustodiado</string>
<string name="yield_module_promo_screen_terms_disclaimer">Al utilizar este servicio, usted acepta que el proveedor\n%1$s y %2$s</string>
<string name="yield_module_promo_screen_title">Conectar Aave</string>
@ -1544,11 +1544,9 @@
<string name="yield_module_stop_earning_sheet_fee_note">La comisión de red se deducirá del importe que retire.</string>
<string name="yield_module_supply_apr">Suministro APY</string>
<string name="yield_module_token_details_earn_notification_apy">APY</string>
<string name="yield_module_token_details_earn_notification_description">Deje que sus fondos hagan el trabajo mientras usted mantiene el control.</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_subtitle">Los intereses se devengan automáticamente</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_title">Modo de rendimiento</string>
<string name="yield_module_token_details_earn_notification_processing">Procesando su depósito</string>
<string name="yield_module_token_details_earn_notification_title">Haga que sus activos trabajen para usted</string>
<string name="yield_module_transfer_mode_automatic">Automático</string>
<string name="yield_module_unable_to_cover_fee_description">Deposite algo de %1$s %2$s para cubrir la tarifa de red para las transacciones</string>
<string name="yield_module_unable_to_cover_fee_title">No se puede cubrir la tarifa %s</string>

View file

@ -244,7 +244,7 @@
<string name="common_transaction_failed">La transaction a échoué</string>
<string name="common_transaction_status">Statut de la transaction</string>
<string name="common_transactions">Transactions</string>
<string name="common_transfer">Transfert</string>
<string name="common_transfer">Fourniture</string>
<string name="common_understand">Je comprends</string>
<string name="common_unknown_error">Il y avait une erreur. Veuillez réessayer.</string>
<string name="common_unreachable">Inaccessible</string>
@ -1457,13 +1457,14 @@
<string name="xtz_withdrawal_message_warning">Pour ne pas payer un fraid de commissions élevé la prochaine fois que vous rechargez votre portefeuille, veuillez réduire le montant de %s XTZ</string>
<string name="yield_module_alert_description">Vos fonds sont actuellement fournis au protocole Aave, mais vous pouvez les gérer à tout moment.</string>
<string name="yield_module_alert_title">Vos %s sont fournis à Aave.</string>
<string name="yield_module_amount_not_transfered_to_aave_title">Le transfert de %1$s %2$s vers Aave est en attente.</string>
<string name="yield_module_amount_not_transfered_to_aave_title">Le transfert de %1$s %2$s vers Aave est en attente.</string>
<string name="yield_module_approve_needed_notification_cta">Donnez votre accord</string>
<string name="yield_module_approve_needed_notification_description">Un problème est survenu lors de votre précédente approbation, nous avons donc besoin d\'une nouvelle approbation. Choisissez comment vous souhaitez procéder.</string>
<string name="yield_module_approve_needed_notification_title">Autorisation nécessaire</string>
<string name="yield_module_approve_sheet_fee_note">Les frais seront prélevés et vos actifs seront à nouveau prêtés.</string>
<string name="yield_module_approve_sheet_subtitle">Pour continuer à percevoir des revenus, une autorisation est nécessaire.</string>
<string name="yield_module_approve_sheet_title">Confirmer l\'approbation</string>
<string name="yield_module_balance_info_sheet_subtitle">Vos fonds sont actuellement affectés au protocole Aave, mais vous pouvez les gérer à tout moment.</string>
<string name="yield_module_balance_info_sheet_title">Vos %s sont déposés dans Aave.</string>
<string name="yield_module_chart_loading_error">Impossible de charger le graphique...</string>
<string name="yield_module_deposit_error_notification_title">Le montant reçu, %1$s %2$s, n\'a pas été fourni à Aave.</string>
@ -1487,9 +1488,10 @@
<string name="yield_module_fee_policy_sheet_min_amount_note">Le montant minimum est calculé à partir des frais de réseau actuels afin de garantir qu\'il ne dépasse pas 4 %%, ce qui donne un minimum de %1$s (%2$s).</string>
<string name="yield_module_fee_policy_sheet_min_amount_title">Recharge minimale</string>
<string name="yield_module_fee_policy_sheet_title">Politique tarifaire</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem prélève également des frais de service de 3% sur les revenus générés.</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem prélève également des frais de service de 15% sur les revenus générés.</string>
<string name="yield_module_high_fee_error">Vos fonds seront automatiquement transférés vers Aave dès que les frais de réseau seront moins élevés ou que votre solde atteindra le montant minimum requis.</string>
<string name="yield_module_historical_returns">Rendements historiques</string>
<string name="yield_module_main_view_approve_notification_description">L\'autorisation pour votre token en mode Yield a été révoquée. Ouvrez le token pour accorder à nouveau l\'autorisation.</string>
<string name="yield_module_main_view_approve_notification_title">Approbations de tokens nécessaires</string>
<string name="yield_module_network_fee_unreachable_notification_description">Vérifiez votre connexion réseau.</string>
<string name="yield_module_network_fee_unreachable_notification_title">Informations sur les frais de réseau inaccessibles</string>
@ -1498,7 +1500,7 @@
<string name="yield_module_promo_screen_cash_out_subtitle">Envoyez, échangez ou vendez vos fonds instantanément, quand vous le souhaitez.</string>
<string name="yield_module_promo_screen_cash_out_title">Accédez à vos fonds à tout moment</string>
<string name="yield_module_promo_screen_how_it_works_button_title">Comment ça marche ?</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave est un protocole décentralisé qui gère plus de 81,9 milliards de dollars en valeur totale.</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave est un protocole décentralisé qui gère plus de 61 milliards de dollars en valeur totale.</string>
<string name="yield_module_promo_screen_self_custodial_title">Décentralisé et auto-détenu</string>
<string name="yield_module_promo_screen_terms_disclaimer">En utilisant ce service, vous acceptez les conditions générales du fournisseur %1$s et %2$s.</string>
<string name="yield_module_promo_screen_title">Connecter Aave</string>
@ -1521,11 +1523,9 @@
<string name="yield_module_stop_earning_sheet_fee_note">Les frais de réseau seront déduits du montant que vous retirez.</string>
<string name="yield_module_supply_apr">Rendement annuel brut (APY)</string>
<string name="yield_module_token_details_earn_notification_apy">APY</string>
<string name="yield_module_token_details_earn_notification_description">Laissez vos fonds travailler pour vous tout en gardant le contrôle.</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_subtitle">Les intérêts sont cumulés automatiquement.</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_title">Mode de rendement</string>
<string name="yield_module_token_details_earn_notification_processing">Traitement de votre dépôt</string>
<string name="yield_module_token_details_earn_notification_title">Faites fructifier vos actifs</string>
<string name="yield_module_transfer_mode_automatic">Automatique</string>
<string name="yield_module_unable_to_cover_fee_description">Déposez %1$s %2$s pour couvrir les frais de réseau liés aux transactions.</string>
<string name="yield_module_unable_to_cover_fee_title">Impossible de couvrir les frais %s</string>

View file

@ -181,6 +181,7 @@
<string name="cardano_max_amount_has_token_title">ADAが不足しています。</string>
<string name="common_accept">受け入れる</string>
<string name="common_access_denied">アクセスが拒否されました</string>
<string name="common_account">アカウント</string>
<string name="common_accounts">アカウント</string>
<string name="common_activate">有効化</string>
<string name="common_add">追加</string>
@ -244,6 +245,7 @@
<string name="common_enable">有効にする</string>
<string name="common_enabled">有効</string>
<string name="common_error">エラー</string>
<string name="common_estimated_fee">ネットワークサービス手数料</string>
<string name="common_exchange">スワップ</string>
<string name="common_explore">移動する</string>
<string name="common_explore_transaction_history">取引履歴を調べる</string>
@ -476,7 +478,7 @@
<string name="express_provider">プロバイダー</string>
<string name="express_provider_best_rate">ベストレート</string>
<string name="express_provider_fca_warning_list">FCA警告リスト</string>
<string name="express_provider_great_rate">お得なレート</string>
<string name="express_provider_great_rate">ベストチョイス</string>
<string name="express_provider_in_fca_warning_list">FCA警告リストに掲載されたプロバイダー</string>
<string name="express_provider_max_amount">最大 %s まで使用可能</string>
<string name="express_provider_min_amount">%s 以上で利用可能</string>
@ -1346,7 +1348,7 @@
<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_yield_supply_approval">ここにテキストを入力</string>
<string name="token_button_unavailability_reason_yield_supply_approval">承認が取り消されましたが、あなたの資金は引き続き利息モードです。操作を行うには、利息モードに移動し、再度承認を付与してください。</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>
@ -1740,15 +1742,16 @@
<string name="xtz_withdrawal_message_ignore">いいえ、すべて送信します</string>
<string name="xtz_withdrawal_message_reduce">%s XTZを減らす</string>
<string name="xtz_withdrawal_message_warning">次回ウォレットにチャージするときに手数料の増加を避けるには、金額を%s XTZ減らしてください。</string>
<string name="yield_module_alert_description">あなたの資金は現在Aaveプロトコルに供給されていますが、いつでも管理できます。</string>
<string name="yield_module_alert_description">利息モードを有効にすると、このアドレスへの今後のすべての入金はAaveに送られます。ただし、資金の管理は引き続き自由に行えます。</string>
<string name="yield_module_alert_title">%sはAaveに供給されています</string>
<string name="yield_module_amount_not_transfered_to_aave_title">Aaveへの%1$s %2$sの供給は保留中です</string>
<string name="yield_module_approve_needed_notification_cta">承認する</string>
<string name="yield_module_approve_needed_notification_description">前回の承認に問題があったため、新しい承認が必要です。手続き方法を選択してください。</string>
<string name="yield_module_approve_needed_notification_description">トークンの承認は取り消されました。サービス機能を再開するには、再度承認を行ってください。</string>
<string name="yield_module_approve_needed_notification_title">承認が必要</string>
<string name="yield_module_approve_sheet_fee_note">手数料が差し引かれ、あなたの資産は再び貸し出されます。</string>
<string name="yield_module_approve_sheet_subtitle">引き続き収益を得るには承認が必要です。</string>
<string name="yield_module_approve_sheet_title">承認を確定する</string>
<string name="yield_module_balance_info_sheet_subtitle">あなたの資金は現在Aaveプロトコルに預けられていますが、いつでも自由に管理できます。</string>
<string name="yield_module_balance_info_sheet_title">あなたの%sはAaveに預けられています</string>
<string name="yield_module_chart_loading_error">チャートを読み込めません・・</string>
<string name="yield_module_deposit_error_notification_title">受け取った金額%1$s %2$sはAaveに入金されませんでした。</string>
@ -1758,8 +1761,8 @@
<string name="yield_module_earn_sheet_fee_description">貸付のために入金する際は、残高から%1$s以下のネットワーク手数料が差し引かれます。</string>
<string name="yield_module_earn_sheet_high_fee_description">現在、ネットワーク手数料が高すぎるため貸付を実行できません。手数料が%1$s以下に下がり次第、資金が供給されます。</string>
<string name="yield_module_earn_sheet_my_funds_title">私の資金</string>
<string name="yield_module_earn_sheet_provider_description">あなたの%1$sはAaveに預けられ、利息が付きます。あなたは%2$sトークンを保有しており、これは残高を表し、時間の経過とともに増加します。入金すると資金はAaveに供給され、取引手数料を差し引いた利息が付きます。</string>
<string name="yield_module_earn_sheet_title">回りを得る</string>
<string name="yield_module_earn_sheet_provider_description">あなたの%1$sは現在Aaveにデプロイされ、利回りを生んでいます。あなたは%2$sトークンを保有しており、これはあなたの残高を表し、自動的に利回りが発生します。追加入金すると、手数料を差し引いた上でAaveに資産が追加され、さらに利回りを得られるようになります。</string>
<string name="yield_module_earn_sheet_title">息モード</string>
<string name="yield_module_earn_sheet_total_earnings_title">総収益</string>
<string name="yield_module_earn_sheet_transfers_title">Aaveへの送金</string>
<string name="yield_module_explore_sheet_explore_aave_button_title">Aaveの詳細を見る</string>
@ -1769,13 +1772,14 @@
<string name="yield_module_fee_policy_sheet_fee_note">今後のチャージごとに、おおよそ%1$s%2$sのネットワーク手数料が差し引かれますが、上限の%3$s%4$sを超えることはありません。</string>
<string name="yield_module_fee_policy_sheet_max_fee_note">ネットワーク手数料が上限手数料を超えた場合、手数料が下がるまで取引は成立しません。この制限は後で変更できます。</string>
<string name="yield_module_fee_policy_sheet_max_fee_title">最大手数料</string>
<string name="yield_module_fee_policy_sheet_min_amount_note">最小金額は現在のネットワーク手数料に基づいて計算されており、手数料が4を超えないように設定されています。その結果、最小金額は%1$s%2$sとなります。</string>
<string name="yield_module_fee_policy_sheet_min_amount_note">最小金額は現在のネットワーク手数料に基づいて計算されており、手数料が4を超えないように設定されています。そのため、最小金額は%1$s%2$sとなります。</string>
<string name="yield_module_fee_policy_sheet_min_amount_title">最低入金額</string>
<string name="yield_module_fee_policy_sheet_title">手数料ポリシー</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangemはまた、得られた利回りに対して3%のサービス手数料を差し引きます。</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangemはまた、得られた利回りに対して15%のサービス手数料を差し引きます。</string>
<string name="yield_module_high_fee_error">ネットワーク手数料が下がるか、残高が最低必要額に達すると、資金は自動的にAaveに供給されます。</string>
<string name="yield_module_historical_returns">過去のリターン</string>
<string name="yield_module_main_view_approve_notification_title">トークンの承認が必要</string>
<string name="yield_module_main_view_approve_notification_description">利息モードでのトークンの承認が取り消されました。トークンを開いて再度許可してください。</string>
<string name="yield_module_main_view_approve_notification_title">トークンの承認が必要です</string>
<string name="yield_module_network_fee_unreachable_notification_description">ネットワーク接続を確認してください</string>
<string name="yield_module_network_fee_unreachable_notification_title">ネットワーク手数料についての情報にアクセスできません</string>
<string name="yield_module_promo_screen_auto_balance_subtitle">あなたが行うすべての入金は、自動的にAaveへ供給されます。</string>
@ -1783,7 +1787,7 @@
<string name="yield_module_promo_screen_cash_out_subtitle">いつでも、即座に資金を送信、交換、売却できます。</string>
<string name="yield_module_promo_screen_cash_out_title">いつでも資金にアクセス可能</string>
<string name="yield_module_promo_screen_how_it_works_button_title">使い方</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aaveは、総額819億ドル以上の資産を管理する分散型プロトコルです。</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aaveは、総額610億ドル以上の資産を管理する分散型プロトコルです。</string>
<string name="yield_module_promo_screen_self_custodial_title">分散型・自己管理型</string>
<string name="yield_module_promo_screen_terms_disclaimer">このサービスを利用することにより、プロバイダー\n%1$sおよび%2$sに同意するものとします。</string>
<string name="yield_module_promo_screen_title">Aave を接続</string>
@ -1802,19 +1806,20 @@
<string name="yield_module_status_active">アクティブ</string>
<string name="yield_module_status_paused">停止中</string>
<string name="yield_module_stop_earning">利回りモードを無効にする</string>
<string name="yield_module_stop_earning_sheet_description">これをオフにすると、Aave からウォレットの %s に資金が引き出され、報酬の獲得が停止します。</string>
<string name="yield_module_stop_earning_sheet_description">これをオフにすると、Aaveから資産が引き出され、ウォレット内の%sに変換され、利回りの発生が停止します。</string>
<string name="yield_module_stop_earning_sheet_fee_note">出金金額からネットワーク手数料が差し引かれます。</string>
<string name="yield_module_supply">供給</string>
<string name="yield_module_supply_apr">供給APY</string>
<string name="yield_module_token_details_earn_notification_apy">APY</string>
<string name="yield_module_token_details_earn_notification_description">自分で管理しながら、資金に働かせましょう。</string>
<string name="yield_module_token_details_earn_notification_description">利息は自動的に発生します</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_subtitle">利息は自動的に発生します</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_title">利回りモード</string>
<string name="yield_module_token_details_earn_notification_processing">入金の処理中</string>
<string name="yield_module_token_details_earn_notification_title">資産を有効活用しましょう</string>
<string name="yield_module_token_details_earn_notification_title">利息モード</string>
<string name="yield_module_transfer_mode_automatic">自動</string>
<string name="yield_module_unable_to_cover_fee_description">取引のネットワーク手数料をカバーするために、 %1$s %2$sを入金してください</string>
<string name="yield_module_unable_to_cover_fee_title">%s手数料を支払えません</string>
<string name="yield_module_unavailable_subtitle">利息サービスは現在利用できません。しばらくしてから再度お試しください。</string>
<string name="yield_module_unavailable_title">収益は利用できません</string>
<string name="yield_module_unavailable_subtitle">現在、利息モードのサービスは利用できません。しばらくしてから再度お試しください。</string>
<string name="yield_module_unavailable_title">利息モードは利用できません</string>
<string name="yield_supply_chart_loading_error">チャートを読み込めません・・</string>
</resources>

View file

@ -181,6 +181,7 @@
<string name="common_enable">Включить</string>
<string name="common_enabled">Включено</string>
<string name="common_error">Ошибка</string>
<string name="common_estimated_fee">Комиссия сети</string>
<string name="common_exchange">Обменять</string>
<string name="common_explore">Обозреватель</string>
<string name="common_explore_transaction_history">Посмотреть историю транзакций</string>
@ -1588,7 +1589,7 @@
<string name="yield_module_earn_sheet_available_title">Доступно</string>
<string name="yield_module_earn_sheet_current_apy_title">Текущий APY</string>
<string name="yield_module_earn_sheet_my_funds_title">Мои средства</string>
<string name="yield_module_earn_sheet_provider_description">Ваш %1$s теперь внесён в Aave и приносит проценты. У вас есть токен %2$s, который отражает ваш баланс и со временем увеличивается. При пополнении средства автоматически направляются в Aave для получения процентов за вычетом комиссии за транзакцию.</string>
<string name="yield_module_earn_sheet_provider_description">Ваши %1$s теперь внесён в Aave и приносит проценты. У вас есть токен %2$s, который отражает ваш баланс и со временем увеличивается. При пополнении средства автоматически направляются в Aave для получения процентов за вычетом комиссии за транзакцию.</string>
<string name="yield_module_earn_sheet_total_earnings_title">Итоговый доход</string>
<string name="yield_module_earn_sheet_transfers_title">Переводы в Aave</string>
<string name="yield_module_explore_sheet_explore_aave_button_title">Изучите Aave</string>
@ -1600,7 +1601,7 @@
<string name="yield_module_fee_policy_sheet_min_amount_note">Это минимальный депозит, который можно отправить в Aave. Чтобы депозиты оставались прибыльными, мы не обрабатываем их, когда комиссия сети превышает %1$s%2$sот суммы.</string>
<string name="yield_module_fee_policy_sheet_min_amount_title">Минимальный депозит</string>
<string name="yield_module_fee_policy_sheet_title">Политика комиссий</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem взимает комиссию за обслуживание в размере 3% от полученного дохода.</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem взимает комиссию за обслуживание в размере 15% от полученного дохода.</string>
<string name="yield_module_high_fee_error">Ваши средства будут автоматически переведены в Aave, как только комиссия сети снизится или баланс достигнет минимально необходимой суммы.</string>
<string name="yield_module_historical_returns">Историческая доходность</string>
<string name="yield_module_main_view_approve_notification_description">Разрешение для вашего токена в Yield сервисе было отозвано. Откройте токен, чтобы выдать разрешение снова.</string>
@ -1612,7 +1613,7 @@
<string name="yield_module_promo_screen_cash_out_subtitle">Отправляйте, обменивайте или продавайте свои средства мгновенно, когда захотите.</string>
<string name="yield_module_promo_screen_cash_out_title">Мгновенный вывод средств</string>
<string name="yield_module_promo_screen_how_it_works_button_title">Как это работает?</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave — это децентрализованный протокол, управляющий активами на сумму более 81,9 миллиарда долларов США.</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave — это децентрализованный протокол, управляющий активами на сумму более 61 миллиарда долларов США.</string>
<string name="yield_module_promo_screen_self_custodial_title">Децентрализованный и некастодиальный</string>
<string name="yield_module_promo_screen_terms_disclaimer">Используя сервис, вы соглашаетесь с условиями провайдера %1$s и %2$s</string>
<string name="yield_module_promo_screen_title">Подключить Aave</string>
@ -1631,15 +1632,13 @@
<string name="yield_module_status_active">Активен</string>
<string name="yield_module_status_paused">На паузе</string>
<string name="yield_module_stop_earning">Завершить заработок</string>
<string name="yield_module_stop_earning_sheet_description">Выключив эту функцию, вы выведёте средства из Aave, получите их обратно в %s в кошельке и перестанете зарабатывать награды.</string>
<string name="yield_module_stop_earning_sheet_description">Выключив эту функцию, вы выведёте средства из Aave, получите их обратно в %s в своем кошельке и перестанете зарабатывать награды.</string>
<string name="yield_module_stop_earning_sheet_fee_note">Комиссия сети будет вычтена из суммы вашего вывода.</string>
<string name="yield_module_supply_apr">Годовая доходность (APY)</string>
<string name="yield_module_token_details_earn_notification_apy">APY</string>
<string name="yield_module_token_details_earn_notification_description">Пусть ваши деньги работают — зарабатывайте проценты на свой баланс.</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_subtitle">Проценты начисляются автоматически.</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_title">Режим доходности</string>
<string name="yield_module_token_details_earn_notification_processing">Отправка ваших средств</string>
<string name="yield_module_token_details_earn_notification_title">Пусть ваш баланс работает на вас!</string>
<string name="yield_module_transfer_mode_automatic">Автоматически</string>
<string name="yield_module_unable_to_cover_fee_description">Внесите немного %1$s %2$s, чтобы покрыть комиссию сети за транзакции.</string>
<string name="yield_module_unable_to_cover_fee_title">Невозможно покрыть комиссию в %s</string>

View file

@ -1432,6 +1432,80 @@
<string name="xtz_withdrawal_message_ignore">Ні, відправити все</string>
<string name="xtz_withdrawal_message_reduce">Зменшити на %s XTZ</string>
<string name="xtz_withdrawal_message_warning">Щоб не платити підвищену комісію при наступному поповненні гаманця, зменште суму на %s XTZ</string>
<string name="yield_module_alert_description">З активним режимом дохідності всі майбутні депозити на цю адресу будуть надходити до Aave. Ви все ще можете вільно розпоряджатися своїми коштами.</string>
<string name="yield_module_alert_title">Ваш %s внесений до Aave</string>
<string name="yield_module_amount_not_transfered_to_aave_title">Передача %1$s %2$s до Aave очікується</string>
<string name="yield_module_approve_needed_notification_cta">Дати згоду</string>
<string name="yield_module_approve_needed_notification_description">Схвалення для вашого токена було відкликано. Надайте його знову, щоб відновити роботу сервісу.</string>
<string name="yield_module_approve_needed_notification_title">Потрібне схвалення</string>
<string name="yield_module_approve_sheet_fee_note">Комісія буде знята, а ваші активи знову почнуть приносити дохід.</string>
<string name="yield_module_approve_sheet_subtitle">Щоб продовжити заробляти, потрібне схвалення.</string>
<string name="yield_module_approve_sheet_title">Підтвердити дозвіл</string>
<string name="yield_module_balance_info_sheet_subtitle">Наразі ваші кошти розміщені у протоколі Aave, але ви можете керувати ними в будь-який час.</string>
<string name="yield_module_balance_info_sheet_title">Ваш %s внесений у Aave</string>
<string name="yield_module_chart_loading_error">Неможливо завантажити графік</string>
<string name="yield_module_deposit_error_notification_title">Отримана сума, %1$s %2$s не була зарахована на Aave.</string>
<string name="yield_module_earn_badge">APY %1$s%%</string>
<string name="yield_module_earn_sheet_available_title">Доступно</string>
<string name="yield_module_earn_sheet_current_apy_title">Поточний APY</string>
<string name="yield_module_earn_sheet_fee_description">При поповненні для кредитування з балансу буде вирахувано комісію мережі, що не перевищує %1$s.</string>
<string name="yield_module_earn_sheet_high_fee_description">Наразі мережева комісія є занадто високою, щоб здійснювати кредитування. Кошти будуть надані, як тільки вона знизиться до %1$s або нижче.</string>
<string name="yield_module_earn_sheet_my_funds_title">Мої кошти</string>
<string name="yield_module_earn_sheet_provider_description">Ваші %1$s тепер розміщено в Aave і приносить дохід. У вас є токен %2$s, який представляє ваш баланс і з часом збільшується. При поповненні кошти автоматично направляються в Aave для отримання процентів з вирахуванням комісії за транзакцію.</string>
<string name="yield_module_earn_sheet_title">Режим дохідності</string>
<string name="yield_module_earn_sheet_total_earnings_title">Підсумковий дохід</string>
<string name="yield_module_earn_sheet_transfers_title">Перекази в Aave</string>
<string name="yield_module_explore_sheet_explore_aave_button_title">Дослідити Aave</string>
<string name="yield_module_fee_policy_sheet_current_fee_note">Це поточна комісія у мережі %s.</string>
<string name="yield_module_fee_policy_sheet_current_fee_title">Поточна комісія</string>
<string name="yield_module_fee_policy_sheet_description">Усі майбутні депозити %s будуть надходити до Aave автоматично, з вирахуванням комісії за транзакцію.</string>
<string name="yield_module_fee_policy_sheet_fee_note">Приблизна мережева плата в розмірі %1$s (%2$s) буде вираховуватися з кожного наступного поповнення, і вона не перевищуватиме ваш ліміт %3$s (%4$s).</string>
<string name="yield_module_fee_policy_sheet_max_fee_note">Якщо мережеві комісії перевищують максимальну комісію, транзакція не пройде, поки вони не знизяться. Ви можете змінити цей ліміт пізніше.</string>
<string name="yield_module_fee_policy_sheet_max_fee_title">Максимальна комісія</string>
<string name="yield_module_fee_policy_sheet_min_amount_note">Це найменший депозит, який можна надіслати в Aave. Щоб депозити залишалися прибутковими, ми не обробляємо їх, коли комісія мережі перевищує %1$s%2$s від суми.</string>
<string name="yield_module_fee_policy_sheet_min_amount_title">Мінімальне поповнення</string>
<string name="yield_module_fee_policy_sheet_title">Політика комісій</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem комісію за обслуговування у розмірі 15% від отриманого доходу.</string>
<string name="yield_module_high_fee_error">Ваші кошти будуть автоматично переведені у Aave, як тільки мережеві комісії знизяться або ваш баланс досягне мінімально необхідної суми.</string>
<string name="yield_module_historical_returns">Історична прибутковість</string>
<string name="yield_module_main_view_approve_notification_description">Дозвіл для вашого токена в режимі Yield було відкликано. Відкрийте токен, щоб надати дозвіл знову.</string>
<string name="yield_module_main_view_approve_notification_title">Потрібний дозвіл для токену</string>
<string name="yield_module_network_fee_unreachable_notification_description">Перевірте підключення до мережі</string>
<string name="yield_module_network_fee_unreachable_notification_title">Інформація про комісію недоступна</string>
<string name="yield_module_promo_screen_auto_balance_subtitle">Кожен ваш депозит буде автоматично надходити до Aave.</string>
<string name="yield_module_promo_screen_auto_balance_title">Автопереказ до AAVE</string>
<string name="yield_module_promo_screen_cash_out_subtitle">Відправляйте, обмінюйте або продавайте свої кошти миттєво, в будь-який час.</string>
<string name="yield_module_promo_screen_cash_out_title">Миттєвий вивід коштів</string>
<string name="yield_module_promo_screen_how_it_works_button_title">Як це працює?</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave — це децентралізований протокол, який управляє активами загальною вартістю понад 61 мільярд доларів.</string>
<string name="yield_module_promo_screen_self_custodial_title">Децентралізований та некастодіальний</string>
<string name="yield_module_promo_screen_terms_disclaimer">Використовуючи сервіс, ви погоджуєтесь з умовами провайдера %1$s та %2$s</string>
<string name="yield_module_promo_screen_title">Підключити Aave</string>
<string name="yield_module_promo_screen_variable_rate_info">Aave %1$s%% • Ставка з плаваючим відсотком</string>
<string name="yield_module_provider">Аave</string>
<string name="yield_module_rate_info_sheet_chart_average">Серед. %s</string>
<string name="yield_module_rate_info_sheet_chart_title">Дохідність за минулий рік</string>
<string name="yield_module_rate_info_sheet_description">Поточна відсоткова ставка завжди змінна і автоматично розраховується смарт-контрактом Aave у блокчейні на основі попиту та пропозиції в режимі реального часу.</string>
<string name="yield_module_rate_info_sheet_powered_by">При підтримці</string>
<string name="yield_module_rate_info_sheet_title">Ставка може змінюватися</string>
<string name="yield_module_receive_sheet_description">Коли ви поповнюєте рахунок, ваші кошти автоматично надсилатимуться на Aave, щоб почати нараховувати відсотки. Для покриття комісії з вас буде утримана невелика плата у розмірі %s.</string>
<string name="yield_module_start_earning">Почати заробляти</string>
<string name="yield_module_start_earning_sheet_description">Ваш %s буде передано до Aave, і залишиться завжди доступним.</string>
<string name="yield_module_start_earning_sheet_fee_policy">Політика комісій</string>
<string name="yield_module_start_earning_sheet_next_deposits">Ваші наступні поповнення рахунку автоматично надходитимуть до Aave.</string>
<string name="yield_module_status_active">Активний</string>
<string name="yield_module_status_paused">На паузі</string>
<string name="yield_module_stop_earning">Завершити заробіток</string>
<string name="yield_module_stop_earning_sheet_description">Вимкнення цієї опції виведе ваші активи з Aave, отримаєте їх назад у %s у вашому гаманці і зупинить накопичення нагород.</string>
<string name="yield_module_stop_earning_sheet_fee_note">Комісія мережі буде вирахувана з суми, яку ви знімаєте.</string>
<string name="yield_module_supply_apr">Річна прибутковість (APY)</string>
<string name="yield_module_token_details_earn_notification_apy">APY</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_subtitle">Відсотки нараховуються автоматично</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_title">Режим дохідності</string>
<string name="yield_module_token_details_earn_notification_processing">Відправка ваших коштів</string>
<string name="yield_module_transfer_mode_automatic">Автоматично</string>
<string name="yield_module_unable_to_cover_fee_description">Внесіть трохи %1$s %2$s, щоб покрити комісію мережі за транзакції.</string>
<string name="yield_module_unable_to_cover_fee_title">Неможливо покрити комісію в %s</string>
<string name="yield_module_unavailable_subtitle">Сервіс доходності у даний час недоступний. Будь ласка, спробуйте пізніше.</string>
<string name="yield_module_unavailable_title">Режим дохідності недоступний</string>
</resources>

View file

@ -184,6 +184,7 @@
<string name="cardano_max_amount_has_token_title">Not enough ADA</string>
<string name="common_accept">Accept</string>
<string name="common_access_denied">Access denied</string>
<string name="common_account">Account</string>
<string name="common_accounts">Accounts</string>
<string name="common_activate">Activate</string>
<string name="common_add">Add</string>
@ -249,7 +250,7 @@
<string name="common_enable">Enable</string>
<string name="common_enabled">Enabled</string>
<string name="common_error">Error</string>
<string name="common_estimated_fee">Estimated fee</string>
<string name="common_estimated_fee">Network service fee</string>
<string name="common_exchange">Swap</string>
<string name="common_explore">Explore</string>
<string name="common_explore_transaction_history">Explore transaction history</string>
@ -1815,7 +1816,7 @@
<string name="xtz_withdrawal_message_warning">To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ</string>
<string name="yield_module_alert_description">With Yield mode active, all future deposits to this address will go to Aave. You can still manage your funds freely.</string>
<string name="yield_module_alert_title">Your %s is supplied to Aave</string>
<string name="yield_module_amount_not_transfered_to_aave_title">Supplying %1$s %2$s to Aave is pending</string>
<string name="yield_module_amount_not_transfered_to_aave_title">Supplying %1$s %2$s to Aave is pending</string>
<string name="yield_module_approve_needed_notification_cta">Give Approve</string>
<string name="yield_module_approve_needed_notification_description">Your tokens approval has been revoked. Grant it again to resume service functionality.</string>
<string name="yield_module_approve_needed_notification_title">Approve needed</string>
@ -1832,7 +1833,7 @@
<string name="yield_module_earn_sheet_fee_description">When topping up for lending, a network fee not exceeding %1$s will be deducted from the balance.</string>
<string name="yield_module_earn_sheet_high_fee_description">The network fee is currently too high to execute lending. Funds will be supplied once it drops to %1$s or below. </string>
<string name="yield_module_earn_sheet_my_funds_title">My funds</string>
<string name="yield_module_earn_sheet_provider_description">Your %1$s is now deposited in Aave and earning interest. You hold a%2$s token, which represents your balance and grows over time. When you deposit more funds, they\'ll be supplied to Aave to earn interest, minus a transaction fee.</string>
<string name="yield_module_earn_sheet_provider_description">Your %1$s is now deployed to Aave and earning yield. You hold %2$s tokens, which represent your balance and accrue yield automatically. When you top up, funds are added to Aave to earn more yield, minus fees.</string>
<string name="yield_module_earn_sheet_title">Yield mode</string>
<string name="yield_module_earn_sheet_total_earnings_title">Total earnings</string>
<string name="yield_module_earn_sheet_transfers_title">Transfers to Aave</string>
@ -1840,13 +1841,13 @@
<string name="yield_module_fee_policy_sheet_current_fee_note">This is the current supply fee on %s. The actual cost will be shown on the activation tab.</string>
<string name="yield_module_fee_policy_sheet_current_fee_title">Current fee</string>
<string name="yield_module_fee_policy_sheet_description">All future %s deposits will be supplied to Aave automatically, with the transaction fee deducted.</string>
<string name="yield_module_fee_policy_sheet_fee_note">An approximate network fee of %1$s (%2$s) will be deducted from each future top-up, and it wont exceed your %3$s (%4$s) limit.</string>
<string name="yield_module_fee_policy_sheet_fee_note">An approximate network fee of %1$s (%2$s) will be deducted from each future top-up, and it wont exceed your %3$s (%4$s) limit.</string>
<string name="yield_module_fee_policy_sheet_max_fee_note">If network fees rise above maximum fee, the transaction wont go through until they decrease. You can change this limit later.</string>
<string name="yield_module_fee_policy_sheet_max_fee_title">Maximum fee</string>
<string name="yield_module_fee_policy_sheet_min_amount_note">The minimum amount is calculated from the current network fee to ensure it does not exceed 4%%, which makes the minimum %1$s (%2$s).</string>
<string name="yield_module_fee_policy_sheet_min_amount_title">Minimum top-up</string>
<string name="yield_module_fee_policy_sheet_title">Fee policy</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem also takes a 3% service fee on yield earned.</string>
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem also takes a 15% service fee on yield earned.</string>
<string name="yield_module_high_fee_error">Your funds will be automatically supplied to Aave once network fees are lower or your balance meets the minimum required amount.</string>
<string name="yield_module_historical_returns">Historical returns</string>
<string name="yield_module_main_view_approve_notification_description">Approval for your token in the Yield mode has been revoked. Open the token to grant permission again.</string>
@ -1858,7 +1859,7 @@
<string name="yield_module_promo_screen_cash_out_subtitle">Send, swap, or sell your funds instantly, anytime you want.</string>
<string name="yield_module_promo_screen_cash_out_title">Access your funds anytime</string>
<string name="yield_module_promo_screen_how_it_works_button_title">How it works?</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave is a decentralized protocol managing over $81.9billion in total value.</string>
<string name="yield_module_promo_screen_self_custodial_subtitle">Aave is a decentralized protocol managing over $61 billion in total value.</string>
<string name="yield_module_promo_screen_self_custodial_title">Decentralized and self-custodial</string>
<string name="yield_module_promo_screen_terms_disclaimer">By using this service, you agree with provider\n%1$s and %2$s</string>
<string name="yield_module_promo_screen_title">Connect Aave</string>
@ -1877,15 +1878,16 @@
<string name="yield_module_status_active">Active</string>
<string name="yield_module_status_paused">Paused</string>
<string name="yield_module_stop_earning">Disable yield mode</string>
<string name="yield_module_stop_earning_sheet_description">Turning this off will withdraw your funds from Aave to %s in your wallet and it will stop earning rewards.</string>
<string name="yield_module_stop_earning_sheet_description">Turning this off will withdraw your assets from Aave, convert them back to %s in your wallet, and stop yield accrual.</string>
<string name="yield_module_stop_earning_sheet_fee_note">The network fee will be deducted from the amount you withdraw.</string>
<string name="yield_module_supply">Supply</string>
<string name="yield_module_supply_apr">Supply APY</string>
<string name="yield_module_token_details_earn_notification_apy">APY</string>
<string name="yield_module_token_details_earn_notification_description">Let your funds do the work while you stay in control.</string>
<string name="yield_module_token_details_earn_notification_description">Interest accrues automatically</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_subtitle">Interest accrues automatically</string>
<string name="yield_module_token_details_earn_notification_earning_on_your_balance_title">Yield mode</string>
<string name="yield_module_token_details_earn_notification_processing">Processing your deposit</string>
<string name="yield_module_token_details_earn_notification_title">Make your assets work for you</string>
<string name="yield_module_token_details_earn_notification_title">Yield Mode</string>
<string name="yield_module_transfer_mode_automatic">Automatic</string>
<string name="yield_module_unable_to_cover_fee_description">Deposit some %1$s %2$s to cover the network fee for transactions</string>
<string name="yield_module_unable_to_cover_fee_title">Unable to cover %s fee</string>

View file

@ -9,6 +9,7 @@ import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.models.account.DerivationIndex
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWallet
import timber.log.Timber
import javax.inject.Inject
@ -53,11 +54,36 @@ class ResponseCryptoCurrenciesFactory @Inject constructor(
blockchain = blockchain.getTestnetVersion() ?: blockchain
}
val network = networkFactory.create(
blockchain = blockchain,
extraDerivationPath = responseToken.derivationPath,
userWallet = userWallet,
accountIndex = accountIndex,
) ?: return null
return createCurrency(responseToken = responseToken, userWallet = userWallet, network = network)
}
fun createCurrency(
responseToken: UserTokensResponse.Token,
userWallet: UserWallet,
network: Network,
): CryptoCurrency? {
var blockchain = Blockchain.fromNetworkId(responseToken.networkId)
if (blockchain == null || blockchain == Blockchain.Unknown) {
Timber.e("Unable to find a blockchain with the network ID: ${responseToken.networkId}")
return null
}
if (userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isTestCard()) {
blockchain = blockchain.getTestnetVersion() ?: blockchain
}
val sdkToken = createSdkToken(responseToken)
return if (sdkToken == null) {
createCoin(blockchain, responseToken, userWallet, accountIndex)
createCoin(blockchain, responseToken, network)
} else {
createToken(blockchain, sdkToken, responseToken.derivationPath, userWallet, accountIndex)
createToken(blockchain, sdkToken, network)
}
}
@ -76,16 +102,8 @@ class ResponseCryptoCurrenciesFactory @Inject constructor(
private fun createCoin(
blockchain: Blockchain,
responseToken: UserTokensResponse.Token,
userWallet: UserWallet,
accountIndex: DerivationIndex?,
network: Network,
): CryptoCurrency.Coin? {
val network = networkFactory.create(
blockchain = blockchain,
extraDerivationPath = responseToken.derivationPath,
userWallet = userWallet,
accountIndex = accountIndex,
) ?: return null
return CryptoCurrency.Coin(
id = getCoinId(network, blockchain.toCoinId()),
network = network,
@ -109,20 +127,7 @@ class ResponseCryptoCurrenciesFactory @Inject constructor(
}
}
private fun createToken(
blockchain: Blockchain,
sdkToken: Token,
responseDerivationPath: String?,
userWallet: UserWallet,
accountIndex: DerivationIndex?,
): CryptoCurrency.Token? {
val network = networkFactory.create(
blockchain = blockchain,
extraDerivationPath = responseDerivationPath,
userWallet = userWallet,
accountIndex = accountIndex,
) ?: return null
private fun createToken(blockchain: Blockchain, sdkToken: Token, network: Network): CryptoCurrency.Token? {
val id = getTokenId(network, sdkToken)
return CryptoCurrency.Token(

View file

@ -76,6 +76,24 @@ class NetworkFactory @Inject constructor(
)
}
/**
* Create
*
* @param blockchain blockchain
* @param derivationPath derivation path
* @param userWallet user wallet
*/
fun create(blockchain: Blockchain, derivationPath: Network.DerivationPath, userWallet: UserWallet): Network? {
return create(
blockchain = blockchain,
derivationPath = derivationPath,
canHandleTokens = userWallet.canHandleToken(
blockchain = blockchain,
excludedBlockchains = excludedBlockchains,
),
)
}
/**
* Create
*

View file

@ -2,6 +2,7 @@ package com.tangem.data.swap
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
import com.tangem.data.common.currency.UserTokensResponseFactory
import com.tangem.data.common.network.NetworkFactory
import com.tangem.data.swap.converter.transaction.SavedSwapStatusConverter
import com.tangem.data.swap.converter.transaction.SavedSwapTransactionConverter
import com.tangem.data.swap.converter.transaction.SavedSwapTransactionListConverter
@ -31,11 +32,15 @@ import kotlinx.coroutines.flow.flowOn
internal class DefaultSwapTransactionRepository(
private val appPreferencesStore: AppPreferencesStore,
private val responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory,
private val networkFactory: NetworkFactory,
private val dispatchers: CoroutineDispatcherProvider,
) : SwapTransactionRepository {
private val listConverter by lazy(LazyThreadSafetyMode.NONE) {
SavedSwapTransactionListConverter(responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory)
SavedSwapTransactionListConverter(
responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory,
networkFactory = networkFactory,
)
}
private val converter by lazy(LazyThreadSafetyMode.NONE) {
SavedSwapTransactionConverter(responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory)
@ -124,52 +129,25 @@ internal class DefaultSwapTransactionRepository(
}
}.flowOn(dispatchers.default)
override suspend fun removeTransaction(
userWalletId: UserWalletId,
fromCryptoCurrency: CryptoCurrency,
toCryptoCurrency: CryptoCurrency,
txId: String,
) {
override suspend fun removeTransaction(userWalletId: UserWalletId, txId: String) {
clearTransactionsStatuses(txId = txId)
appPreferencesStore.editData { mutablePreferences ->
val savedList: List<SwapTransactionListDTO>? = mutablePreferences.getObjectList(
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
)
val tokenTransactions = savedList
?.firstOrNull {
it.checkId(
checkUserWalletId = userWalletId,
fromCurrencyId = fromCryptoCurrency.id,
toCurrencyId = toCryptoCurrency.id,
)
}
?.transactions
?.filterNot { it.txId == txId }
?.asSequence()
?.map {
it.copy(transactions = it.transactions.filterNot { it.txId == txId })
}?.filterNot { it.transactions.isEmpty() }
?.toList()
val editedList =
if (tokenTransactions.isNullOrEmpty()) {
savedList?.filterNot {
it.checkId(
checkUserWalletId = userWalletId,
fromCurrencyId = fromCryptoCurrency.id,
toCurrencyId = toCryptoCurrency.id,
)
}
} else {
savedList.updateList(
userWalletId = userWalletId,
fromCryptoCurrency = fromCryptoCurrency,
toCryptoCurrency = toCryptoCurrency,
transactions = tokenTransactions,
)
}
if (editedList.isNullOrEmpty()) {
if (tokenTransactions.isNullOrEmpty()) {
mutablePreferences.remove(key = PreferencesKeys.SWAP_TRANSACTIONS_KEY)
} else {
mutablePreferences.setObject(
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
value = editedList,
value = tokenTransactions,
)
}
}

View file

@ -1,11 +1,16 @@
package com.tangem.data.swap.converter.transaction
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.fromNetworkId
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
import com.tangem.data.common.currency.UserTokensResponseFactory
import com.tangem.data.common.network.NetworkFactory
import com.tangem.data.swap.models.SwapStatusDTO
import com.tangem.data.swap.models.SwapTransactionDTO
import com.tangem.data.swap.models.SwapTransactionListDTO
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.swap.models.SwapTransactionListModel
@ -13,6 +18,7 @@ import com.tangem.utils.converter.Converter
internal class SavedSwapTransactionListConverter(
private val responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory,
private val networkFactory: NetworkFactory,
) : Converter<SwapTransactionListModel, SwapTransactionListDTO> {
private val userTokensResponseFactory = UserTokensResponseFactory()
@ -45,13 +51,17 @@ internal class SavedSwapTransactionListConverter(
return if (fromToken == null || toToken == null) {
null
} else {
val fromNetwork = createSwapTransactionNetwork(fromToken, userWallet) ?: return null
val fromCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency(
responseToken = fromToken,
userWallet = userWallet,
network = fromNetwork,
) ?: return null
val toNetwork = createSwapTransactionNetwork(fromToken, userWallet) ?: return null
val toCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency(
responseToken = toToken,
userWallet = userWallet,
network = toNetwork,
) ?: return null
return SwapTransactionListModel(
@ -83,4 +93,22 @@ internal class SavedSwapTransactionListConverter(
toTokensResponse = userTokensResponseFactory.createResponseToken(currency = toCryptoCurrency, accountId = null),
transactions = tokenTransactions,
)
private fun createSwapTransactionNetwork(token: UserTokensResponse.Token, userWallet: UserWallet): Network? {
val blockchain = Blockchain.fromNetworkId(token.networkId) ?: return null
return if (token.derivationPath == null) {
networkFactory.create(
blockchain = blockchain,
derivationPath = Network.DerivationPath.None,
userWallet = userWallet,
)
} else {
networkFactory.create(
blockchain = blockchain,
extraDerivationPath = token.derivationPath,
userWallet = userWallet,
)
}
}
}

View file

@ -2,6 +2,7 @@ package com.tangem.data.swap.di
import com.squareup.moshi.Moshi
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
import com.tangem.data.common.network.NetworkFactory
import com.tangem.data.express.converter.ExpressErrorConverter
import com.tangem.data.swap.DefaultSwapErrorResolver
import com.tangem.data.swap.DefaultSwapRepositoryV2
@ -66,11 +67,13 @@ internal object SwapDataModule {
fun provideSwapTransactionRepository(
appPreferencesStore: AppPreferencesStore,
responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory,
networkFactory: NetworkFactory,
dispatchers: CoroutineDispatcherProvider,
): SwapTransactionRepository {
return DefaultSwapTransactionRepository(
appPreferencesStore = appPreferencesStore,
responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory,
networkFactory = networkFactory,
dispatchers = dispatchers,
)
}

View file

@ -5,12 +5,12 @@ import com.tangem.blockchain.yieldsupply.YieldSupplyProvider
import com.tangem.blockchainsdk.utils.fromNetworkId
import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.blockchainsdk.utils.toNetworkId
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
import com.tangem.data.yield.supply.converters.YieldMarketTokenConverter
import com.tangem.datasource.api.tangemTech.YieldSupplyApi
import com.tangem.data.yield.supply.converters.YieldTokenChartConverter
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.tangemTech.YieldSupplyApi
import com.tangem.datasource.api.tangemTech.models.YieldSupplyChangeTokenStatusBody
import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.walletmanager.WalletManagersFacade
@ -23,7 +23,6 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import java.util.concurrent.ConcurrentHashMap
import kotlin.collections.map
internal class DefaultYieldSupplyRepository(
private val yieldSupplyApi: YieldSupplyApi,
@ -77,7 +76,7 @@ internal class DefaultYieldSupplyRepository(
(walletManager as? YieldSupplyProvider)?.isSupported() ?: false
}
override suspend fun activateProtocol(cryptoCurrencyToken: CryptoCurrency.Token): Boolean =
override suspend fun activateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean =
withContext(dispatchers.io) {
val chainId = Blockchain.fromNetworkId(cryptoCurrencyToken.network.backendId)?.getChainId()
?: error("Chain id is required for evm's")
@ -85,11 +84,12 @@ internal class DefaultYieldSupplyRepository(
YieldSupplyChangeTokenStatusBody(
tokenAddress = cryptoCurrencyToken.contractAddress,
chainId = chainId,
userAddress = address,
),
).getOrThrow().isActive
}
override suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token): Boolean =
override suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean =
withContext(dispatchers.io) {
val chainId = Blockchain.fromNetworkId(cryptoCurrencyToken.network.backendId)?.getChainId()
?: error("Chain id is required for evm's")
@ -97,6 +97,7 @@ internal class DefaultYieldSupplyRepository(
YieldSupplyChangeTokenStatusBody(
tokenAddress = cryptoCurrencyToken.contractAddress,
chainId = chainId,
userAddress = address,
),
).getOrThrow().isActive
}
@ -108,8 +109,8 @@ internal class DefaultYieldSupplyRepository(
statusMap[cryptoCurrency.id.value] = yieldSupplyEnterStatus
}
override fun getTokenProtocolStatus(cryptoCurrencyToken: CryptoCurrency): YieldSupplyEnterStatus? {
return statusMap[cryptoCurrencyToken.id.value]
override fun getTokenProtocolStatus(cryptoCurrency: CryptoCurrency): YieldSupplyEnterStatus? {
return statusMap[cryptoCurrency.id.value]
}
private fun List<YieldMarketToken>.enrichNetworkIds(): List<YieldMarketToken> {

View file

@ -201,5 +201,35 @@
"info": "stakeBSC",
"source": "https://bscscan.com/tx/0xfcbeac6e0a4ba5768d97d14b5115d08dda92defa8a8deee8bba34e2f0655c52b",
"name": "claim"
},
"0xcbeda14c": {
"info": "yieldModule",
"source": "https://github.com/tangem/tangem-yield-module-contracts/",
"name": "supply"
},
"0x79be55f7": {
"info": "yieldModule",
"source": "https://github.com/tangem/tangem-yield-module-contracts/",
"name": "supply"
},
"0xc65e6dcf": {
"info": "yieldModule",
"source": "https://github.com/tangem/tangem-yield-module-contracts/",
"name": "supply"
},
"0xebd4b81c": {
"info": "yieldModule",
"source": "https://github.com/tangem/tangem-yield-module-contracts/",
"name": "supply"
},
"0xc478e956": {
"info": "yieldModule",
"source": "https://github.com/tangem/tangem-yield-module-contracts/",
"name": "supply"
},
"0x0779afe6": {
"info": "yieldModule",
"source": "https://github.com/tangem/tangem-yield-module-contracts/",
"name": "transfer"
}
}

View file

@ -1,37 +1,42 @@
package com.tangem.domain.staking.usecase
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.toNetworkId
import com.tangem.domain.staking.model.StakingIntegrationID
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.staking.repositories.StakingRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import java.math.BigDecimal
/**
* Emits a map of APY values per currency for staking.
* Emits a map of Validators values per currency for staking.
*
* Return map:
* - key: currency staking key (network.backendId + "_" + symbol)
* - value: APY as string
* - value: validators
*/
class StakingApyFlowUseCase(private val stakingRepository: StakingRepository) {
operator fun invoke(): Flow<Map<String, BigDecimal>> {
operator fun invoke(): Flow<Map<String, List<Yield.Validator>>> {
return stakingRepository.getEnabledYields()
.map { yields ->
yields.associate { yield ->
val key = "${yield.token.coinGeckoId}_${yield.token.symbol}"
val apy = calculateApy(yield)
val key = composeKey(yield)
val apy = yield.validators
key to apy
}
}
}
private fun calculateApy(yield: Yield): BigDecimal {
val rates = yield.validators.mapNotNull { it.rewardInfo?.rate }
return if (rates.isNotEmpty()) {
rates.maxOf { it }
// so that cause for api.stakek.it coinGeckoId on BNB Smart chain different how we receive our backendId
// coinGeckoId - binance
// our backendId BNB Smart Chain - binance-smart-chain
// our backendId BNB Beacon Chain - binance
private fun composeKey(yield: Yield): String {
return if (yield.token.symbol == StakingIntegrationID.Coin.BSC.blockchain.currency) {
"${Blockchain.BSC.toNetworkId()}_${yield.token.symbol}"
} else {
yield.apy
"${yield.token.coinGeckoId}_${yield.token.symbol}"
}
}
}

View file

@ -44,16 +44,9 @@ interface SwapTransactionRepository {
* Remove stores swap transaction
*
* @param userWalletId selected user wallet id
* @param fromCryptoCurrency currency swap from
* @param toCryptoCurrency currency swap to
* @param txId transaction id to remove
*/
suspend fun removeTransaction(
userWalletId: UserWalletId,
fromCryptoCurrency: CryptoCurrency,
toCryptoCurrency: CryptoCurrency,
txId: String,
)
suspend fun removeTransaction(userWalletId: UserWalletId, txId: String)
/**
* Update swap transaction

View file

@ -46,7 +46,7 @@ interface YieldSupplyRepository {
* May throw on network/backend errors or if required chain id cannot be resolved.
*/
@Throws
suspend fun activateProtocol(cryptoCurrencyToken: CryptoCurrency.Token): Boolean
suspend fun activateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean
/**
* Deactivate yield protocol for the specified token.
@ -56,7 +56,7 @@ interface YieldSupplyRepository {
* network/backend errors or if required chain id cannot be resolved.
*/
@Throws
suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token): Boolean
suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean
/**
* Save the last user-initiated yield protocol action for the given currency.
@ -65,13 +65,10 @@ interface YieldSupplyRepository {
* for the definitive protocol status to be fetched from the network. This information
* is transient and not intended to be persisted across app restarts.
*
* @param cryptoCurrencyToken the currency or token the action relates to
* @param cryptoCurrency the currency or token the action relates to
* @param yieldSupplyEnterStatus the last action intent: [YieldSupplyEnterStatus.Enter] or [YieldSupplyEnterStatus.Exit]
*/
suspend fun saveTokenProtocolStatus(
cryptoCurrencyToken: CryptoCurrency,
yieldSupplyEnterStatus: YieldSupplyEnterStatus,
)
suspend fun saveTokenProtocolStatus(cryptoCurrency: CryptoCurrency, yieldSupplyEnterStatus: YieldSupplyEnterStatus)
/**
* Get the last saved user-initiated yield protocol action for the given currency, if any.
@ -79,8 +76,8 @@ interface YieldSupplyRepository {
* Used to determine whether the UI should display an intermediate "processing" state
* until the protocol status retrieved from backend reflects the change.
*
* @param cryptoCurrencyToken the currency or token to query
* @param cryptoCurrency the currency or token to query
* @return the last action intent or null if nothing has been recorded
*/
fun getTokenProtocolStatus(cryptoCurrencyToken: CryptoCurrency): YieldSupplyEnterStatus?
fun getTokenProtocolStatus(cryptoCurrency: CryptoCurrency): YieldSupplyEnterStatus?
}

View file

@ -8,8 +8,9 @@ class YieldSupplyActivateUseCase(
private val yieldSupplyRepository: YieldSupplyRepository,
) {
suspend operator fun invoke(cryptoCurrency: CryptoCurrency): Either<Throwable, Boolean> = Either.catch {
val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected")
yieldSupplyRepository.activateProtocol(token)
}
suspend operator fun invoke(cryptoCurrency: CryptoCurrency, address: String): Either<Throwable, Boolean> =
Either.catch {
val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected")
yieldSupplyRepository.activateProtocol(token, address)
}
}

View file

@ -8,8 +8,9 @@ class YieldSupplyDeactivateUseCase(
private val yieldSupplyRepository: YieldSupplyRepository,
) {
suspend operator fun invoke(cryptoCurrency: CryptoCurrency): Either<Throwable, Boolean> = Either.catch {
val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected")
yieldSupplyRepository.deactivateProtocol(token)
}
suspend operator fun invoke(cryptoCurrency: CryptoCurrency, address: String): Either<Throwable, Boolean> =
Either.catch {
val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected")
yieldSupplyRepository.deactivateProtocol(token, address)
}
}

View file

@ -43,12 +43,18 @@ internal fun StoriesScreen(
var currentStory by remember { mutableStateOf(state.firstStory) }
val currentStoryIndex by rememberUpdatedState(newValue = state.stepOf(currentStory))
LaunchedEffect(currentStoryIndex) {
if (currentStoryIndex < 0) {
currentStory = state.firstStory
}
}
val goToPreviousStory = remember(currentStory, currentStoryIndex) {
{ currentStory = state.stories[max(0, currentStoryIndex - 1)] }
}
val goToNextStory = remember(currentStory, currentStoryIndex) {
{
currentStory = if (currentStoryIndex < state.stories.lastIndex) {
currentStory = if (currentStoryIndex >= 0 && currentStoryIndex < state.stories.lastIndex) {
state.stories[currentStoryIndex + 1]
} else {
state.firstStory

View file

@ -33,12 +33,18 @@ internal fun StoriesScreenV2(state: HomeUM, onGetStartedClick: () -> Unit, modif
var currentStory by remember { mutableStateOf(state.firstStory) }
val currentStoryIndex by rememberUpdatedState(newValue = state.stepOf(currentStory))
LaunchedEffect(currentStoryIndex) {
if (currentStoryIndex < 0) {
currentStory = state.firstStory
}
}
val goToPreviousStory = remember(currentStory, currentStoryIndex) {
{ currentStory = state.stories[max(0, currentStoryIndex - 1)] }
}
val goToNextStory = remember(currentStory, currentStoryIndex) {
{
currentStory = if (currentStoryIndex < state.stories.lastIndex) {
currentStory = if (currentStoryIndex >= 0 && currentStoryIndex < state.stories.lastIndex) {
state.stories[currentStoryIndex + 1]
} else {
state.firstStory

View file

@ -85,7 +85,7 @@ fun StoriesProgressBar(
.let {
when (index) {
currentStep -> it.fillMaxWidth(progress.value)
in 0..currentStep -> it.fillMaxWidth(fraction = 1f)
in 0 until currentStep -> it.fillMaxWidth(fraction = 1f)
else -> it
}
},

View file

@ -179,9 +179,9 @@ internal class ReferralModel @Inject constructor(
showErrorSnackbar(DemoModeException())
} else {
analyticsEventHandler.send(ReferralEvents.ClickParticipate)
val lastInfoState = uiState.referralInfoState
uiState = uiState.copy(referralInfoState = ReferralInfoState.Loading)
modelScope.launch {
val lastInfoState = uiState.referralInfoState
val portfolioId = when (accountsFeatureToggles.isFeatureEnabled) {
true -> PortfolioId(requireNotNull(portfolioSelectorController.selectedAccountSync))
false -> PortfolioId(params.userWalletId)

View file

@ -39,9 +39,11 @@ fun SendAmountContent(
amountState = amountState,
clickIntents = clickIntents,
extraContent = {
SendConvertTokenButton(
onConvertToAnother = clickIntents::onConvertToAnotherToken,
).takeIf { isSendWithSwapAvailable }
if (isSendWithSwapAvailable) {
SendConvertTokenButton(
onConvertToAnother = clickIntents::onConvertToAnotherToken,
)
}
},
)
SpacerH(16.dp)

View file

@ -272,6 +272,7 @@ internal class NotificationsModel @Inject constructor(
reserveAmount = currencyCheck.reserveAmount,
sendingAmount = sendingAmount,
cryptoCurrency = currency,
feeCryptoCurrency = feeCryptoCurrencyStatus.currency,
isAccountFunded = currencyCheck.isAccountFunded,
)
addMinimumAmountErrorNotification(

View file

@ -41,8 +41,9 @@ internal class StakingStateRouter(
StakingStep.Validators,
StakingStep.Amount,
-> showConfirmation()
StakingStep.Confirmation -> showInitial()
StakingStep.Success -> appRouter.pop()
StakingStep.Confirmation,
StakingStep.Success,
-> showInitial()
}
}

View file

@ -139,7 +139,7 @@ internal class SetButtonsStateTransformer(
StakingStep.Amount -> clickIntents.onAmountEnterClick()
StakingStep.Confirmation -> onConfirmationClick()
StakingStep.RewardsValidators -> Unit
StakingStep.Success -> clickIntents.onBackClick()
StakingStep.Success -> clickIntents.onNextClick()
}
}

View file

@ -214,6 +214,7 @@ internal class AddStakingNotificationsTransformer(
reserveAmount = currencyCheck.reserveAmount,
sendingAmount = sendingAmount,
cryptoCurrency = cryptoCurrency,
feeCryptoCurrency = feeCryptoCurrencyStatus?.currency,
isAccountFunded = false,
)
}

View file

@ -2,6 +2,7 @@ package com.tangem.feature.swap
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
import com.tangem.data.common.currency.UserTokensResponseFactory
import com.tangem.data.common.network.NetworkFactory
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.getObjectList
@ -24,10 +25,14 @@ internal class DefaultSwapTransactionRepository(
private val appPreferencesStore: AppPreferencesStore,
private val dispatchers: CoroutineDispatcherProvider,
responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory,
networkFactory: NetworkFactory,
) : SwapTransactionRepository {
private val converter by lazy(LazyThreadSafetyMode.NONE) {
SavedSwapTransactionListConverter(responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory)
SavedSwapTransactionListConverter(
responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory,
networkFactory = networkFactory,
)
}
private val userTokensResponseFactory = UserTokensResponseFactory()
@ -128,52 +133,25 @@ internal class DefaultSwapTransactionRepository(
.flowOn(dispatchers.default)
}
override suspend fun removeTransaction(
userWalletId: UserWalletId,
fromCryptoCurrency: CryptoCurrency,
toCryptoCurrency: CryptoCurrency,
txId: String,
) {
override suspend fun removeTransaction(userWalletId: UserWalletId, txId: String) {
clearTransactionsStatuses(txId = txId)
appPreferencesStore.editData { mutablePreferences ->
val savedList: List<SavedSwapTransactionListModelInner>? = mutablePreferences.getObjectList(
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
)
val tokenTransactions = savedList
?.firstOrNull {
it.checkId(
checkUserWalletId = userWalletId,
fromCurrencyId = fromCryptoCurrency.id,
toCurrencyId = toCryptoCurrency.id,
)
}
?.transactions
?.filterNot { it.txId == txId }
?.asSequence()
?.map {
it.copy(transactions = it.transactions.filterNot { it.txId == txId })
}?.filterNot { it.transactions.isEmpty() }
?.toList()
val editedList =
if (tokenTransactions.isNullOrEmpty()) {
savedList?.filterNot {
it.checkId(
checkUserWalletId = userWalletId,
fromCurrencyId = fromCryptoCurrency.id,
toCurrencyId = toCryptoCurrency.id,
)
}
} else {
savedList.updateList(
userWalletId = userWalletId,
fromCryptoCurrency = fromCryptoCurrency,
toCryptoCurrency = toCryptoCurrency,
transactions = tokenTransactions,
)
}
if (editedList.isNullOrEmpty()) {
if (tokenTransactions.isNullOrEmpty()) {
mutablePreferences.remove(key = PreferencesKeys.SWAP_TRANSACTIONS_KEY)
} else {
mutablePreferences.setObject(
key = PreferencesKeys.SWAP_TRANSACTIONS_KEY,
value = editedList,
value = tokenTransactions,
)
}
}

View file

@ -1,8 +1,13 @@
package com.tangem.feature.swap.converters
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.fromNetworkId
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
import com.tangem.data.common.currency.UserTokensResponseFactory
import com.tangem.data.common.network.NetworkFactory
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.swap.domain.models.domain.ExchangeStatusModel
@ -13,6 +18,7 @@ import com.tangem.utils.converter.Converter
internal class SavedSwapTransactionListConverter(
private val responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory,
private val networkFactory: NetworkFactory,
) : Converter<SavedSwapTransactionListModel, SavedSwapTransactionListModelInner> {
private val userTokensResponseFactory = UserTokensResponseFactory()
@ -43,13 +49,17 @@ internal class SavedSwapTransactionListConverter(
return if (fromToken == null || toToken == null) {
null
} else {
val fromNetwork = createSwapTransactionNetwork(fromToken, userWallet) ?: return null
val fromCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency(
responseToken = fromToken,
userWallet = userWallet,
network = fromNetwork,
) ?: return null
val toNetwork = createSwapTransactionNetwork(fromToken, userWallet) ?: return null
val toCryptoCurrency = responseCryptoCurrenciesFactory.createCurrency(
responseToken = toToken,
userWallet = userWallet,
network = toNetwork,
) ?: return null
return SavedSwapTransactionListModel(
@ -91,4 +101,22 @@ internal class SavedSwapTransactionListConverter(
toTokensResponse = userTokensResponseFactory.createResponseToken(currency = toCryptoCurrency, accountId = null),
transactions = tokenTransactions,
)
private fun createSwapTransactionNetwork(token: UserTokensResponse.Token, userWallet: UserWallet): Network? {
val blockchain = Blockchain.fromNetworkId(token.networkId) ?: return null
return if (token.derivationPath == null) {
networkFactory.create(
blockchain = blockchain,
derivationPath = Network.DerivationPath.None,
userWallet = userWallet,
)
} else {
networkFactory.create(
blockchain = blockchain,
extraDerivationPath = token.derivationPath,
userWallet = userWallet,
)
}
}
}

View file

@ -3,6 +3,7 @@ package com.tangem.feature.swap.di
import com.squareup.moshi.Moshi
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
import com.tangem.data.common.network.NetworkFactory
import com.tangem.datasource.api.express.TangemExpressApi
import com.tangem.datasource.api.express.models.response.ExpressErrorResponse
import com.tangem.datasource.crypto.DataSignatureVerifier
@ -60,11 +61,13 @@ internal class SwapDataModule {
fun provideSwapTransactionRepository(
appPreferencesStore: AppPreferencesStore,
responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory,
networkFactory: NetworkFactory,
dispatcherProvider: CoroutineDispatcherProvider,
): SwapTransactionRepository {
return DefaultSwapTransactionRepository(
appPreferencesStore = appPreferencesStore,
responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory,
networkFactory = networkFactory,
dispatchers = dispatcherProvider,
)
}

View file

@ -23,12 +23,7 @@ interface SwapTransactionRepository {
cryptoCurrencyId: CryptoCurrency.ID,
): Flow<List<SavedSwapTransactionListModel>?>
suspend fun removeTransaction(
userWalletId: UserWalletId,
fromCryptoCurrency: CryptoCurrency,
toCryptoCurrency: CryptoCurrency,
txId: String,
)
suspend fun removeTransaction(userWalletId: UserWalletId, txId: String)
suspend fun storeTransactionState(
txId: String,

View file

@ -192,6 +192,7 @@ internal class SwapNotificationsFactory(
reserveAmount = quoteModel.currencyCheck?.reserveAmount,
sendingAmount = amountToRequest.value,
cryptoCurrency = fromCurrencyStatus.currency,
feeCryptoCurrency = feeCryptoCurrencyStatus?.currency,
isAccountFunded = false,
)
addReduceAmountNotification(

View file

@ -88,8 +88,6 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
if (shouldDispose) {
swapTransactionRepository.removeTransaction(
userWalletId = userWallet.walletId,
fromCryptoCurrency = selectedTx.fromCryptoCurrency,
toCryptoCurrency = selectedTx.toCryptoCurrency,
txId = selectedTx.info.txId,
)
}

View file

@ -63,9 +63,8 @@ internal class TxHistoryItemToTransactionStateConverter(
is TxInfo.TransactionType.Approve -> resourceReference(R.string.common_approval)
is TxInfo.TransactionType.Operation -> stringReference(type.name)
is TxInfo.TransactionType.Swap -> resourceReference(R.string.common_swap)
is TxInfo.TransactionType.YieldSupply,
is TxInfo.TransactionType.Transfer,
-> resourceReference(R.string.common_transfer)
is TxInfo.TransactionType.Transfer -> resourceReference(R.string.common_transfer)
is TxInfo.TransactionType.YieldSupply -> resourceReference(R.string.yield_module_supply)
is TxInfo.TransactionType.Staking.Stake -> resourceReference(R.string.common_stake)
is TxInfo.TransactionType.Staking.Unstake -> resourceReference(R.string.common_unstake)
is TxInfo.TransactionType.Staking.Vote -> resourceReference(R.string.staking_vote)

View file

@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
@ -10,7 +11,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.converte
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TokenListStateConverter
import com.tangem.feature.wallet.presentation.wallet.state.utils.enableButtons
import timber.log.Timber
import java.math.BigDecimal
internal class SetTokenListTransformer(
private val params: TokenConverterParams,
@ -18,7 +18,7 @@ internal class SetTokenListTransformer(
private val appCurrency: AppCurrency,
private val clickIntents: WalletClickIntents,
private val yieldSupplyApyMap: Map<String, String> = emptyMap(),
private val stakingApyMap: Map<String, BigDecimal> = emptyMap(),
private val stakingApyMap: Map<String, List<Yield.Validator>> = emptyMap(),
) : WalletStateTransformer(userWallet.walletId) {
override fun transform(prevState: WalletState): WalletState {

View file

@ -17,6 +17,7 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.tokenlist.TokenList
import com.tangem.domain.models.tokenlist.TokenList.GroupedByNetwork.NetworkGroup
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState
@ -27,7 +28,6 @@ import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.mutate
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
import java.math.BigDecimal
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState.OrganizeTokensButtonConfig as WalletOrganizeTokensButtonConfig
internal class TokenListStateConverter(
@ -36,7 +36,7 @@ internal class TokenListStateConverter(
private val selectedWallet: UserWallet,
private val clickIntents: WalletClickIntents,
private val yieldModuleApyMap: Map<String, String>,
private val stakingApyMap: Map<String, BigDecimal>,
private val stakingApyMap: Map<String, List<Yield.Validator>>,
) : Converter<WalletTokensListState, WalletTokensListState> {
private val onTokenClick: (accountId: AccountId?, currencyStatus: CryptoCurrencyStatus) -> Unit =

View file

@ -71,9 +71,8 @@ internal class TxHistoryItemStateConverter(
is TransactionType.Approve -> resourceReference(R.string.common_approval)
is TransactionType.Operation -> stringReference(type.name)
is TransactionType.Swap -> resourceReference(R.string.common_swap)
is TransactionType.YieldSupply,
is TransactionType.Transfer,
-> resourceReference(R.string.common_transfer)
is TransactionType.Transfer -> resourceReference(R.string.common_transfer)
is TransactionType.YieldSupply -> resourceReference(R.string.yield_module_supply)
is TransactionType.Staking.Stake -> resourceReference(R.string.common_stake)
is TransactionType.Staking.Unstake -> resourceReference(R.string.common_unstake)
is TransactionType.Staking.Vote -> resourceReference(R.string.staking_vote)

View file

@ -13,6 +13,7 @@ import com.tangem.domain.models.account.AccountStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.tokenlist.TokenList
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
@ -33,7 +34,6 @@ import kotlinx.coroutines.flow.*
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import timber.log.Timber
import java.math.BigDecimal
@Suppress("LongParameterList")
internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
@ -103,7 +103,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
appCurrency: AppCurrency,
portfolioId: PortfolioId,
yieldSupplyApyMap: Map<String, String>,
stakingApyMap: Map<String, BigDecimal>,
stakingApyMap: Map<String, List<Yield.Validator>>,
) {
val tokenList = maybeTokenList.getOrElse(
ifLoading = { maybeContent ->
@ -242,7 +242,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
params: TokenConverterParams,
appCurrency: AppCurrency,
yieldSupplyApyMap: Map<String, String>,
stakingApyMap: Map<String, BigDecimal>,
stakingApyMap: Map<String, List<Yield.Validator>>,
) {
stateHolder.update(
SetTokenListTransformer(
@ -268,6 +268,6 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
private fun yieldSupplyApyFlow(): Flow<Map<String, String>> = yieldSupplyApyFlowUseCase()
.distinctUntilChanged()
private fun stakingApyFlow(): Flow<Map<String, BigDecimal>> = stakingApyFlowUseCase()
private fun stakingApyFlow(): Flow<Map<String, List<Yield.Validator>>> = stakingApyFlowUseCase()
.distinctUntilChanged()
}

View file

@ -10,6 +10,7 @@ internal sealed class YieldSupplyUM {
data class Available(
val apy: String,
val apyText: TextReference,
val title: TextReference,
val onClick: () -> Unit,
) : YieldSupplyUM()

View file

@ -13,6 +13,7 @@ import com.tangem.core.ui.extensions.combinedReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.models.StatusSource
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.currency.yieldSupplyNotAllAmountSupplied
@ -27,19 +28,21 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyActivateUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyIsAvailableUseCase
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.api.YieldSupplyComponent
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
import com.tangem.features.yield.supply.impl.main.model.transformers.YieldSupplyTokenStatusSuccessTransformer
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.DelayedWork
import com.tangem.utils.transformer.update
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import com.tangem.utils.transformer.update
import javax.inject.Inject
import kotlin.properties.Delegates
@ -84,6 +87,7 @@ internal class YieldSupplyModel @Inject constructor(
field = MutableStateFlow(false)
private var lastYieldSupplyStatus: YieldSupplyStatus? = null
private val fetchCurrencyJobHolder = JobHolder()
init {
checkIfYieldSupplyIsAvailable()
@ -183,6 +187,19 @@ internal class YieldSupplyModel @Inject constructor(
val yieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus
val tokenProtocolStatus = yieldSupplyRepository.getTokenProtocolStatus(cryptoCurrency)
val isActive = yieldSupplyStatus?.isActive == true
val isCryptoCurrencyStatusFromCache = cryptoCurrencyStatus.value.sources.networkSource != StatusSource.ACTUAL
val processing = uiState.value is YieldSupplyUM.Processing
Timber.d(
"currentUiState ${uiState.value.javaClass} \n" +
"yieldSupplyStatus $yieldSupplyStatus" +
"tokenProtocolStatus $tokenProtocolStatus " +
"isActive $isActive " +
"processing $processing " +
"isCryptoCurrencyStatusFromCache $isCryptoCurrencyStatusFromCache",
)
if (isCryptoCurrencyStatusFromCache && processing) {
return
}
when {
!isActive && tokenProtocolStatus == YieldSupplyEnterStatus.Enter -> {
@ -215,8 +232,10 @@ internal class YieldSupplyModel @Inject constructor(
userWalletId = userWallet.walletId,
network = cryptoCurrency.network,
),
)
}
).onLeft {
fetchCurrencyWithDelay()
}
}.saveIn(fetchCurrencyJobHolder)
}
private fun loadActiveState(cryptoCurrencyStatus: CryptoCurrencyStatus, yieldSupplyStatus: YieldSupplyStatus) {
@ -276,13 +295,14 @@ internal class YieldSupplyModel @Inject constructor(
private fun sendInfoAboutProtocolStatus(cryptoCurrencyStatus: CryptoCurrencyStatus) {
if (lastYieldSupplyStatus == cryptoCurrencyStatus.value.yieldSupplyStatus) return
val token = cryptoCurrency as? CryptoCurrency.Token ?: return
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value ?: return
modelScope.launch(dispatchers.default) {
if (cryptoCurrencyStatus.value.yieldSupplyStatus?.isActive == true) {
yieldSupplyActivateUseCase(token).onRight {
yieldSupplyActivateUseCase(token, address).onRight {
lastYieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus
}
} else {
yieldSupplyDeactivateUseCase(token).onRight {
yieldSupplyDeactivateUseCase(token, address).onRight {
lastYieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus
}
}

View file

@ -1,10 +1,11 @@
package com.tangem.features.yield.supply.impl.main.model.transformers
import com.tangem.core.ui.extensions.combinedReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.yield.supply.models.YieldMarketToken
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.yield.supply.models.YieldMarketToken
import com.tangem.utils.transformer.Transformer
internal class YieldSupplyTokenStatusSuccessTransformer(
@ -17,11 +18,16 @@ internal class YieldSupplyTokenStatusSuccessTransformer(
return YieldSupplyUM.Available(
title = resourceReference(
id = R.string.yield_module_token_details_earn_notification_title,
formatArgs = wrappedList(tokenStatus.apy),
R.string.yield_module_token_details_earn_notification_earning_on_your_balance_title,
),
onClick = onStartEarningClick,
apy = tokenStatus.apy.toString(),
apyText = combinedReference(
resourceReference(
R.string.yield_module_token_details_earn_notification_apy,
),
stringReference(" ${tokenStatus.apy}%"),
),
)
}
}

View file

@ -62,8 +62,9 @@ internal fun YieldSupplyBlockContent(yieldSupplyUM: YieldSupplyUM, modifier: Mod
@Composable
private fun SupplyAvailable(supplyUM: YieldSupplyUM.Available, modifier: Modifier = Modifier) {
SupplyInfo(
title = supplyUM.title,
title = resourceReference(R.string.yield_module_token_details_earn_notification_earning_on_your_balance_title),
subtitle = resourceReference(R.string.yield_module_token_details_earn_notification_description),
rewardsApy = supplyUM.apyText,
iconTint = TangemTheme.colors.icon.accent,
modifier = modifier,
button = {
@ -82,6 +83,7 @@ private fun SupplyUnavailable(modifier: Modifier = Modifier) {
SupplyInfo(
title = resourceReference(R.string.yield_module_unavailable_title),
subtitle = resourceReference(R.string.yield_module_unavailable_subtitle),
rewardsApy = null,
iconTint = TangemTheme.colors.icon.inactive,
button = null,
modifier = modifier,
@ -249,6 +251,7 @@ private fun SupplyLoading(modifier: Modifier = Modifier) {
private fun SupplyInfo(
title: TextReference,
subtitle: TextReference,
rewardsApy: TextReference?,
iconTint: Color,
modifier: Modifier = Modifier,
button: (@Composable () -> Unit)? = null,
@ -264,6 +267,7 @@ private fun SupplyInfo(
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_analytics_up_24),
@ -277,11 +281,28 @@ private fun SupplyInfo(
Column(
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.button,
color = TangemTheme.colors.text.primary1,
)
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
)
if (rewardsApy != null) {
Text(
text = StringsSigns.DOT,
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
)
Text(
text = rewardsApy.resolveReference(),
style = TangemTheme.typography.subtitle2,
maxLines = 1,
color = TangemTheme.colors.text.accent,
)
}
}
Text(
text = subtitle.resolveReference(),
style = TangemTheme.typography.caption2,
@ -312,6 +333,7 @@ private class PreviewProvider : PreviewParameterProvider<YieldSupplyUM> {
wrappedList("5.1"),
),
apy = "5.1",
apyText = stringReference("5.1 % APY"),
onClick = {},
),
YieldSupplyUM.Content(

View file

@ -22,13 +22,9 @@ import com.tangem.domain.transaction.usecase.SendTransactionUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.yield.supply.YieldSupplyRepository
import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus
import com.tangem.domain.yield.supply.usecase.YieldSupplyActivateUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyEstimateEnterFeeUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyStartEarningUseCase
import com.tangem.features.yield.supply.impl.R
import com.tangem.domain.yield.supply.usecase.*
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM
@ -234,10 +230,12 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
ifLeft = { error ->
Timber.e(error.toString())
uiState.update(YieldSupplyTransactionReadyTransformer)
analytics.send(YieldSupplyAnalytics.EarnErrors(
action = YieldSupplyAnalytics.Action.Approve,
errorDescription = error.getAnalyticsDescription(),
))
analytics.send(
YieldSupplyAnalytics.EarnErrors(
action = YieldSupplyAnalytics.Action.Approve,
errorDescription = error.getAnalyticsDescription(),
),
)
yieldSupplyAlertFactory.getSendTransactionErrorState(
error = error,
popBack = params.callback::onBackClick,
@ -255,7 +253,12 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
ifRight = {
yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Enter)
analytics.send(YieldSupplyAnalytics.FundsEarned)
yieldSupplyActivateUseCase(cryptoCurrency)
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
if (address != null) {
yieldSupplyActivateUseCase(cryptoCurrency, address)
}
modelScope.launch {
params.callback.onTransactionSent()
}

View file

@ -42,10 +42,13 @@ internal class YieldSupplyStartEarningFeeContentTransformer(
val tokenFiatFee = feeFiat // same fiat amount
val tokenFiatFeeValueText = tokenFiatFee.format { fiat(appCurrency.code, appCurrency.symbol) }
val maxFeeCryptoValueText = maxNetworkFee.format { crypto(cryptoCurrency) }
val maxFiatFee = tokenFiatRate?.let { rate ->
val maxFiatFee = feeFiatRate?.let { rate ->
maxNetworkFee.multiply(rate)
}
val maxFeeCryptoValueText = tokenFiatRate?.let { rate ->
maxFiatFee?.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP)
}.format { crypto(cryptoCurrency) }
val maxFiatFeeValueText = maxFiatFee.format { fiat(appCurrency.code, appCurrency.symbol) }
val minAmountCryptoText = minAmount.format { crypto(cryptoCurrency) }

View file

@ -20,8 +20,8 @@ import com.tangem.domain.yield.supply.YieldSupplyRepository
import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus
import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyStopEarningUseCase
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM
@ -140,10 +140,12 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
ifLeft = { error ->
Timber.e(error.toString())
uiState.update(YieldSupplyTransactionReadyTransformer)
analytics.send(YieldSupplyAnalytics.EarnErrors(
action = YieldSupplyAnalytics.Action.Stop,
errorDescription = error.getAnalyticsDescription(),
))
analytics.send(
YieldSupplyAnalytics.EarnErrors(
action = YieldSupplyAnalytics.Action.Stop,
errorDescription = error.getAnalyticsDescription(),
),
)
yieldSupplyAlertFactory.getSendTransactionErrorState(
error = error,
popBack = params.callback::onBackClick,
@ -166,7 +168,11 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
blockchain = cryptoCurrency.network.name,
),
)
yieldSupplyDeactivateUseCase(cryptoCurrency)
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
if (address != null) {
yieldSupplyDeactivateUseCase(cryptoCurrency, address)
}
modelScope.launch {
params.callback.onTransactionSent()
}

View file

@ -5,7 +5,7 @@
# https://github.com/tangem/tangem-sdk-android/
# https://github.com/tangem/vico
tangemBlockchainSdk = "develop-1287"
tangemBlockchainSdk = "develop-1294"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "develop-564"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^