From e644ff7c96014ed07e78f8bda11cd8e6dd256976 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 23 Sep 2025 11:30:30 +0300 Subject: [PATCH 01/10] Updated on 2026-08-14 --- .gitignore | 1 + .../tap/di/domain/TransactionDomainModule.kt | 6 +- core/res/src/main/res/values-de/strings.xml | 2 +- core/res/src/main/res/values-es/strings.xml | 2 +- core/res/src/main/res/values-fr/strings.xml | 6 +- core/res/src/main/res/values-ja/strings.xml | 63 ++++++++++++------- core/res/src/main/res/values-ru/strings.xml | 4 +- .../src/main/res/values-uk-rUA/strings.xml | 2 +- core/res/src/main/res/values/strings.xml | 13 +++- .../DefaultWalletManagersFacade.kt | 4 +- .../analytics/StakingAnalyticsEvent.kt | 5 ++ ...eCase.kt => IsSelfSendAvailableUseCase.kt} | 6 +- .../usecase/ValidateWalletAddressUseCase.kt | 5 +- .../walletmanager/WalletManagersFacade.kt | 4 +- .../destination/model/SendDestinationModel.kt | 8 +-- .../SendRecipientWalletListConverter.kt | 4 +- .../SendDestinationRecentListTransformer.kt | 4 +- .../impl/presentation/model/StakingModel.kt | 3 + gradle/tangem_dependencies.toml | 2 +- 19 files changed, 87 insertions(+), 57 deletions(-) rename domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/{IsUtxoConsolidationAvailableUseCase.kt => IsSelfSendAvailableUseCase.kt} (74%) diff --git a/.gitignore b/.gitignore index a4d9c4c73d..7f43fa6dc1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ **/build/kotlin/** **/build/libs/** **/build/outputs/** +**/build/reports/** **/build/tmp/** # Local configuration file (sdk path, etc) diff --git a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt index 3a63ffb6a8..64dbe9c954 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt @@ -143,10 +143,8 @@ internal object TransactionDomainModule { @Provides @Singleton - fun provideIsUtxoConsolidationAvailableUseCase( - walletManagersFacade: WalletManagersFacade, - ): IsUtxoConsolidationAvailableUseCase { - return IsUtxoConsolidationAvailableUseCase(walletManagersFacade) + fun provideIsSelfSendAvailableUseCase(walletManagersFacade: WalletManagersFacade): IsSelfSendAvailableUseCase { + return IsSelfSendAvailableUseCase(walletManagersFacade) } @Provides diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index a590f5ba85..95e6c4e686 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -1025,7 +1025,7 @@ Keine gültige Adresse Stelle sicher, dass sich die empfangende Wallet-Adresse im **%s -Netzwerk** befindet, um den Verlust Deiner Token zu vermeiden. Senden an - Ein Memo/Destination Tag ist eine eindeutige ID zur Unterscheidung von Transaktionen, die an denselben Empfänger im selben Netzwerk gesendet werden. Vorsicht! Das Weglassen eines Vermerks kann dazu führen, dass Gelder für immer verloren sind! + Ein Memo/Destination Tag ist eine eindeutige ID zur Unterscheidung von Transaktionen, die an denselben Empfänger im selben Netzwerk gesendet werden.\n**Vorsicht! Das Weglassen eines Vermerks kann dazu führen, dass Gelder für immer verloren sind!** Memo / Destination Tag ist ein Code, der Transaktionen an einen gemeinsamen Empfänger im Kryptonetzwerk voneinander trennt. Achtung: Das Fehlen eines Memos kann zum Verlust von Geldern führen. Meine Wallet diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index 79b4f20f19..8278e828ad 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -925,7 +925,7 @@ No es una dirección válida Asegúrese de que la dirección de la billetera receptora esté en **la red %s** para evitar perder sus tokens Destinatario - Un Memo/ID de destino es un ID único para diferenciar transacciones enviadas al mismo destinatario en la misma red. Precaución: Omitir un memo puede llevar a la pérdida de fondos + Un Memo/ID de destino es un ID único para diferenciar transacciones enviadas al mismo destinatario en la misma red.\n**Precaución: Omitir un memo puede llevar a la pérdida de fondos** Memo / Destination Tag es un código que separa las transacciones dirigidas a un destinatario compartido en una red de criptomonedas. Atención: La omisión del campo Memo puede provocar la pérdida de fondos. Mis billeteras diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index bb23367928..b4299c0887 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -623,8 +623,8 @@ Partagez votre code et gagnez 5 USDT par vente. Votre ami bénéficie de 10 % de réduction. Recevez des RÉCOMPENSES pour chaque ami ! Acheter crypto - Tangem réduit les frais SEPA à presque rien, vous offrant ainsi la meilleure offre à ce jour. - Achetez des cryptomonnaies sans payer de frais ! + Profitez de **0% de frais** lors de l\'achat de cryptomonnaies via des virements SEPA. + Acheter des cryptomonnaies avec SEPA Vous devez définir un seul code d\'accès pour protéger tous vos appareils. Protéger Vous pourrez définir un code d\'accès individuel sur chaque carte plus tard @@ -899,7 +899,7 @@ Adresse non valide Assurez-vous que l\'adresse du portefeuille de réception est sur **le réseau %s** pour éviter de perdre vos jetons Envoyer à - Un Memo/Destination Tag est un identifiant unique permettant de différencier les transactions envoyées au même destinataire sur le même réseau. Attention : L\'omission d\'un mémo peut entraîner des fonds mal placés + Un Memo/Destination Tag est un identifiant unique permettant de différencier les transactions envoyées au même destinataire sur le même réseau.\n**Attention : L\'omission d\'un mémo peut entraîner des fonds mal placés** Le Memo / Destination Tag est un code qui distingue les transactions envoyées à un destinataire partagé sur un réseau crypto. Attention : l\'absence de Memo peut entraîner une perte de fonds. Mes portefeuilles diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 6b3712c0c4..aebdb99134 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -1,10 +1,10 @@ - アクセスコードがないとウォレットは保護されません。 + アクセスコードがないとウォレットは安全ではありません。 とにかくスキップ アクセスコードが設定されていません アクセスコードを入力 - アクセスコードが間違っています。あと%s回間違えるとホットウォレットが削除されます。 + アクセスコードが間違っています。あと%s回間違えると、モバイルウォレットが削除されます。 アクセスコードが間違っています。あと%s回失敗すると、アプリはロックされます。 アクセスコードが間違っています。 \n %s秒待ってから再試行してください。 続行するにはアクセスコードを確認してください @@ -77,7 +77,7 @@ %1$s ネットワークのトークンは、ファームウェアの制限により、このカードまたはリングではサポートされていません。 カードまたはリングのスキャンに問題がありますか? このカードはこのアプリでは使用できません。 - %1$sを使用すると、ウォレットのロックを迅速かつ安全に解除できます。また、取引の署名など、機密性の高い操作も承認できます。ハードウェアウォレットの場合は、署名にカードが必要です。 + %1$sを使用してウォレットのロックを解除し、取引の署名などの機密性の高い操作を承認してください。ハードウェアウォレットの場合は、署名にカードまたはリングが必要です。 デフォルト手数料 デフォルト手数料を有効にすると、取引手数料が自動的に設定され、送金時に手数料ページを表示する必要がなくなります。必要に応じて、いつでもこのページに戻ることができます。 設定に移動して、Tangemアプリで生体認証を有効にします。 @@ -88,7 +88,7 @@ 保存したデバイスを削除すると、保存されているすべてのウォレットとそのアクセスコードがアプリから削除されます。 これにより、保存されているウォレットアクセスコードがすべて削除されます。今後ウォレットを操作するには、アクセスコードの送信が必要になります。 アクセスコードを要求する - このオプションを選択すると、機密性の高い操作における生体認証が無効になります。取引の署名時などには、毎回アクセスコードの入力が必要になります。 + このオプションを選択すると、機密性の高い操作における生体認証が無効になります。取引に署名するたびにアクセスコードを入力する必要があります。 アクセスコードを保存 カードまたはリングとのやり取りには、アクセスコードの代わりに生体認証が要求されます。 ウォレットをアプリに保存する @@ -106,17 +106,17 @@ モバイルウォレット ウォレットのバックアップが正常に完了しました。 - これらの単語は紛失した場合、復元できません。必ず安全な場所に保管してください。 + これらの単語は一度失うと復元できません。安全な場所に保管してください。 バックアップが完了しました シークレットリカバリーフレーズとは、ウォレットへのアクセスや復元のために使う、固定された%s個のランダムな単語のセットです。 - これらの単語は紛失した場合、復元できません。必ず安全な場所に保管してください。 + これらの単語は紛失した場合、復元できません。大切に保管してください。 安全に保管してください - これらの%s個の単語をパスワードマネージャーなどの安全な場所に保存し、決して他の人と共有しないでください。 + これらの%s個の単語を安全な場所に保存し、決して誰とも共有しないでください。 復元は不可能です リカバリーフレーズ - これらの単語は、絶対に誰にも共有しないでください。もし他人がこの単語を知れば、あなたの暗号資産をすべて盗むことができます。Tangemがこれらの単語を尋ねることはありません。以下の%s単語はウォレットの復元フレーズです。これらのフレーズを使用すると、デバイスを紛失した場合でもウォレットを復元できます。 - これらの%s語を順番に書き留めて、安全かつプライベートに保管してください。 - ウォレットと、リカバリーフレーズのセキュリティとバックアップの全責任は、Tangemではなくユーザーにあります。 + これらの単語は誰にも教えないでください。Tangemがこれらの単語を尋ねることは、絶対にありません。以下の%s個の単語はウォレットのリカバリーフレーズです。デバイスを紛失した場合、これらの単語を使用してウォレットを復元できます。 + これらの%s個の単語を番号順に書き留め、安全かつ他人の目に触れない場所に保管してください + ウォレットおよびリカバリーフレーズの保護とバックアップは、すべてあなた自身の責任となります。 リカバリーフレーズ 残高を表示または非表示にするには、デバイスの画面を下向きにするか、設定でオフにしてください。 今後表示しない @@ -507,7 +507,7 @@ アクセスコードの設定をキャンセルしてもよろしいですか? 今すぐバックアップ 設定を完了するには、ウォレットをバックアップし、アクセスコードでアプリを保護してください。 - 今すぐ実施 + 今すぐ確定 ウォレットの設定を完了する アクセスコードでアプリを保護して、設定を完了してください。 そうした場合は、最初からやり直す必要があります。 @@ -515,7 +515,7 @@ 実行すると、最初からやり直す必要があります。 Googleドライブのバックアップから既存のウォレットを復元する Googleドライブのバックアップ - Tangemの業界最高水準のハードウェアウォレットで、今すぐセキュリティをアップグレードしましょう。 + Tangemの高性能ハードウェアウォレットで、セキュリティをさらに強化しましょう。 ハードウェアウォレット バックアップへ移動 アクセスコードを作成する前にウォレットをバックアップしてください。 @@ -530,7 +530,7 @@ アップグレードできません。このデバイスにはすでにウォレットが存在します。 別のデバイスを選択してください。このデバイスはアップグレードに使用できません。 操作中にエラーが発生しました。 - 手続き中も資金は安全に保管され、完全にアクセス可能です + 処理中も、資金は安全に保たれ、常にアクセス可能です。 資金へのアクセス ウォレットのデータはアプリから削除され、Tangemデバイスに保存されます。 セキュリティ全般 @@ -538,7 +538,7 @@ 鍵の移行 デバイスをスキャン アップグレードを開始 - ウォレットをTangemウォレットにアップグレードします。これにより、コールドストレージで資産を安全に保管できます。 + ハードウェアウォレットにアップグレードすると、資産がコールドストレージで安全に保管されます。 Tangemウォレット ハードウェアウォレットにアップグレード Tangemの業界最高クラスのハードウェアウォレットで、暗号資産を安全に保管しましょう。 @@ -583,7 +583,7 @@ %1$d の %2$d ウォレット\n%1$d の %2$d ウォレット 削除 - 例:私はBTCを信じる、HODLしなければならない + 例:ビットコイン ポートフォリオが更新されました 選択したトークンは現在、暗号資産ウォレット内でのアクションには利用できません。しかし、心配しないでください。賛成票を投じることで関心を表明できます。 賛成票を投じる @@ -762,7 +762,7 @@ トークンを追加する バックアップカードまたはリングを1つ追加しました。バックアップ処理が終了すると、これ以上バックアップデバイスを追加することはできません。もう一つカードまたはリングがある場合、バックアップに追加してください。バックアップ処理を続けますか? バックアップ手続きは部分的に完了しています。現在終了することはできません。 - パスフレーズは、暗号資産ウォレットが使用する高度なセキュリティ機能です。既存のリカバリフレーズに、自分で選択した単語またはフレーズを追加することで、まったく新しいアドレスのロック解除が可能になります。 + パスフレーズは、リカバリーフレーズに単語やフレーズを追加することで、追加の保護を提供する任意のセキュリティ機能です。これにより、新しいウォレットアドレスのセットが作成されます。 バックアップ用のカードまたはリングを追加 カードをスキャン カード #%d をスキャン @@ -790,7 +790,7 @@ 追加しようとしているカードには、すでに別のウォレットが作成されています。このウォレットに資金がある場合は、それを引き出してからこのカードをリセットし、バックアップとして追加してください。 ウォレットを保存する バックアップの作成 - 生体認証を使用する + 生体認証 シードフレーズについてもっと読む これらの %d 単語を以下の順番通りに書き留め、安全かつ秘密の場所に保管してください。 @@ -852,6 +852,7 @@ 通貨で検索 即時 オンランプ機能を使用することにより、プロバイダの%1$sおよび%2$sに同意するものとします + サービスは外部プロバイダーによって提供されます。 \nTangemは責任を負いません。 買付金額は%s以下にしてください 買付金額は少なくとも%sである必要があります この通貨で利用可能なプロバイダーはありません @@ -1034,7 +1035,7 @@ 有効なアドレスではありません トークンの損失を避けるために、受信ウォレットアドレスが**%sネットワーク**上にあることを確認してください 送金先 - メモ/宛先タグは、同じネットワーク上の同じ受信者に送信された取引を区別するためのユニークなIDです。注意:メモを省略すると、資金の行き違いにつながる可能性があります。 + メモ / 宛先タグは、同じネットワーク上の同じ受信者に送信される取引を区別するためのユニークなIDです。 \n **注意: メモを省略すると、資金が紛失する可能性があります** メモ / 宛先タグは、暗号資産ネットワーク内の共有受信者への取引を分離するコードです。 注意:メモを忘れると資金が失われる可能性があります。 マイウォレット @@ -1245,6 +1246,10 @@ 受け取る トークンを選択 利用不可 + アカウントを作成してカードを発行 + Tangem Pay + ステータスを表示 + Tangem PayのKYC手続き進行中 カードをGET ウォレットに追加して、どこでもスマートフォンで支払いができます。 Apple Pay & Google Pay @@ -1321,9 +1326,15 @@ %sを使用するか、カード / リングをスキャンしてウォレットにアクセスしてください 接続に失敗しました:このdAppは、サポートされていないWallet Connectバージョン1.0を使用しています。正常に接続するには、dAppがWallet Connectバージョン2.0をサポートしていることを確認してください。 最新の機能とニュースをお届けします + 取引・スワップ・重要な更新に関するリアルタイム通知。 + 取引アラート 受信取引の通知を受け取る 新しいプロモーション情報をいち早く入手しましょう + 新しい機能や限定オファーへの早期アクセス。 + 機能およびニュースのアップデート プッシュ通知を使用しますか? + プッシュ通知を有効にすると、資金が到着するとすぐに通知されます + 取引を見逃さない 新しいウォレットを追加 このウォレットを忘れてもよろしいですか? エラーが発生しました。カードまたはリングをスキャンしてログインしてください。 @@ -1374,6 +1385,8 @@ Tangemアプリで誤ったカードまたはリングが選択されました Dappデータから取引を作成できませんでした。コード: %s 不明なエラーが発生しました。エラーコード: %d 。問題が解決しない場合は、お気軽にサポートにお問い合わせください。 + 複数の取引 + このプロセスを完了するには、Tangemデバイスを数回タップする必要があります。 WalletConnectセッションが開かれていません おっと。セッションがありません。 WalletConnectセッションのペアリングに失敗しました: %1$s @@ -1385,6 +1398,8 @@ このカードは、WalletConnectセッションの確立には使用できません。 このネットワークはサポートされていません。別のネットワークを選択してください。 ネットワークを選択 + 取引を処理中です + 送金しています... WalletConnectセッション dAppsに接続する WalletConnect @@ -1400,7 +1415,7 @@ ウォレットの設定方法を選択する Tangemウォレットを手に入れる準備はできた? 今すぐ購入 - Googleドライブのバックアップに保存されている既存のウォレットを復元する + Googleドライブのバックアップから既存のウォレットを復元する Googleドライブからインポート 既存のウォレットを追加 秘密鍵をオフラインで安全に保存する物理デバイス。 @@ -1420,9 +1435,9 @@ 今すぐ10 % オフで購入 1.3万種類以上の暗号資産にアクセス。ワンタップで買付、売却、スワップ、ステーキングが可能です。\nバックアップ用に最大3枚のカードを連携できます。 Tangemウォレットを見る - このウォレットを保護するためのシークレットコードです。ログインと署名に使用されます。 + このシークレットコードはウォレットを保護し、ログインや取引の署名に使用されます。 アクセスコードの設定・変更 - アクセスコードの変更 + アクセスコードを変更する ウォレットの受信取引とTangemの更新について通知を受け取る。 現在、Huaweiデバイスではプッシュ通知が機能しない可能性があります。現在、解決策の検討に取り組んでおり、今後のアップデートで修正をリリースする予定です。ご理解のほどよろしくお願いいたします。 取引通知 @@ -1628,13 +1643,15 @@ いいえ、すべて送信します %s XTZを減らす 次回ウォレットにチャージするときに手数料の増加を避けるには、金額を%s XTZ減らしてください。 + 資産残高に関するテキスト [プレースホルダー] + %sはAaveに預け入れられています 承認する 前回の承認に問題があったため、新しい承認が必要です。手続き方法を選択してください。 承認が必要 手数料が差し引かれ、あなたの資産は再び貸し出されます。 引き続き収益を得るには承認が必要です。 承認を確定する - 資産残高 + 資産残高に関するテキスト [プレースホルダー] あなたの%sはAaveに預けられています %s%を獲得 利用可能 @@ -1645,13 +1662,13 @@ 総収益 Aaveへの送金 Aaveの詳細を見る - あなたの%sはAaveに預けられています これは%sの現在の供給手数料です。実際のコストは受取画面に表示されます。 現在の手数料 今後の%sの入金はすべて、取引手数料が差し引かれて自動的にAaveに供給されます。 ネットワーク手数料が上限手数料を超えた場合、手数料が下がるまで取引は成立しません。この制限は後で変更できます。 最大手数料 手数料ポリシー + ここに説明を入力してください。1〜3行が理想的です。[プレースホルダー] トークン承認が必要 アカウントへの入金はすべて自動的にAaveに貸し出されます。 残高は自動的に計算されます diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 2adc2175b5..8c66048afe 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -991,7 +991,7 @@ Неверный адрес Убедитесь, что адрес получателя находится **в сети %s**, чтобы избежать потери отправляемых средств Отправить - Мемо/ Код назначения - это код, разделяющий транзакции к общему получателю в сети криптовалют. Внимание: отсутствие мемо может привести к потере средств. + Мемо/ Код назначения - это код, разделяющий транзакции к общему получателю в сети криптовалют.\n**Внимание: отсутствие мемо может привести к потере средств.** Memo / Destination Tag — это код, разделяющий транзакции, отправляемые одному и тому же получателю в криптовалютной сети. Внимание: отсутствие Memo может привести к потере средств. Мои кошельки @@ -1096,7 +1096,7 @@ Реинвестируйте свои заработанные награды в вашу застейканную сумму, увеличивая потенциальный доход Рестейк позволяет вам переместить средства из одного валидатора в другого без необходимости выхода из стейкинга. Вы собираетесь застейкать весь баланс, рекомендуем оставить небольшую сумму для оплаты комиссии сети при выходе из стейкинга или получении награды. - Чтобы начать стейкинг в TON, сначала осуществите исходящую транзакцию на любую сумму — это активирует ваш кошелек. + Чтобы начать стейкинг в TON, сначала отправьте небольшую транзакцию на свой же адрес — это активирует ваш кошелёк. До 0.2 TON может потребоваться сверх сетевой комиссии для завершения транзакции. Неиспользованная часть будет возвращена. Для выполнения операции требуется дополнительно 0.2 TON, помимо сетевой комиссии. Пожалуйста, пополните баланс. Требуется резерв TON 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 a9c4cfc398..90e59315d2 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -906,7 +906,7 @@ Недійсна адреса Переконайтеся, що адреса отримувача знаходиться **в мережі %s**, щоб уникнути втрати ваших коштів. Надіслати до - Memo/ Тег призначення — це унікальний ідентифікатор для розрізнення транзакцій, надісланих тому самому одержувачу в тій самій мережі. Застереження: відсутність тегу може призвести до втрати коштів. + Memo/ Тег призначення — це унікальний ідентифікатор для розрізнення транзакцій, надісланих тому самому одержувачу в тій самій мережі.\n**Застереження: відсутність тегу може призвести до втрати коштів.** Мемо / Destination Tag — це код, що розділяє транзакції до спільного одержувача в криптовалютній мережі. Увага: відсутність Memo може призвести до втрати коштів. Мої гаманці diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index f276d1abc5..e12a6bbfa6 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -1057,7 +1057,7 @@ Not a valid address Ensure the recipient\'s address is on **the %s network** to avoid losing your funds Send to - A Memo/Destination Tag is a unique ID for differentiating transactions sent to the same recipient on the same network. Caution: Omitting a memo may lead to misplaced funds + A Memo/Destination Tag is a unique ID for differentiating transactions sent to the same recipient on the same network.\n**Caution: Omitting a memo may lead to misplaced funds** Memo / Destination Tag is a code separating transactions to a shared recipient in a crypto network. Caution: Missing a memo may lead to fund loss. My wallets @@ -1165,7 +1165,7 @@ Reinvests your earned rewards in your staked amount, increasing potential earnings. Restake lets you move your funds from one validator to another without the need to unstake You’re about to stake your entire balance. We recommend leaving a small amount to cover network fees for unstaking or claiming rewards. - To start staking in TON, first make an outgoing transaction of any amount — this will activate your wallet. + To start staking in TON, first send a small transaction to your own address — this will activate your wallet. Up to 0.2 TON may be required in addition to the network fee to complete the transaction. Any unused amount will be refunded. 0.2 TON is required to proceed with this operation, in addition to the network fee. Please top up your balance. TON reserve required @@ -1268,6 +1268,10 @@ You receive Choose token not available + Create account and issue a card + Tangem Pay + View Status + KYC in progress for Tangem Pay Get card Add to your wallet and pay with your phone anywhere. Apple Pay & Google Pay @@ -1710,13 +1714,15 @@ No, send all Reduce by %s XTZ To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ + Text about your money in balance [PLACEHOLDER] + Your %s is deposited in Aave Give Approve Something went wrong with your previous approval, so we need a new one. Choose how you’d like to proceed. Approve needed The fee will be taken out, and your assets will be lent again. To continue earning, approval is required. Confirm approval - Text about your money in balance + Text about your money in balance [PLACEHOLDER] Your %s is deposited in Aave Earn %s% Available @@ -1734,6 +1740,7 @@ If network fees rise above maximum fee, the transaction won’t go through until they decrease. You can change this limit later. Maximum fee Fee policy + Write description here. In one, two or three lines will be awesome. [PLACEHOLDER] Some token approve needed Every top-up of your account will be lended to Aave automatically. Your balance works automatically diff --git a/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/DefaultWalletManagersFacade.kt b/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/DefaultWalletManagersFacade.kt index 4999c1b188..bf3dcaa1c9 100644 --- a/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/DefaultWalletManagersFacade.kt +++ b/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/DefaultWalletManagersFacade.kt @@ -650,7 +650,7 @@ internal class DefaultWalletManagersFacade @Inject constructor( } } - override suspend fun checkUtxoConsolidationAvailability(userWalletId: UserWalletId, network: Network): Boolean { + override suspend fun checkSelfSendAvailability(userWalletId: UserWalletId, network: Network): Boolean { val blockchain = network.toBlockchain() val walletManager = getOrCreateWalletManager( userWalletId = userWalletId, @@ -658,7 +658,7 @@ internal class DefaultWalletManagersFacade @Inject constructor( derivationPath = network.derivationPath.value, ) ?: return false - return (walletManager as? UtxoBlockchainManager)?.allowConsolidation == true + return walletManager.isSelfSendAvailable } override suspend fun getNFTCollections(userWalletId: UserWalletId, network: Network): List { diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt b/domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt index f8376e3707..e46624f635 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt @@ -154,6 +154,11 @@ sealed class StakingAnalyticsEvent( data object TransactionError : StakingAnalyticsEvent( event = "Error - Transaction Rejected", ) + + data class UnitializedAddress(val token: String) : StakingAnalyticsEvent( + event = "Notice - Uninitialized Address", + params = mapOf(AnalyticsParam.TOKEN_PARAM to token), + ) } enum class StakeScreenSource { diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/IsUtxoConsolidationAvailableUseCase.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/IsSelfSendAvailableUseCase.kt similarity index 74% rename from domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/IsUtxoConsolidationAvailableUseCase.kt rename to domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/IsSelfSendAvailableUseCase.kt index dc8cef03b8..cf602e2959 100644 --- a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/IsUtxoConsolidationAvailableUseCase.kt +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/IsSelfSendAvailableUseCase.kt @@ -5,14 +5,14 @@ import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.models.wallet.UserWalletId /** - * Gets UTXO consolidation availability + * Gets self send availability */ -class IsUtxoConsolidationAvailableUseCase( +class IsSelfSendAvailableUseCase( private val walletManagersFacade: WalletManagersFacade, ) { suspend fun invokeSync(userWalletId: UserWalletId, network: Network) = - walletManagersFacade.checkUtxoConsolidationAvailability( + walletManagersFacade.checkSelfSendAvailability( userWalletId = userWalletId, network = network, ) diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ValidateWalletAddressUseCase.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ValidateWalletAddressUseCase.kt index f86486cc2c..88413f9891 100644 --- a/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ValidateWalletAddressUseCase.kt +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/usecase/ValidateWalletAddressUseCase.kt @@ -56,12 +56,11 @@ class ValidateWalletAddressUseCase( isCurrentAddress: (String) -> Boolean, ): AddressValidationResult { val decodedXAddress = BlockchainUtils.decodeRippleXAddress(address, network.rawId) - val isUtxoConsolidationAvailable = - walletManagersFacade.checkUtxoConsolidationAvailability(userWalletId, network) + val isSelfSendAvailable = walletManagersFacade.checkSelfSendAvailability(userWalletId, network) val addressToValidate = decodedXAddress?.address ?: address val current = isCurrentAddress(addressToValidate) - val isForbidSelfSend = current && !isUtxoConsolidationAvailable + val isForbidSelfSend = current && !isSelfSendAvailable val isValidAddress = walletAddressServiceRepository.validateAddress(userWalletId, network, addressToValidate) return when { diff --git a/domain/wallet-manager/src/main/kotlin/com/tangem/domain/walletmanager/WalletManagersFacade.kt b/domain/wallet-manager/src/main/kotlin/com/tangem/domain/walletmanager/WalletManagersFacade.kt index 744e98f336..26f486dbb3 100644 --- a/domain/wallet-manager/src/main/kotlin/com/tangem/domain/walletmanager/WalletManagersFacade.kt +++ b/domain/wallet-manager/src/main/kotlin/com/tangem/domain/walletmanager/WalletManagersFacade.kt @@ -243,12 +243,12 @@ interface WalletManagersFacade { suspend fun discardRequirements(userWalletId: UserWalletId, currency: CryptoCurrency): SimpleResult /** - * Indicates UTXO consolidation availability + * Indicates self send availability * * @param userWalletId selected user wallet * @param network availability for network */ - suspend fun checkUtxoConsolidationAvailability(userWalletId: UserWalletId, network: Network): Boolean + suspend fun checkSelfSendAvailability(userWalletId: UserWalletId, network: Network): Boolean suspend fun getNFTCollections(userWalletId: UserWalletId, network: Network): List diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt index 8d73d20253..c4385c59d6 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt @@ -20,7 +20,7 @@ import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase import com.tangem.domain.tokens.GetCryptoCurrencyUseCase import com.tangem.domain.tokens.GetNetworkAddressesUseCase -import com.tangem.domain.transaction.usecase.IsUtxoConsolidationAvailableUseCase +import com.tangem.domain.transaction.usecase.IsSelfSendAvailableUseCase import com.tangem.domain.transaction.usecase.ValidateWalletAddressUseCase import com.tangem.domain.transaction.usecase.ValidateWalletMemoUseCase import com.tangem.domain.txhistory.usecase.GetFixedTxHistoryItemsUseCase @@ -62,7 +62,7 @@ internal class SendDestinationModel @Inject constructor( private val getCryptoCurrencyUseCase: GetCryptoCurrencyUseCase, private val getNetworkAddressesUseCase: GetNetworkAddressesUseCase, private val getFixedTxHistoryItemsUseCase: GetFixedTxHistoryItemsUseCase, - private val isUtxoConsolidationAvailableUseCase: IsUtxoConsolidationAvailableUseCase, + private val isSelfSendAvailableUseCase: IsSelfSendAvailableUseCase, private val listenToQrScanningUseCase: ListenToQrScanningUseCase, private val parseQrCodeUseCase: ParseQrCodeUseCase, private val analyticsEventHandler: AnalyticsEventHandler, @@ -197,7 +197,7 @@ internal class SendDestinationModel @Inject constructor( waitForDelay(RECENT_LOAD_DELAY) { it } }.conflate(), ) { destinationWalletList, txHistoryList -> - val isUtxoConsolidationAvailable = isUtxoConsolidationAvailableUseCase.invokeSync( + val isSelfSendAvailable = isSelfSendAvailableUseCase.invokeSync( userWalletId = userWalletId, network = cryptoCurrency.network, ) @@ -206,7 +206,7 @@ internal class SendDestinationModel @Inject constructor( SendDestinationRecentListTransformer( cryptoCurrency = cryptoCurrency, senderAddress = senderAddresses.value.firstOrNull()?.address, - isUtxoConsolidationAvailable = isUtxoConsolidationAvailable, + isSelfSendAvailable = isSelfSendAvailable, destinationWalletList = destinationWalletList, txHistoryList = txHistoryList, ), diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/converters/SendRecipientWalletListConverter.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/converters/SendRecipientWalletListConverter.kt index 7eb6244a95..67b3584c57 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/converters/SendRecipientWalletListConverter.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/converters/SendRecipientWalletListConverter.kt @@ -13,7 +13,7 @@ import kotlinx.collections.immutable.toPersistentList internal class SendRecipientWalletListConverter( private val senderAddress: String?, - private val isUtxoConsolidationAvailable: Boolean, + private val isSelfSendAvailable: Boolean, ) : Converter, PersistentList> { override fun convert(value: List): PersistentList { @@ -31,7 +31,7 @@ internal class SendRecipientWalletListConverter( val isNotSameAddress = it.address != senderAddress val isNotBlankAddress = it.address.isNotBlank() - isNotBlankAddress && isCoin && (isNotSameAddress || isUtxoConsolidationAvailable) + isNotBlankAddress && isCoin && (isNotSameAddress || isSelfSendAvailable) } .groupBy { item -> item.name } .values.map { wallets -> diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/transformers/SendDestinationRecentListTransformer.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/transformers/SendDestinationRecentListTransformer.kt index aaa18babfe..c1c579cbd8 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/transformers/SendDestinationRecentListTransformer.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/transformers/SendDestinationRecentListTransformer.kt @@ -11,7 +11,7 @@ import com.tangem.utils.transformer.Transformer internal class SendDestinationRecentListTransformer( private val senderAddress: String?, private val cryptoCurrency: CryptoCurrency, - private val isUtxoConsolidationAvailable: Boolean, + private val isSelfSendAvailable: Boolean, private val destinationWalletList: List, private val txHistoryList: List, ) : Transformer { @@ -21,7 +21,7 @@ internal class SendDestinationRecentListTransformer( return state.copy( wallets = SendRecipientWalletListConverter( senderAddress = senderAddress, - isUtxoConsolidationAvailable = isUtxoConsolidationAvailable, + isSelfSendAvailable = isSelfSendAvailable, ).convert(destinationWalletList), recent = SendRecipientHistoryListConverter( cryptoCurrency = cryptoCurrency, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt index 81379472ab..d02e6fc773 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt @@ -261,6 +261,9 @@ internal class StakingModel @Inject constructor( return@launch } isInitialInfoStep && noBalanceState && !isAccountInitialized -> { + analyticsEventHandler.send(StakingAnalyticsEvent.UnitializedAddress( + token = cryptoCurrencyStatus.currency.symbol, + ),) stakingEventFactory.createInitializeAccountAlert() return@launch } diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index c481baf889..e18209bb3c 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 = "releases-5.29-1231" +tangemBlockchainSdk = "releases-5.29-1237" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "releases-5.29-565" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From c72fdf004d8b7e1787110d226d7fa5b0394e9268 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 23 Sep 2025 12:24:39 +0300 Subject: [PATCH 02/10] Updated on 2026-08-14 --- .../src/main/assets/configs/feature_toggles_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json index 711bf35291..6a91513972 100644 --- a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json @@ -57,7 +57,7 @@ }, { "name": "NEW_ONRAMP_MAIN_ENABLED", - "version": "5.29.0" + "version": "undefined" }, { "name": "ACCOUNTS_FEATURE_ENABLED", From bc8a0ba20d574c2a6bd283a5436810e66507b858 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 23 Sep 2025 13:36:18 +0300 Subject: [PATCH 03/10] Updated on 2026-08-14 --- ...InfoResponse.kt => PromoBannerResponse.kt} | 2 +- .../api/tangemTech/TangemTechApi.kt | 9 +++++++++ .../data/promo/DefaultPromoRepository.kt | 19 ++++++++++++++++++- ...seConverter.kt => PromoBannerConverter.kt} | 6 +++--- 4 files changed, 31 insertions(+), 5 deletions(-) rename core/datasource/src/main/java/com/tangem/datasource/api/promotion/models/{PromotionInfoResponse.kt => PromoBannerResponse.kt} (95%) rename data/promo/src/main/java/com/tangem/data/promo/converters/{PromoResponseConverter.kt => PromoBannerConverter.kt} (74%) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/promotion/models/PromotionInfoResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/promotion/models/PromoBannerResponse.kt similarity index 95% rename from core/datasource/src/main/java/com/tangem/datasource/api/promotion/models/PromotionInfoResponse.kt rename to core/datasource/src/main/java/com/tangem/datasource/api/promotion/models/PromoBannerResponse.kt index 668a77c321..90caaabe5a 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/promotion/models/PromotionInfoResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/promotion/models/PromoBannerResponse.kt @@ -4,7 +4,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -data class PromotionInfoResponse( +data class PromoBannerResponse( @Json(name = "name") val name: String, @Json(name = "all") val bannerState: BannerState?, ) { diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt index d173c69c57..3b08465384 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt @@ -1,6 +1,7 @@ package com.tangem.datasource.api.tangemTech import com.tangem.datasource.api.common.response.ApiResponse +import com.tangem.datasource.api.promotion.models.PromoBannerResponse import com.tangem.datasource.api.promotion.models.StoryContentResponse import com.tangem.datasource.api.tangemTech.models.* import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse @@ -163,4 +164,12 @@ interface TangemTechApi { @Header("If-None-Match") eTag: String? = null, ): ApiResponse // endregion + + // region promo banners + @GET("/v1/promotion") + suspend fun getPromoBanner( + @Query("programName") name: String, + @Header("Cache-Control") cacheControl: String = "max-age=600", + ): ApiResponse + // endregion } \ No newline at end of file diff --git a/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt b/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt index f58b3d0613..09b1d25af8 100644 --- a/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt +++ b/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt @@ -1,5 +1,6 @@ package com.tangem.data.promo +import com.tangem.data.promo.converters.PromoBannerConverter import com.tangem.data.promo.converters.StoryContentResponseConverter import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.tangemTech.TangemTechApi @@ -12,6 +13,7 @@ import com.tangem.datasource.local.preferences.utils.store import com.tangem.datasource.local.promo.PromoStoriesStore import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.promo.PromoRepository +import com.tangem.domain.promo.models.PromoBanner import com.tangem.domain.promo.models.PromoId import com.tangem.domain.promo.models.StoryContent import com.tangem.feature.referral.domain.ReferralRepository @@ -22,6 +24,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeoutOrNull +import com.tangem.utils.coroutines.runCatching internal class DefaultPromoRepository( private val tangemApi: TangemTechApi, @@ -32,6 +35,7 @@ internal class DefaultPromoRepository( ) : PromoRepository { private val storyContentConverter = StoryContentResponseConverter() + private val promoBannerConverter = PromoBannerConverter() override fun isReadyToShowWalletPromo(userWalletId: UserWalletId, promoId: PromoId): Flow { return appPreferencesStore.get( @@ -42,7 +46,11 @@ internal class DefaultPromoRepository( PromoId.Referral -> runCatching { !referralRepository.isReferralParticipant(userWalletId) && shouldShow }.getOrDefault(false) - PromoId.Sepa -> shouldShow + PromoId.Sepa -> { + val isActive = getSepaPromoBanner()?.isActive ?: false + + isActive && shouldShow + } } } } @@ -118,7 +126,16 @@ internal class DefaultPromoRepository( ) } + private suspend fun getSepaPromoBanner(): PromoBanner? { + return runCatching(dispatchers.io) { + promoBannerConverter.convert( + tangemApi.getPromoBanner(SEPA_NAME).getOrThrow(), + ) + }.getOrNull() + } + private companion object { + const val SEPA_NAME = "sepa" const val STORIES_LOAD_DELAY = 1000L } } \ No newline at end of file diff --git a/data/promo/src/main/java/com/tangem/data/promo/converters/PromoResponseConverter.kt b/data/promo/src/main/java/com/tangem/data/promo/converters/PromoBannerConverter.kt similarity index 74% rename from data/promo/src/main/java/com/tangem/data/promo/converters/PromoResponseConverter.kt rename to data/promo/src/main/java/com/tangem/data/promo/converters/PromoBannerConverter.kt index cc418e808c..1128472f33 100644 --- a/data/promo/src/main/java/com/tangem/data/promo/converters/PromoResponseConverter.kt +++ b/data/promo/src/main/java/com/tangem/data/promo/converters/PromoBannerConverter.kt @@ -1,13 +1,13 @@ package com.tangem.data.promo.converters -import com.tangem.datasource.api.promotion.models.PromotionInfoResponse +import com.tangem.datasource.api.promotion.models.PromoBannerResponse import com.tangem.domain.promo.models.PromoBanner import com.tangem.utils.converter.Converter import org.joda.time.DateTime -class PromoResponseConverter : Converter { +class PromoBannerConverter : Converter { - override fun convert(value: PromotionInfoResponse): PromoBanner? { + override fun convert(value: PromoBannerResponse): PromoBanner? { val bannerState = value.bannerState ?: return null return PromoBanner( name = value.name, From a733dd0e527a557d2fcce652a44e1a7ab44d90af Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 23 Sep 2025 13:36:37 +0300 Subject: [PATCH 04/10] Updated on 2026-08-14 --- .../tangem/datasource/di/OnrampStoreModule.kt | 16 ++++++ .../DefaultOnrampCurrentCountryByIPStore.kt | 22 ++++++++ .../DefaultOnrampSepaAvailabilityStore.kt | 20 +++++++ .../sepa/OnrampCurrentCountryByIPStore.kt | 9 +++ .../sepa/OnrampSepaAvailabilityStore.kt | 10 ++++ .../sepa/OnrampSepaAvailabilityStoreKey.kt | 11 ++++ .../components/notifications/Notification.kt | 14 ++++- .../data/onramp/DefaultOnrampRepository.kt | 55 +++++++++++++++---- .../tangem/data/onramp/di/OnrampDataModule.kt | 6 ++ .../domain/onramp/GetOnrampCountryUseCase.kt | 7 ++- .../onramp/OnrampSepaAvailableUseCase.kt | 3 - .../onramp/repositories/OnrampRepository.kt | 9 +-- .../domain/GetMultiWalletWarningsFactory.kt | 1 - 13 files changed, 158 insertions(+), 25 deletions(-) create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/DefaultOnrampCurrentCountryByIPStore.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/DefaultOnrampSepaAvailabilityStore.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampCurrentCountryByIPStore.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampSepaAvailabilityStore.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampSepaAvailabilityStoreKey.kt diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/OnrampStoreModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/OnrampStoreModule.kt index e786b22f21..6d392c4e90 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/OnrampStoreModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/OnrampStoreModule.kt @@ -11,6 +11,10 @@ import com.tangem.datasource.local.onramp.paymentmethods.DefaultOnrampPaymentMet import com.tangem.datasource.local.onramp.paymentmethods.OnrampPaymentMethodsStore import com.tangem.datasource.local.onramp.quotes.DefaultOnrampQuotesStore import com.tangem.datasource.local.onramp.quotes.OnrampQuotesStore +import com.tangem.datasource.local.onramp.sepa.DefaultOnrampCurrentCountryByIPStore +import com.tangem.datasource.local.onramp.sepa.DefaultOnrampSepaAvailabilityStore +import com.tangem.datasource.local.onramp.sepa.OnrampCurrentCountryByIPStore +import com.tangem.datasource.local.onramp.sepa.OnrampSepaAvailabilityStore import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -50,4 +54,16 @@ internal object OnrampStoreModule { fun provideOnrampCurrencies(): OnrampCurrenciesStore { return DefaultOnrampCurrenciesStore(dataStore = RuntimeDataStore()) } + + @Provides + @Singleton + fun provideOnrampSepaAvailableStore(): OnrampSepaAvailabilityStore { + return DefaultOnrampSepaAvailabilityStore(dataStore = RuntimeDataStore()) + } + + @Provides + @Singleton + fun provideOnrampCurrentCountryByIPStore(): OnrampCurrentCountryByIPStore { + return DefaultOnrampCurrentCountryByIPStore(dataStore = RuntimeDataStore()) + } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/DefaultOnrampCurrentCountryByIPStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/DefaultOnrampCurrentCountryByIPStore.kt new file mode 100644 index 0000000000..a2530e4208 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/DefaultOnrampCurrentCountryByIPStore.kt @@ -0,0 +1,22 @@ +package com.tangem.datasource.local.onramp.sepa + +import com.tangem.datasource.local.datastore.core.StringKeyDataStore +import com.tangem.datasource.local.datastore.core.StringKeyDataStoreDecorator +import com.tangem.domain.onramp.model.OnrampCountry + +internal class DefaultOnrampCurrentCountryByIPStore( + val dataStore: StringKeyDataStore, +) : OnrampCurrentCountryByIPStore, StringKeyDataStoreDecorator( + wrappedDataStore = dataStore, +) { + + override suspend fun getSyncOrNull(): OnrampCountry? { + return getSyncOrNull(Unit) + } + + override suspend fun store(value: OnrampCountry) { + return store(Unit, value) + } + + override fun provideStringKey(key: Unit) = "KEY" +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/DefaultOnrampSepaAvailabilityStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/DefaultOnrampSepaAvailabilityStore.kt new file mode 100644 index 0000000000..9e8c14dff4 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/DefaultOnrampSepaAvailabilityStore.kt @@ -0,0 +1,20 @@ +package com.tangem.datasource.local.onramp.sepa + +import com.tangem.datasource.local.datastore.core.StringKeyDataStore +import com.tangem.datasource.local.datastore.core.StringKeyDataStoreDecorator + +internal class DefaultOnrampSepaAvailabilityStore( + val dataStore: StringKeyDataStore, +) : OnrampSepaAvailabilityStore, StringKeyDataStoreDecorator( + wrappedDataStore = dataStore, +) { + override fun provideStringKey(key: OnrampSepaAvailabilityStoreKey) = with(key) { + buildString { + append(userWallet.walletId.toString()) + append("_") + append(country.code) + append("_") + append(cryptoCurrency.id.value) + } + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampCurrentCountryByIPStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampCurrentCountryByIPStore.kt new file mode 100644 index 0000000000..cf05f2046d --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampCurrentCountryByIPStore.kt @@ -0,0 +1,9 @@ +package com.tangem.datasource.local.onramp.sepa + +import com.tangem.domain.onramp.model.OnrampCountry + +interface OnrampCurrentCountryByIPStore { + suspend fun getSyncOrNull(): OnrampCountry? + suspend fun store(value: OnrampCountry) + suspend fun clear() +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampSepaAvailabilityStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampSepaAvailabilityStore.kt new file mode 100644 index 0000000000..6ae1bd2af0 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampSepaAvailabilityStore.kt @@ -0,0 +1,10 @@ +package com.tangem.datasource.local.onramp.sepa + +import kotlinx.coroutines.flow.Flow + +interface OnrampSepaAvailabilityStore { + suspend fun getSyncOrNull(key: OnrampSepaAvailabilityStoreKey): Boolean? + fun get(key: OnrampSepaAvailabilityStoreKey): Flow + suspend fun store(key: OnrampSepaAvailabilityStoreKey, value: Boolean) + suspend fun clear() +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampSepaAvailabilityStoreKey.kt b/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampSepaAvailabilityStoreKey.kt new file mode 100644 index 0000000000..301c4e83ef --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/onramp/sepa/OnrampSepaAvailabilityStoreKey.kt @@ -0,0 +1,11 @@ +package com.tangem.datasource.local.onramp.sepa + +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.onramp.model.OnrampCountry + +data class OnrampSepaAvailabilityStoreKey( + val userWallet: UserWallet, + val country: OnrampCountry, + val cryptoCurrency: CryptoCurrency, +) \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt index 93f5aefdf0..50f8841ef5 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt @@ -27,10 +27,12 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp import com.tangem.core.ui.R import com.tangem.core.ui.components.* import com.tangem.core.ui.components.buttons.common.TangemButtonSize import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resolveAnnotatedReference import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.res.TangemTheme @@ -216,7 +218,7 @@ internal fun TextsBlock( SpacerH(height = TangemTheme.dimens.spacing2) } - val subtitleText = subtitle.resolveReference() + val subtitleText = subtitle.resolveAnnotatedReference() if (subtitleText.isNotEmpty()) { Text( text = subtitleText, @@ -459,5 +461,15 @@ private class NotificationConfigProvider : CollectionPreviewParameterProvider { - return Either.catch { repository.getDefaultCountrySync() ?: repository.getCountryByIp(userWallet) } + return Either.catch { + repository.getDefaultCountrySync() ?: repository.getCountryByIp( + userWallet = userWallet, + fromCache = true, + ) + } .mapLeft(errorResolver::resolve) } } \ No newline at end of file diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSepaAvailableUseCase.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSepaAvailableUseCase.kt index ad7c22bfaa..6fd0b223d9 100644 --- a/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSepaAvailableUseCase.kt +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSepaAvailableUseCase.kt @@ -6,7 +6,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.onramp.repositories.OnrampRepository import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.onramp.model.OnrampCountry -import com.tangem.domain.onramp.model.OnrampCurrency class OnrampSepaAvailableUseCase( private val repository: OnrampRepository, @@ -14,7 +13,6 @@ class OnrampSepaAvailableUseCase( suspend operator fun invoke( userWallet: UserWallet, - currency: OnrampCurrency, country: OnrampCountry, cryptoCurrency: CryptoCurrency, ): Boolean { @@ -25,7 +23,6 @@ class OnrampSepaAvailableUseCase( return Either.catch { repository.hasSepaMethod( userWallet = userWallet, - currency = currency, country = country, cryptoCurrency = cryptoCurrency, ) diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampRepository.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampRepository.kt index 2dad8a9e87..268ade4d37 100644 --- a/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampRepository.kt +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampRepository.kt @@ -13,14 +13,9 @@ interface OnrampRepository { fun getCurrencies(): Flow> fun getCountries(): Flow> suspend fun getCountriesSync(): List? - suspend fun getCountryByIp(userWallet: UserWallet): OnrampCountry + suspend fun getCountryByIp(userWallet: UserWallet, fromCache: Boolean = false): OnrampCountry suspend fun getStatus(userWallet: UserWallet, txId: String): OnrampStatus - suspend fun hasSepaMethod( - userWallet: UserWallet, - currency: OnrampCurrency, - country: OnrampCountry, - cryptoCurrency: CryptoCurrency, - ): Boolean + suspend fun hasSepaMethod(userWallet: UserWallet, country: OnrampCountry, cryptoCurrency: CryptoCurrency): Boolean suspend fun fetchCurrencies(userWallet: UserWallet) suspend fun fetchCountries(userWallet: UserWallet): List suspend fun fetchPaymentMethodsIfAbsent(userWallet: UserWallet) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt index 14395672c1..7de4aeda99 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt @@ -254,7 +254,6 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( val isSepaAvailable = onrampSepaAvailableUseCase( userWallet = userWallet, country = country, - currency = country.defaultCurrency, cryptoCurrency = bitcoinCurrency, ) From ec989ca2d04feb643d2147f8d8cb23a663c16533 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 23 Sep 2025 13:38:05 +0300 Subject: [PATCH 05/10] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index ad46a043f9..5cf863d2ad 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit ad46a043f9b98b4f4577f906920532cb370c15d4 +Subproject commit 5cf863d2ad68d89a111520aca3504fe9db234c82 From a237c5c029f0cbba39bf270de262894a83104e83 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 23 Sep 2025 15:40:02 +0300 Subject: [PATCH 06/10] Updated on 2026-08-14 --- .../impl/child/create/model/OnboardingNoteCreateWalletModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/child/create/model/OnboardingNoteCreateWalletModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/child/create/model/OnboardingNoteCreateWalletModel.kt index 26cc7fab20..efecb19956 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/child/create/model/OnboardingNoteCreateWalletModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/note/impl/child/create/model/OnboardingNoteCreateWalletModel.kt @@ -63,7 +63,6 @@ internal class OnboardingNoteCreateWalletModel @Inject constructor( when (result) { is CompletionResult.Success -> { Analytics.send(OnboardingEvent.CreateWallet.WalletCreatedSuccessfully()) - cardRepository.startCardActivation(scanResponse.card.cardId) createWalletAndNavigateBackWithDone(scanResponse.copy(card = result.data.card)) } is CompletionResult.Failure -> _uiState.update { From 3b666039ad4e6ccf69ddab2582ef8d3b7860eddc Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 24 Sep 2025 10:52:05 +0300 Subject: [PATCH 07/10] Updated on 2026-08-14 --- .../managetokens/utils/list/ManageTokensUiManager.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUiManager.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUiManager.kt index 49919e627d..410ac938d0 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUiManager.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUiManager.kt @@ -70,8 +70,11 @@ internal class ManageTokensUiManager( val updatedBatch = uiBatchToUpdate.copy( data = data.mapIndexed { index, item -> - if (item == currencyBatch.data[index]) { - return@mapIndexed uiBatchToUpdate.data[index] + val uiBatch = uiBatchToUpdate.data.getOrNull(index) + if (item == currencyBatch.data.getOrNull(index) && + uiBatch != null + ) { + return@mapIndexed uiBatch } val previousUiItem = uiBatchToUpdate.data.getOrNull(index) From 98c01df61881be31416b67e83aa73aa4b651d377 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 24 Sep 2025 10:55:25 +0300 Subject: [PATCH 08/10] Updated on 2026-08-14 --- .../environment/converter/BlockchainSDKConfigConverter.kt | 1 + .../local/config/environment/models/EnvironmentConfigModel.kt | 1 + gradle/tangem_dependencies.toml | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/config/environment/converter/BlockchainSDKConfigConverter.kt b/core/datasource/src/main/java/com/tangem/datasource/local/config/environment/converter/BlockchainSDKConfigConverter.kt index c19f0204c0..cc0be2459f 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/config/environment/converter/BlockchainSDKConfigConverter.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/config/environment/converter/BlockchainSDKConfigConverter.kt @@ -44,6 +44,7 @@ internal object BlockchainSDKConfigConverter : Converter Date: Wed, 24 Sep 2025 07:55:42 +0000 Subject: [PATCH 09/10] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 4e84217654..fa358b8aed 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,9 +5,9 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.29-1238" +tangemBlockchainSdk = "develop-1236" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "releases-5.29-565" +tangemCardSdk = "develop-564" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem12" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ From 9e1c8500cc05d3e2ae43084108beeca5b5d6a077 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 24 Sep 2025 15:29:08 +0500 Subject: [PATCH 10/10] Updated on 2026-08-14 --- .../yield/supply/DefaultYieldSupplyTransactionRepository.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyTransactionRepository.kt b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyTransactionRepository.kt index ea544fed18..cbc1107bd4 100644 --- a/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyTransactionRepository.kt +++ b/data/yield-supply/src/main/java/com/tangem/data/yield/supply/DefaultYieldSupplyTransactionRepository.kt @@ -83,7 +83,7 @@ internal class DefaultYieldSupplyTransactionRepository( walletManager = walletManager, cryptoCurrency = cryptoCurrency, callData = callData, - destinationAddress = walletManager.getYieldContract(), + destinationAddress = walletManager.getYieldModuleAddress(), amount = BigDecimal.ZERO.convertToSdkAmount(cryptoCurrencyStatus), fee = fee, ) @@ -175,7 +175,7 @@ internal class DefaultYieldSupplyTransactionRepository( blockchain = cryptoCurrency.network.toBlockchain(), derivationPath = cryptoCurrency.network.derivationPath.value, ) ?: error("Wallet manager not found") - walletManager.calculateYieldContract() + walletManager.calculateYieldModuleAddress() }.onFailure(Timber::e).getOrNull() } @@ -188,7 +188,7 @@ internal class DefaultYieldSupplyTransactionRepository( blockchain = cryptoCurrency.network.toBlockchain(), derivationPath = cryptoCurrency.network.derivationPath.value, ) ?: error("Wallet manager not found") - walletManager.getYieldContract() + walletManager.getYieldModuleAddress() }.onFailure(Timber::e).getOrNull() }