diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index 7b792e100c..16c0de5855 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit 7b792e100c14f64d3e44306c3a9b25a25d0cfc03 +Subproject commit 16c0de5855d0a75e285a9c84e616dd020f7da4d1 diff --git a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt index 362f8ad5a4..404a8fcf28 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt @@ -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) }, ), ) diff --git a/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt b/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt index 31d7fecf65..273839cc0e 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt @@ -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 = emptyMap(), - private val stakingApyMap: Map = emptyMap(), + private val stakingApyMap: Map> = emptyMap(), private val iconStateProvider: (CryptoCurrencyStatus) -> CurrencyIconState = { CryptoCurrencyToIconStateConverter().convert(it) }, @@ -156,7 +157,7 @@ class TokenItemStateConverter( private fun createTitleState( currencyStatus: CryptoCurrencyStatus, yieldModuleApyMap: Map, - stakingApyMap: Map, + stakingApyMap: Map>, ): TokenItemState.TitleState { return when (val value = currencyStatus.value) { is CryptoCurrencyStatus.Loading, @@ -190,7 +191,7 @@ class TokenItemStateConverter( private fun resolveEarnApy( cryptoCurrencyStatus: CryptoCurrencyStatus, yieldModuleApyMap: Map, - stakingApyMap: Map, + stakingApyMap: Map>, ): Pair { 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>, + ): Pair { + 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, diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldSupplyChangeTokenStatusBody.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldSupplyChangeTokenStatusBody.kt index 68db0ea530..841ecd9c81 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldSupplyChangeTokenStatusBody.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/YieldSupplyChangeTokenStatusBody.kt @@ -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, ) \ No newline at end of file diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index d03a24ea12..6960013a5c 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -337,7 +337,7 @@ Transaktion fehlgeschlagen Transaktionsstatus Transaktionen - Überweisung + Überweiseung Die Daten konnten nicht geladen werden… Ich verstehe Es ist ein Fehler aufgetreten. Bitte versuche es erneut. @@ -1708,7 +1708,7 @@ Der Mindestbetrag wird aus der aktuellen Netzwerkgebühr berechnet, um sicherzustellen, dass er 4%% nicht überschreitet, was den Mindestbetrag %1$s (%2$s) ergibt. Mindestaufladung Gebührenpolitik - Tangem erhebt außerdem eine Servicegebühr von 3% auf den erzielten Ertrag. + Tangem erhebt außerdem eine Servicegebühr von 15% auf den erzielten Ertrag. Deine Gelder werden automatisch an Aave überwiesen, sobald die Netzwerkgebühren niedriger sind oder Dein Guthaben den erforderlichen Mindestbetrag erreicht. Historische Renditen Die Freigabe für Deine Token im Yield-Modus wurde widerrufen. Öffne den Token, um die Berechtigung erneut zu erteilen. @@ -1720,7 +1720,7 @@ Senden, tauschen oder verkaufen Deine Gelder sofort, wann immer Du willst. Jederzeit Zugriff auf Dein Geld Wie funktioniert das? - Aave ist ein dezentrales Protokoll, das einen Gesamtwert von über 81,9 Milliarden US-Dollar verwaltet. + Aave ist ein dezentrales Protokoll, das einen Gesamtwert von über 61 Milliarden US-Dollar verwaltet. Dezentral und selbstverwahrend Durch die Nutzung dieses Dienstes erklärst Du Dich mit provider\n%1$s und %2$s einverstanden Mit Aave verbinden @@ -1743,11 +1743,9 @@ Die Netzwerkgebühr wird von dem Betrag, den Du abhebst, abgezogen. Effektiver Jahreszins für Versorgung Effektiver Jahreszins - Lass Dein Geld arbeiten – verdiene Zinsen auf Dein Guthaben. Zinsen fallen automatisch an Ertragsmodus Bearbeitung Deiner Einzahlung - Lass dein Guthaben arbeiten Automatisch Einzahlung von %1$s %2$s zur Deckung der Netzwerkgebühr für Transaktionen Die Gebühr %s kann nicht gedeckt werden diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index 4a8daa7d9e..1a93e0147b 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -1509,7 +1509,7 @@ 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). Recarga mínima Política de tarifas - Tangem también cobra una comisión de servicio del 3% sobre el rendimiento obtenido. + Tangem también cobra una comisión de servicio del 15% sobre el rendimiento obtenido. 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. Rendimientos históricos Se ha revocado la autorización para su token en el modo Rendimiento. Abra el token para volver a conceder el permiso. @@ -1521,7 +1521,7 @@ Envíe, intercambie o venda sus fondos al instante, cuando quiera. Acceda a sus fondos en cualquier momento ¿Cómo funciona? - Aave es un protocolo descentralizado que administra más de 81.9 billones de dólares en valor total. + Aave es un protocolo descentralizado que administra más de 61 billones de dólares en valor total. Descentralizado y autocustodiado Al utilizar este servicio, usted acepta que el proveedor\n%1$s y %2$s Conectar Aave @@ -1544,11 +1544,9 @@ La comisión de red se deducirá del importe que retire. Suministro APY APY - Deje que sus fondos hagan el trabajo mientras usted mantiene el control. Los intereses se devengan automáticamente Modo de rendimiento Procesando su depósito - Haga que sus activos trabajen para usted Automático Deposite algo de %1$s %2$s para cubrir la tarifa de red para las transacciones No se puede cubrir la tarifa %s diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index 22419eb4eb..8c6ab60718 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -244,7 +244,7 @@ La transaction a échoué Statut de la transaction Transactions - Transfert + Fourniture Je comprends Il y avait une erreur. Veuillez réessayer. Inaccessible @@ -1457,13 +1457,14 @@ 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 Vos fonds sont actuellement fournis au protocole Aave, mais vous pouvez les gérer à tout moment. Vos %s sont fournis à Aave. - Le transfert de %1$s %2$s vers Aave est en attente. + Le transfert de %1$s %2$s vers Aave est en attente. Donnez votre accord 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. Autorisation nécessaire Les frais seront prélevés et vos actifs seront à nouveau prêtés. Pour continuer à percevoir des revenus, une autorisation est nécessaire. Confirmer l\'approbation + Vos fonds sont actuellement affectés au protocole Aave, mais vous pouvez les gérer à tout moment. Vos %s sont déposés dans Aave. Impossible de charger le graphique... Le montant reçu, %1$s %2$s, n\'a pas été fourni à Aave. @@ -1487,9 +1488,10 @@ 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). Recharge minimale Politique tarifaire - Tangem prélève également des frais de service de 3% sur les revenus générés. + Tangem prélève également des frais de service de 15% sur les revenus générés. 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. Rendements historiques + L\'autorisation pour votre token en mode Yield a été révoquée. Ouvrez le token pour accorder à nouveau l\'autorisation. Approbations de tokens nécessaires Vérifiez votre connexion réseau. Informations sur les frais de réseau inaccessibles @@ -1498,7 +1500,7 @@ Envoyez, échangez ou vendez vos fonds instantanément, quand vous le souhaitez. Accédez à vos fonds à tout moment Comment ça marche ? - Aave est un protocole décentralisé qui gère plus de 81,9 milliards de dollars en valeur totale. + Aave est un protocole décentralisé qui gère plus de 61 milliards de dollars en valeur totale. Décentralisé et auto-détenu En utilisant ce service, vous acceptez les conditions générales du fournisseur %1$s et %2$s. Connecter Aave @@ -1521,11 +1523,9 @@ Les frais de réseau seront déduits du montant que vous retirez. Rendement annuel brut (APY) APY - Laissez vos fonds travailler pour vous tout en gardant le contrôle. Les intérêts sont cumulés automatiquement. Mode de rendement Traitement de votre dépôt - Faites fructifier vos actifs Automatique Déposez %1$s %2$s pour couvrir les frais de réseau liés aux transactions. Impossible de couvrir les frais %s diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 1b9d2b102f..2d8b7ca984 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -181,6 +181,7 @@ ADAが不足しています。 受け入れる アクセスが拒否されました + アカウント アカウント 有効化 追加 @@ -244,6 +245,7 @@ 有効にする 有効 エラー + ネットワークサービス手数料 スワップ 移動する 取引履歴を調べる @@ -476,7 +478,7 @@ プロバイダー ベストレート FCA警告リスト - お得なレート + ベストチョイス FCA警告リストに掲載されたプロバイダー 最大 %s まで使用可能 %s 以上で利用可能 @@ -1346,7 +1348,7 @@ ネットワーク%s内の保留中の取引が完了すると、送金が可能になります。 %sの売却は、現在のプロバイダーではサポートされていませんが、より多くのオプションを追加できるよう取り組んでいます。 %sのステーキングは、現在のプロバイダーではサポートされていませんが、より多くのオプションを追加できるよう取り組んでいます。 - ここにテキストを入力 + 承認が取り消されましたが、あなたの資金は引き続き利息モードです。操作を行うには、利息モードに移動し、再度承認を付与してください。 XPUBを生成する 非表示 このトークンをメイン画面から非表示にします。トークンの管理ページからいつでも再度追加できます。 @@ -1740,15 +1742,16 @@ いいえ、すべて送信します %s XTZを減らす 次回ウォレットにチャージするときに手数料の増加を避けるには、金額を%s XTZ減らしてください。 - あなたの資金は現在Aaveプロトコルに供給されていますが、いつでも管理できます。 + 利息モードを有効にすると、このアドレスへの今後のすべての入金はAaveに送られます。ただし、資金の管理は引き続き自由に行えます。 %sはAaveに供給されています Aaveへの%1$s %2$sの供給は保留中です 承認する - 前回の承認に問題があったため、新しい承認が必要です。手続き方法を選択してください。 + トークンの承認は取り消されました。サービス機能を再開するには、再度承認を行ってください。 承認が必要 手数料が差し引かれ、あなたの資産は再び貸し出されます。 引き続き収益を得るには承認が必要です。 承認を確定する + あなたの資金は現在Aaveプロトコルに預けられていますが、いつでも自由に管理できます。 あなたの%sはAaveに預けられています チャートを読み込めません・・ 受け取った金額%1$s %2$sはAaveに入金されませんでした。 @@ -1758,8 +1761,8 @@ 貸付のために入金する際は、残高から%1$s以下のネットワーク手数料が差し引かれます。 現在、ネットワーク手数料が高すぎるため貸付を実行できません。手数料が%1$s以下に下がり次第、資金が供給されます。 私の資金 - あなたの%1$sはAaveに預けられ、利息が付きます。あなたは%2$sトークンを保有しており、これは残高を表し、時間の経過とともに増加します。入金すると資金はAaveに供給され、取引手数料を差し引いた利息が付きます。 - 利回りを得る + あなたの%1$sは現在Aaveにデプロイされ、利回りを生んでいます。あなたは%2$sトークンを保有しており、これはあなたの残高を表し、自動的に利回りが発生します。追加入金すると、手数料を差し引いた上でAaveに資産が追加され、さらに利回りを得られるようになります。 + 利息モード 総収益 Aaveへの送金 Aaveの詳細を見る @@ -1769,13 +1772,14 @@ 今後のチャージごとに、おおよそ%1$s(%2$s)のネットワーク手数料が差し引かれますが、上限の%3$s(%4$s)を超えることはありません。 ネットワーク手数料が上限手数料を超えた場合、手数料が下がるまで取引は成立しません。この制限は後で変更できます。 最大手数料 - 最小金額は現在のネットワーク手数料に基づいて計算されており、手数料が4%を超えないように設定されています。その結果、最小金額は%1$s(%2$s)となります。 + 最小金額は現在のネットワーク手数料に基づいて計算されており、手数料が4%を超えないように設定されています。そのため、最小金額は%1$s(%2$s)となります。 最低入金額 手数料ポリシー - Tangemはまた、得られた利回りに対して3%のサービス手数料を差し引きます。 + Tangemはまた、得られた利回りに対して15%のサービス手数料を差し引きます。 ネットワーク手数料が下がるか、残高が最低必要額に達すると、資金は自動的にAaveに供給されます。 過去のリターン - トークンの承認が必要 + 利息モードでのトークンの承認が取り消されました。トークンを開いて再度許可してください。 + トークンの承認が必要です ネットワーク接続を確認してください ネットワーク手数料についての情報にアクセスできません あなたが行うすべての入金は、自動的にAaveへ供給されます。 @@ -1783,7 +1787,7 @@ いつでも、即座に資金を送信、交換、売却できます。 いつでも資金にアクセス可能 使い方 - Aaveは、総額819億ドル以上の資産を管理する分散型プロトコルです。 + Aaveは、総額610億ドル以上の資産を管理する分散型プロトコルです。 分散型・自己管理型 このサービスを利用することにより、プロバイダー\n%1$sおよび%2$sに同意するものとします。 Aave を接続 @@ -1802,19 +1806,20 @@ アクティブ 停止中 利回りモードを無効にする - これをオフにすると、Aave からウォレットの %s に資金が引き出され、報酬の獲得が停止します。 + これをオフにすると、Aaveから資産が引き出され、ウォレット内の%sに変換され、利回りの発生が停止します。 出金金額からネットワーク手数料が差し引かれます。 + 供給 供給APY APY - 自分で管理しながら、資金に働かせましょう。 + 利息は自動的に発生します 利息は自動的に発生します 利回りモード 入金の処理中 - 資産を有効活用しましょう + 利息モード 自動 取引のネットワーク手数料をカバーするために、 %1$s %2$sを入金してください %s手数料を支払えません - 利息サービスは現在利用できません。しばらくしてから再度お試しください。 - 収益は利用できません + 現在、利息モードのサービスは利用できません。しばらくしてから再度お試しください。 + 利息モードは利用できません チャートを読み込めません・・ diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index d31c06528c..481e539277 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -181,6 +181,7 @@ Включить Включено Ошибка + Комиссия сети Обменять Обозреватель Посмотреть историю транзакций @@ -1588,7 +1589,7 @@ Доступно Текущий APY Мои средства - Ваш %1$s теперь внесён в Aave и приносит проценты. У вас есть токен %2$s, который отражает ваш баланс и со временем увеличивается. При пополнении средства автоматически направляются в Aave для получения процентов за вычетом комиссии за транзакцию. + Ваши %1$s теперь внесён в Aave и приносит проценты. У вас есть токен %2$s, который отражает ваш баланс и со временем увеличивается. При пополнении средства автоматически направляются в Aave для получения процентов за вычетом комиссии за транзакцию. Итоговый доход Переводы в Aave Изучите Aave @@ -1600,7 +1601,7 @@ Это минимальный депозит, который можно отправить в Aave. Чтобы депозиты оставались прибыльными, мы не обрабатываем их, когда комиссия сети превышает %1$s%2$sот суммы. Минимальный депозит Политика комиссий - Tangem взимает комиссию за обслуживание в размере 3% от полученного дохода. + Tangem взимает комиссию за обслуживание в размере 15% от полученного дохода. Ваши средства будут автоматически переведены в Aave, как только комиссия сети снизится или баланс достигнет минимально необходимой суммы. Историческая доходность Разрешение для вашего токена в Yield сервисе было отозвано. Откройте токен, чтобы выдать разрешение снова. @@ -1612,7 +1613,7 @@ Отправляйте, обменивайте или продавайте свои средства мгновенно, когда захотите. Мгновенный вывод средств Как это работает? - Aave — это децентрализованный протокол, управляющий активами на сумму более 81,9 миллиарда долларов США. + Aave — это децентрализованный протокол, управляющий активами на сумму более 61 миллиарда долларов США. Децентрализованный и некастодиальный Используя сервис, вы соглашаетесь с условиями провайдера %1$s и %2$s Подключить Aave @@ -1631,15 +1632,13 @@ Активен На паузе Завершить заработок - Выключив эту функцию, вы выведёте средства из Aave, получите их обратно в %s в кошельке и перестанете зарабатывать награды. + Выключив эту функцию, вы выведёте средства из Aave, получите их обратно в %s в своем кошельке и перестанете зарабатывать награды. Комиссия сети будет вычтена из суммы вашего вывода. Годовая доходность (APY) APY - Пусть ваши деньги работают — зарабатывайте проценты на свой баланс. Проценты начисляются автоматически. Режим доходности Отправка ваших средств - Пусть ваш баланс работает на вас! Автоматически Внесите немного %1$s %2$s, чтобы покрыть комиссию сети за транзакции. Невозможно покрыть комиссию в %s diff --git a/core/res/src/main/res/values-uk-rUA/strings.xml b/core/res/src/main/res/values-uk-rUA/strings.xml index 4a7a2575b3..6812790144 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -1432,6 +1432,80 @@ Ні, відправити все Зменшити на %s XTZ Щоб не платити підвищену комісію при наступному поповненні гаманця, зменште суму на %s XTZ + З активним режимом дохідності всі майбутні депозити на цю адресу будуть надходити до Aave. Ви все ще можете вільно розпоряджатися своїми коштами. + Ваш %s внесений до Aave + Передача %1$s %2$s до Aave очікується + Дати згоду + Схвалення для вашого токена було відкликано. Надайте його знову, щоб відновити роботу сервісу. + Потрібне схвалення + Комісія буде знята, а ваші активи знову почнуть приносити дохід. + Щоб продовжити заробляти, потрібне схвалення. + Підтвердити дозвіл + Наразі ваші кошти розміщені у протоколі Aave, але ви можете керувати ними в будь-який час. + Ваш %s внесений у Aave + Неможливо завантажити графік + Отримана сума, %1$s %2$s не була зарахована на Aave. + APY %1$s%% + Доступно + Поточний APY + При поповненні для кредитування з балансу буде вирахувано комісію мережі, що не перевищує %1$s. + Наразі мережева комісія є занадто високою, щоб здійснювати кредитування. Кошти будуть надані, як тільки вона знизиться до %1$s або нижче. + Мої кошти + Ваші %1$s тепер розміщено в Aave і приносить дохід. У вас є токен %2$s, який представляє ваш баланс і з часом збільшується. При поповненні кошти автоматично направляються в Aave для отримання процентів з вирахуванням комісії за транзакцію. + Режим дохідності + Підсумковий дохід + Перекази в Aave + Дослідити Aave + Це поточна комісія у мережі %s. + Поточна комісія + Усі майбутні депозити %s будуть надходити до Aave автоматично, з вирахуванням комісії за транзакцію. + Приблизна мережева плата в розмірі %1$s (%2$s) буде вираховуватися з кожного наступного поповнення, і вона не перевищуватиме ваш ліміт %3$s (%4$s). + Якщо мережеві комісії перевищують максимальну комісію, транзакція не пройде, поки вони не знизяться. Ви можете змінити цей ліміт пізніше. + Максимальна комісія Це найменший депозит, який можна надіслати в Aave. Щоб депозити залишалися прибутковими, ми не обробляємо їх, коли комісія мережі перевищує %1$s%2$s від суми. + Мінімальне поповнення + Політика комісій + Tangem комісію за обслуговування у розмірі 15% від отриманого доходу. + Ваші кошти будуть автоматично переведені у Aave, як тільки мережеві комісії знизяться або ваш баланс досягне мінімально необхідної суми. + Історична прибутковість Дозвіл для вашого токена в режимі Yield було відкликано. Відкрийте токен, щоб надати дозвіл знову. + Потрібний дозвіл для токену + Перевірте підключення до мережі + Інформація про комісію недоступна + Кожен ваш депозит буде автоматично надходити до Aave. + Автопереказ до AAVE + Відправляйте, обмінюйте або продавайте свої кошти миттєво, в будь-який час. + Миттєвий вивід коштів + Як це працює? + Aave — це децентралізований протокол, який управляє активами загальною вартістю понад 61 мільярд доларів. + Децентралізований та некастодіальний + Використовуючи сервіс, ви погоджуєтесь з умовами провайдера %1$s та %2$s + Підключити Aave + Aave %1$s%% • Ставка з плаваючим відсотком + Аave + Серед. %s + Дохідність за минулий рік + Поточна відсоткова ставка завжди змінна і автоматично розраховується смарт-контрактом Aave у блокчейні на основі попиту та пропозиції в режимі реального часу. + При підтримці + Ставка може змінюватися + Коли ви поповнюєте рахунок, ваші кошти автоматично надсилатимуться на Aave, щоб почати нараховувати відсотки. Для покриття комісії з вас буде утримана невелика плата у розмірі %s. + Почати заробляти + Ваш %s буде передано до Aave, і залишиться завжди доступним. + Політика комісій + Ваші наступні поповнення рахунку автоматично надходитимуть до Aave. + Активний + На паузі + Завершити заробіток + Вимкнення цієї опції виведе ваші активи з Aave, отримаєте їх назад у %s у вашому гаманці і зупинить накопичення нагород. + Комісія мережі буде вирахувана з суми, яку ви знімаєте. + Річна прибутковість (APY) + APY + Відсотки нараховуються автоматично + Режим дохідності + Відправка ваших коштів + Автоматично + Внесіть трохи %1$s %2$s, щоб покрити комісію мережі за транзакції. + Неможливо покрити комісію в %s + Сервіс доходності у даний час недоступний. Будь ласка, спробуйте пізніше. + Режим дохідності недоступний diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index f93fca2b20..51c96443a0 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -184,6 +184,7 @@ Not enough ADA Accept Access denied + Account Accounts Activate Add @@ -249,7 +250,7 @@ Enable Enabled Error - Estimated fee + Network service fee Swap Explore Explore transaction history @@ -1815,7 +1816,7 @@ To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ With Yield mode active, all future deposits to this address will go to Aave. You can still manage your funds freely. Your %s is supplied to Aave - Supplying %1$s %2$s to Aave is pending + Supplying %1$s %2$s to Aave is pending Give Approve Your token’s approval has been revoked. Grant it again to resume service functionality. Approve needed @@ -1832,7 +1833,7 @@ When topping up for lending, a network fee not exceeding %1$s will be deducted from the balance. The network fee is currently too high to execute lending. Funds will be supplied once it drops to %1$s or below. My funds - 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. + 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. Yield mode Total earnings Transfers to Aave @@ -1840,13 +1841,13 @@ This is the current supply fee on %s. The actual cost will be shown on the activation tab. Current fee All future %s deposits will be supplied to Aave automatically, with the transaction fee deducted. - An approximate network fee of %1$s (%2$s) will be deducted from each future top-up, and it won’t exceed your %3$s (%4$s) limit. + An approximate network fee of %1$s (%2$s) will be deducted from each future top-up, and it won’t exceed your %3$s (%4$s) limit. If network fees rise above maximum fee, the transaction won’t go through until they decrease. You can change this limit later. Maximum fee 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). Minimum top-up Fee policy - Tangem also takes a 3% service fee on yield earned. + Tangem also takes a 15% service fee on yield earned. Your funds will be automatically supplied to Aave once network fees are lower or your balance meets the minimum required amount. Historical returns Approval for your token in the Yield mode has been revoked. Open the token to grant permission again. @@ -1858,7 +1859,7 @@ Send, swap, or sell your funds instantly, anytime you want. Access your funds anytime How it works? - Aave is a decentralized protocol managing over $81.9 billion in total value. + Aave is a decentralized protocol managing over $61  billion in total value. Decentralized and self-custodial By using this service, you agree with provider\n%1$s and %2$s Connect Aave @@ -1877,15 +1878,16 @@ Active Paused Disable yield mode - Turning this off will withdraw your funds from Aave to %s in your wallet and it will stop earning rewards. + Turning this off will withdraw your assets from Aave, convert them back to %s in your wallet, and stop yield accrual. The network fee will be deducted from the amount you withdraw. + Supply Supply APY APY - Let your funds do the work while you stay in control. + Interest accrues automatically Interest accrues automatically Yield mode Processing your deposit - Make your assets work for you + Yield Mode Automatic Deposit some %1$s %2$s to cover the network fee for transactions Unable to cover %s fee diff --git a/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt index dab13ed0a5..66faea0a74 100644 --- a/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt @@ -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( diff --git a/data/common/src/main/kotlin/com/tangem/data/common/network/NetworkFactory.kt b/data/common/src/main/kotlin/com/tangem/data/common/network/NetworkFactory.kt index d43b2d8de1..804fb0db6d 100644 --- a/data/common/src/main/kotlin/com/tangem/data/common/network/NetworkFactory.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/network/NetworkFactory.kt @@ -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 * diff --git a/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapTransactionRepository.kt b/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapTransactionRepository.kt index 6d67e11d9d..f7ade3cac9 100644 --- a/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapTransactionRepository.kt +++ b/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapTransactionRepository.kt @@ -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? = 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, ) } } diff --git a/data/swap/src/main/java/com/tangem/data/swap/converter/transaction/SavedSwapTransactionListConverter.kt b/data/swap/src/main/java/com/tangem/data/swap/converter/transaction/SavedSwapTransactionListConverter.kt index dca9f020fc..16b144b862 100644 --- a/data/swap/src/main/java/com/tangem/data/swap/converter/transaction/SavedSwapTransactionListConverter.kt +++ b/data/swap/src/main/java/com/tangem/data/swap/converter/transaction/SavedSwapTransactionListConverter.kt @@ -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 { 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, + ) + } + } } \ No newline at end of file diff --git a/data/swap/src/main/java/com/tangem/data/swap/di/SwapDataModule.kt b/data/swap/src/main/java/com/tangem/data/swap/di/SwapDataModule.kt index 595d799f2d..7784c4ea1b 100644 --- a/data/swap/src/main/java/com/tangem/data/swap/di/SwapDataModule.kt +++ b/data/swap/src/main/java/com/tangem/data/swap/di/SwapDataModule.kt @@ -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, ) } diff --git a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt index 8f5fe85b65..082d68a3d2 100644 --- a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt +++ b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyRepository.kt @@ -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.enrichNetworkIds(): List { diff --git a/domain/legacy/src/main/assets/contract_methods.json b/domain/legacy/src/main/assets/contract_methods.json index 671f0b7d6b..944b8a716b 100644 --- a/domain/legacy/src/main/assets/contract_methods.json +++ b/domain/legacy/src/main/assets/contract_methods.json @@ -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" } } diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt index e709bd63de..5b277e5aed 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt @@ -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> { + operator fun invoke(): Flow>> { 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}" } } } \ No newline at end of file diff --git a/domain/swap/src/main/java/com/tangem/domain/swap/SwapTransactionRepository.kt b/domain/swap/src/main/java/com/tangem/domain/swap/SwapTransactionRepository.kt index c1ed26365a..5f9a18e411 100644 --- a/domain/swap/src/main/java/com/tangem/domain/swap/SwapTransactionRepository.kt +++ b/domain/swap/src/main/java/com/tangem/domain/swap/SwapTransactionRepository.kt @@ -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 diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/YieldSupplyRepository.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/YieldSupplyRepository.kt index a9ce7c69dd..deb3c44851 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/YieldSupplyRepository.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/YieldSupplyRepository.kt @@ -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? } \ No newline at end of file diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyActivateUseCase.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyActivateUseCase.kt index 3ca5a7b0e8..5b2126f395 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyActivateUseCase.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyActivateUseCase.kt @@ -8,8 +8,9 @@ class YieldSupplyActivateUseCase( private val yieldSupplyRepository: YieldSupplyRepository, ) { - suspend operator fun invoke(cryptoCurrency: CryptoCurrency): Either = Either.catch { - val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected") - yieldSupplyRepository.activateProtocol(token) - } + suspend operator fun invoke(cryptoCurrency: CryptoCurrency, address: String): Either = + Either.catch { + val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected") + yieldSupplyRepository.activateProtocol(token, address) + } } \ No newline at end of file diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyDeactivateUseCase.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyDeactivateUseCase.kt index fc666ada1a..ba431ae585 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyDeactivateUseCase.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyDeactivateUseCase.kt @@ -8,8 +8,9 @@ class YieldSupplyDeactivateUseCase( private val yieldSupplyRepository: YieldSupplyRepository, ) { - suspend operator fun invoke(cryptoCurrency: CryptoCurrency): Either = Either.catch { - val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected") - yieldSupplyRepository.deactivateProtocol(token) - } + suspend operator fun invoke(cryptoCurrency: CryptoCurrency, address: String): Either = + Either.catch { + val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected") + yieldSupplyRepository.deactivateProtocol(token, address) + } } \ No newline at end of file diff --git a/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/StoriesScreen.kt b/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/StoriesScreen.kt index 704485cb28..8eab486edb 100644 --- a/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/StoriesScreen.kt +++ b/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/StoriesScreen.kt @@ -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 diff --git a/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/StoriesScreenV2.kt b/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/StoriesScreenV2.kt index 3f790b2e79..e3a485d2cd 100644 --- a/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/StoriesScreenV2.kt +++ b/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/StoriesScreenV2.kt @@ -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 diff --git a/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/views/StoriesProgressBar.kt b/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/views/StoriesProgressBar.kt index cc6ea2107c..058d371b74 100644 --- a/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/views/StoriesProgressBar.kt +++ b/features/home/impl/src/main/kotlin/com/tangem/features/home/impl/ui/compose/views/StoriesProgressBar.kt @@ -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 } }, diff --git a/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt index 4564ce9ded..fd6d531d4f 100644 --- a/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt +++ b/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt @@ -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) diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/ui/SendAmountContent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/ui/SendAmountContent.kt index 91252a0eaa..1177c1f24f 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/ui/SendAmountContent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/ui/SendAmountContent.kt @@ -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) diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt index 23e1fec6c3..7642f338a8 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt @@ -272,6 +272,7 @@ internal class NotificationsModel @Inject constructor( reserveAmount = currencyCheck.reserveAmount, sendingAmount = sendingAmount, cryptoCurrency = currency, + feeCryptoCurrency = feeCryptoCurrencyStatus.currency, isAccountFunded = currencyCheck.isAccountFunded, ) addMinimumAmountErrorNotification( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt index a4d0229f85..673dc355c0 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt @@ -41,8 +41,9 @@ internal class StakingStateRouter( StakingStep.Validators, StakingStep.Amount, -> showConfirmation() - StakingStep.Confirmation -> showInitial() - StakingStep.Success -> appRouter.pop() + StakingStep.Confirmation, + StakingStep.Success, + -> showInitial() } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt index 5a69049425..05f544c7bb 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt @@ -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() } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt index 1681808734..b4daf2050b 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt @@ -214,6 +214,7 @@ internal class AddStakingNotificationsTransformer( reserveAmount = currencyCheck.reserveAmount, sendingAmount = sendingAmount, cryptoCurrency = cryptoCurrency, + feeCryptoCurrency = feeCryptoCurrencyStatus?.currency, isAccountFunded = false, ) } diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt index 638147c85c..67bcaffe1e 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt @@ -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? = 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, ) } } diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt index d476f5ff9c..261e5f675c 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt @@ -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 { 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, + ) + } + } } \ No newline at end of file diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt index 4aada993a6..b80b472729 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt @@ -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, ) } diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapTransactionRepository.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapTransactionRepository.kt index e815518f1c..ef64270e26 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapTransactionRepository.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapTransactionRepository.kt @@ -23,12 +23,7 @@ interface SwapTransactionRepository { cryptoCurrencyId: CryptoCurrency.ID, ): Flow?> - suspend fun removeTransaction( - userWalletId: UserWalletId, - fromCryptoCurrency: CryptoCurrency, - toCryptoCurrency: CryptoCurrency, - txId: String, - ) + suspend fun removeTransaction(userWalletId: UserWalletId, txId: String) suspend fun storeTransactionState( txId: String, diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt index 9710aa7b07..00e5e36c6d 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt @@ -192,6 +192,7 @@ internal class SwapNotificationsFactory( reserveAmount = quoteModel.currencyCheck?.reserveAmount, sendingAmount = amountToRequest.value, cryptoCurrency = fromCurrencyStatus.currency, + feeCryptoCurrency = feeCryptoCurrencyStatus?.currency, isAccountFunded = false, ) addReduceAmountNotification( diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt index 1bfc82a05f..3aed5a00de 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt @@ -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, ) } diff --git a/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/converter/TxHistoryItemToTransactionStateConverter.kt b/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/converter/TxHistoryItemToTransactionStateConverter.kt index f18879a60a..33ef338944 100644 --- a/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/converter/TxHistoryItemToTransactionStateConverter.kt +++ b/features/txhistory/impl/src/main/kotlin/com/tangem/features/txhistory/converter/TxHistoryItemToTransactionStateConverter.kt @@ -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) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt index 5255206967..4d102bb5d8 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt @@ -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 = emptyMap(), - private val stakingApyMap: Map = emptyMap(), + private val stakingApyMap: Map> = emptyMap(), ) : WalletStateTransformer(userWallet.walletId) { override fun transform(prevState: WalletState): WalletState { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt index 68827d346e..d5b1c850ac 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt @@ -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, - private val stakingApyMap: Map, + private val stakingApyMap: Map>, ) : Converter { private val onTokenClick: (accountId: AccountId?, currencyStatus: CryptoCurrencyStatus) -> Unit = diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TxHistoryItemStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TxHistoryItemStateConverter.kt index 5db8fb0058..d926942932 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TxHistoryItemStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TxHistoryItemStateConverter.kt @@ -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) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt index 328d3a5cbe..8fbd5a1d74 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt @@ -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, - stakingApyMap: Map, + stakingApyMap: Map>, ) { val tokenList = maybeTokenList.getOrElse( ifLoading = { maybeContent -> @@ -242,7 +242,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { params: TokenConverterParams, appCurrency: AppCurrency, yieldSupplyApyMap: Map, - stakingApyMap: Map, + stakingApyMap: Map>, ) { stateHolder.update( SetTokenListTransformer( @@ -268,6 +268,6 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { private fun yieldSupplyApyFlow(): Flow> = yieldSupplyApyFlowUseCase() .distinctUntilChanged() - private fun stakingApyFlow(): Flow> = stakingApyFlowUseCase() + private fun stakingApyFlow(): Flow>> = stakingApyFlowUseCase() .distinctUntilChanged() } \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/entity/YieldSupplyUM.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/entity/YieldSupplyUM.kt index 2d7419ea4b..fab5e5aa21 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/entity/YieldSupplyUM.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/entity/YieldSupplyUM.kt @@ -10,6 +10,7 @@ internal sealed class YieldSupplyUM { data class Available( val apy: String, + val apyText: TextReference, val title: TextReference, val onClick: () -> Unit, ) : YieldSupplyUM() diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt index 9d5b7885d9..bf4ac35878 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt @@ -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 } } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/transformers/YieldSupplyTokenStatusSuccessTransformer.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/transformers/YieldSupplyTokenStatusSuccessTransformer.kt index 338012ba0e..ef9f8b8a99 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/transformers/YieldSupplyTokenStatusSuccessTransformer.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/transformers/YieldSupplyTokenStatusSuccessTransformer.kt @@ -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}%"), + ), ) } } \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/ui/YieldSupplyBlockContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/ui/YieldSupplyBlockContent.kt index dbcb639c6b..af19fd4a55 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/ui/YieldSupplyBlockContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/ui/YieldSupplyBlockContent.kt @@ -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 { wrappedList("5.1"), ), apy = "5.1", + apyText = stringReference("5.1 % APY"), onClick = {}, ), YieldSupplyUM.Content( diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt index 8e409ddc3d..fdb9493169 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt @@ -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() } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt index 184f0fa198..b76fd630a4 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt @@ -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) } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt index 4ab5059e24..73cfd703d0 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt @@ -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() } diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index f7e514619e..b7a7456028 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -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 ^