From e660ac89f875cd7dcbb40d3e93d1189a5dde779e Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 21 Nov 2024 11:52:38 +0300 Subject: [PATCH 01/22] Updated on 2026-08-14 --- gradle/dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index a57d4ded92..489719b73a 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -87,7 +87,7 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.18-869" +tangemBlockchainSdk = "release-app_5.18-870" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.18-402" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From 3fc2815385ff0ba5bcadced4ee92978a25a7e3c6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 21 Nov 2024 11:37:02 +0200 Subject: [PATCH 02/22] 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 adbdabe422..f859554840 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit adbdabe422b0513640d1750f276298683d342f61 +Subproject commit f859554840df30c25a8fe266de2db7ef71cf5652 From dcb83d1a5141190090709bb6691113d58b49acce Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 21 Nov 2024 14:14:45 +0300 Subject: [PATCH 03/22] Updated on 2026-08-14 --- .../domain/WcSessionRequestConverter.kt | 4 ++- .../mapper/SolanaTransactionMappings.kt | 30 ---------------- .../models/solana/SolanaTransactionRequest.kt | 35 ++----------------- 3 files changed, 5 insertions(+), 64 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/mapper/SolanaTransactionMappings.kt diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt index 367d7b6a9e..04bab1fa69 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt @@ -163,7 +163,9 @@ internal class WcSessionRequestConverter( return sessionsRepository.loadSessions(userWalletId) .firstOrNull { it.topic == sessionRequest.topic } ?.accounts?.firstOrNull { - it.chainId == sessionRequest.chainId && it.walletAddress.lowercase() == walletAddress?.lowercase() + // if walletAddress == null take first account + it.chainId == sessionRequest.chainId && + (walletAddress == null || it.walletAddress.lowercase() == walletAddress.lowercase()) }?.derivationPath } diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/mapper/SolanaTransactionMappings.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/mapper/SolanaTransactionMappings.kt deleted file mode 100644 index c97506bb7e..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/mapper/SolanaTransactionMappings.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.tangem.tap.domain.walletconnect2.domain.mapper - -import com.tangem.blockchain.blockchains.solana.solanaj.core.SolanaTransaction -import com.tangem.tap.domain.walletconnect2.domain.models.solana.SolanaTransactionRequest -import org.p2p.solanaj.core.AccountMeta -import org.p2p.solanaj.core.PublicKey -import org.p2p.solanaj.core.TransactionInstruction - -internal fun SolanaTransactionRequest.mapToTransaction(): SolanaTransaction { - val from = PublicKey(feePayer) - val instructions = instructions.map(SolanaTransactionRequest.Instruction::mapToInstruction) - - return SolanaTransaction(from) - .apply { - instructions.forEach(::addInstruction) - setRecentBlockHash(recentBlockhash) - } -} - -private fun SolanaTransactionRequest.Instruction.mapToInstruction() = TransactionInstruction( - /* programId = */ PublicKey(programId), - /* keys = */ keys.map(SolanaTransactionRequest.Key::mapToAccountMeta), - /* data = */ data.toByteArray(), -) - -private fun SolanaTransactionRequest.Key.mapToAccountMeta() = AccountMeta( - /* publicKey = */ PublicKey(publicKey), - /* isSigner = */ isSigner, - /* isWritable = */ isWritable, -) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/solana/SolanaTransactionRequest.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/solana/SolanaTransactionRequest.kt index b77ecffae0..bed9fd3897 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/solana/SolanaTransactionRequest.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/models/solana/SolanaTransactionRequest.kt @@ -7,39 +7,8 @@ import com.tangem.tap.domain.walletconnect2.domain.WcRequestData @JsonClass(generateAdapter = true) data class SolanaTransactionRequest( @Json(name = "feePayer") - val feePayer: String, - - @Json(name = "recentBlockhash") - val recentBlockhash: String, - - @Json(name = "instructions") - val instructions: List, + val feePayer: String?, @Json(name = "transaction") val transaction: String, -) : WcRequestData { - - @JsonClass(generateAdapter = true) - data class Instruction( - @Json(name = "programId") - val programId: String, - - @Json(name = "data") - val data: String, - - @Json(name = "keys") - val keys: List, - ) - - @JsonClass(generateAdapter = true) - data class Key( - @Json(name = "isSigner") - val isSigner: Boolean, - - @Json(name = "isWritable") - val isWritable: Boolean, - - @Json(name = "pubkey") - val publicKey: String, - ) -} \ No newline at end of file +) : WcRequestData \ No newline at end of file From fc2b63bdb9a683a83384967d6b534d6c19e533b7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 21 Nov 2024 18:10:30 +0300 Subject: [PATCH 04/22] Updated on 2026-08-14 --- .../details/ui/walletconnect/dialogs/SignTransactionDialog.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/SignTransactionDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/SignTransactionDialog.kt index a21b7a4d75..d985adc26b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/SignTransactionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/SignTransactionDialog.kt @@ -11,7 +11,8 @@ import com.tangem.wallet.R internal object SignTransactionDialog { fun create(preparedData: WcPreparedRequest.SignTransaction, context: Context): AlertDialog { - val message = context.getString(R.string.wallet_connect_alert_sign_message, "") + val signMessage = context.getString(R.string.wallet_connect_alert_sign_message, "") + val message = "${preparedData.preparedRequestData.dAppName}\n$signMessage" return AlertDialog.Builder(context).apply { setTitle(context.getString(R.string.wallet_connect_title)) setMessage(message) From 5dcf2a986e3904958b5256cc319c067c8d8a39d2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 22 Nov 2024 14:54:07 +0300 Subject: [PATCH 05/22] Updated on 2026-08-14 --- .../features/details/redux/DetailsReducer.kt | 3 +++ core/res/src/main/res/values-de/strings.xml | 3 ++- core/res/src/main/res/values-es/strings.xml | 13 ++++++++---- core/res/src/main/res/values-fr/strings.xml | 20 +++++++++++++++++-- core/res/src/main/res/values-ja/strings.xml | 1 + core/res/src/main/res/values-ru/strings.xml | 4 ++++ .../src/main/res/values-uk-rUA/strings.xml | 3 ++- core/res/src/main/res/values/strings.xml | 6 +++++- 8 files changed, 44 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index 1f56b4bf2f..e9b44c3240 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt @@ -53,6 +53,9 @@ private fun handlePrepareScreen(action: DetailsAction.PrepareScreen): DetailsSta store.inject(DaggerGraphState::balanceHidingRepository) .getBalanceHidingSettings().isHidingEnabledInSettings }, + needEnrollBiometrics = runBlocking { + runCatching(tangemSdkManager::needEnrollBiometrics).getOrNull() ?: false + }, ), ) } diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index d8c34ccdc5..79686ce460 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -296,7 +296,7 @@ Empfohlen Gekauft %s Kauf %s - Kauf %s... + Kauf %s… Keine Token gefunden. Bitte versuche eine andere Anfrage ID: %s Transaktions-ID kopiert @@ -908,6 +908,7 @@ Diese Aktion ist unumkehrbar. Du hast keinen Zugriff mehr auf die alte Wallet. Tippe auf die Doppelkarte oder Ring mit der Nummer %s und entferne sie erst am Ende des Vorgangs. Verwende %s oder scanne eine Karte oder Ring, um Zugriff auf deine Wallet zu erhalten. + Verbindung fehlgeschlagen: Diese dApp verwendet Wallet Connect Version 1.0, die nicht unterstützt wird. Bitte stelle sicher, dass die dApp Wallet Connect Version 2.0 unterstützt, um eine erfolgreiche Verbindung herzustellen. Bleib auf dem Laufenden mit den neuesten Funktionen und Neuigkeiten Sei der Erste, der von neuen Aktionen erfährt Möchtest du Push-Benachrichtigungen verwenden? diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index b77f4a6456..38c53c5104 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -294,6 +294,9 @@ No disponible para este par Permiso requerido Recomendado + Comprado %s + Comprando %s + Comprando %s... No se encontraron fichas. Por favor intenta con otra solicitud ID : %s ID de transacción copiado @@ -429,7 +432,6 @@ El valor teórico total de una criptomoneda si todas las monedas que podrían existir estuvieran en circulación, incluidas las que actualmente no circulan. Valoración totalmente diluida Dato de Genesis - Vacío Alto Titulares El cambio en el número de poseedores de tokens dentro de un período de tiempo específico @@ -440,7 +442,6 @@ El cambio en la cantidad de liquidez disponible para el token durante el período de tiempo especificado Liquidez Índice de liquidez - Vacío Listado en Bajo Capital. de mercado @@ -514,12 +515,12 @@ Creando un backup Leer más sobre seed phrase - Vacío + Escriba estas %d palabras en el orden que se indica a continuación y guárdelas en un lugar seguro y secreto. Su seed phrase - Vacío + %d palabras Para importar su billetera, ingrese su seed phrase en el campo de abajo @@ -907,6 +908,7 @@ Esta acción es irreversible. No tendrá acceso la billetera antigua. Toque la tarjeta gemela con el número %s y no la retira hasta el final de la operación Use %s o escanee una tarjeta/anillo para tener acceso a su billetera + Error de conexión: Esta dApp utiliza la versión 1.0 de Wallet Connect, que no es compatible. Asegúrese de que la dApp sea compatible con la versión 2.0 de Wallet Connect para conectarse correctamente. Manténgase actualizado con las últimas funciones y noticias Sea el primero en enterarte de nuevas promociones ¿Quiere utilizar\nnotificaciones push? @@ -1006,6 +1008,9 @@ Este token debe estar asociado con su cuenta de Hedera antes de poder recibirlo. Asocie su token No hay suficiente %s. Recargue su cuenta de Hedera para asociar este token + ¿Está seguro(a) de que desea cancelar la transacción? No podrá volver a intentar realizarla. + Su transacción con un importe de %1$s %2$s no se ha completado. Puede volver a intentarlo para completarla. + Tiene una transacción sin terminar Solo quedan %s firmas en esta tarjeta. Deba retirar todos sus fondos. Recuento de firmas bajo Los tokens en diferentes redes pueden tener direcciones diferentes. Verifique que su dirección coincida con la red cuando transfieras fondos. diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index 346d3081e5..d2e529b9cb 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -180,6 +180,7 @@ Conditions d\'utilisation Aujourd\'hui La transaction a échoué + Statut de la transaction Transactions Transfert Je comprends @@ -187,6 +188,7 @@ Inaccessible Unstakez semaine + avec Oui Adresse du contrat copiée ! Réseaux disponibles @@ -292,6 +294,9 @@ Indisponible pour cette paire Permission requise Recommandé + Acheté %s + Achat en cours %s + Achat en cours %s... Aucun jeton trouvé. Veuillez essayer une autre demande ID : %s ID de transaction copié @@ -453,6 +458,7 @@ Performance des prix Dépôt Score de sécurité + Le score de sécurité d\'un jeton est une mesure qui évalue le niveau de sécurité d\'une blockchain ou d\'un jeton en fonction de divers facteurs. Ceci est compilé à partir des sources répertoriées ci-dessous. Social Approvisionnement total Le nombre maximal de pièces ou de jetons pouvant exister pour une crypto-monnaie particulière @@ -566,12 +572,15 @@ Le montant à acheter doit être au moins %s Aucun fournisseur disponible pour cette devise Payer avec + Vous pourrez finaliser votre transaction sur le fournisseur tiers, %s + Redirection vers %s... Nos services ne sont pas disponibles dans ce pays Modifiez-le ou confirmez-le Votre résidence a été identifiée comme Résidence Veuillez sélectionner le bon pays pour garantir des options de paiement et des services précis. Paramètres + Vous pouvez vérifier l\'état de la transaction à partir de la page du jeton Via Grouper Par solde @@ -596,9 +605,9 @@ pour le portefeuille %d pour les portefeuilles %d - Obtiendras ^^%1$s^^ pour chaque portefeuille acheté par votre ami sur votre adresse de réseau %2$s %3$s ^^30 jours après^^ + Obtiendrez ^^%1$s^^ pour chaque portefeuille acheté par votre ami sur votre adresse de réseau %2$s %3$s ^^30 jours après^^ Vous - Obtiendrez + Obtiendra lors de l\'achat d\'un portefeuille sur tangem.com %s réduction Votre ami @@ -899,6 +908,7 @@ Cette action est irréversible. Vous n\'aurez plus accès à l\'ancien portefeuille. Appuyez sur la carte jumelle avec le numéro %s et ne la retirez pas jusqu\'à la fin de l\'opération Utilisez %s ou scannez une carte/bague pour avoir accès à votre portefeuille + Échec de la connexion : Cette dApp utilise Wallet Connect version1.0, qui n\'est pas prise en charge. Veuillez vous assurer que la dApp prend en charge Wallet Connect version2.0 pour réussir la connexion. Restez à jour avec les dernières fonctionnalités et actualités Soyez le premier informé des nouvelles promotions Souhaitez-vous utiliser les\nnotifications push? @@ -950,6 +960,9 @@ %s réseau L\'adresse a été copiée avec succès Pas de connexion internet + Obtenez-le maintenant avec 10 %% de réduction + Accédez à plus de 13 000 cryptomonnaies. Achetez, vendez, échangez et stakez en un seul clic.\nAssociez jusqu\'à trois cartes pour une sauvegarde. + Découvrez le Portefeuille Tangem Paramètres du portefeuille Tangem Utilisez %s ou scannez une carte/bague pour déverrouiller l\'accès à votre portefeuille @@ -995,6 +1008,9 @@ Ce jeton doit être associé à votre compte Hedera avant que vous puissiez le recevoir Associez votre jeton %s insuffisant. Renflouez votre compte Hedera pour associer ce jeton + Êtes-vous sûr(e) de vouloir annuler la transaction ? Vous ne pourrez plus réessayer. + Votre transaction d\'un montant de %1$s %2$s n\'a pas été finalisée. Vous pouvez réessayer plus tard pour la finaliser. + Vous avez une transaction inachevée Il ne reste que %s signatures sur cette carte. Vous devez retirer tous vos fonds. Faible nombre de signatures Les jetons sur différents réseaux peuvent avoir des adresses différentes. Vérifiez bien que votre adresse correspond au réseau lorsque vous transférez des fonds. diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 0c5037ec1c..9f3c536b40 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -898,6 +898,7 @@ この操作は元に戻せません。古いウォレットにはアクセスできなくなります。 番号%sのツインカードをタップし、操作が終了するまで取り外さないでください。 %sを使用するか、カード / リングをスキャンしてウォレットにアクセスしてください + 接続に失敗しました:このdAppは、サポートされていないWallet Connectバージョン1.0を使用しています。正常に接続するには、dAppがWallet Connectバージョン2.0をサポートしていることを確認してください。 最新の機能とニュースをお届けします 新しいプロモーション情報をいち早く入手しましょう プッシュ通知を使用しますか? diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 280a951d4b..dfbc4e21cc 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -297,6 +297,8 @@ Недоступно для этой пары Требуется разрешение Рекомендовано + Покупка %s + Покупка %s... Токены не найдены. Пожалуйста, попробуйте другой запрос ID: %s ID транзакции скопирован @@ -889,6 +891,7 @@ Обменять Недоступно для покупки Недоступно для продажи + Недоступно для обмена с %s контракт: %s У вас еще нет транзакций Не удалось загрузить историю транзакций.\nНажмите на кнопку перезагрузки, чтобы обновить информацию. @@ -913,6 +916,7 @@ Это действие необратимо. У вас не будет доступа к старому кошельку. Приложите twin-карту с номером %s и не убирайте до окончания операции Используйте %s или отсканируйте карту/кольцо, чтобы получить доступ к своему кошельку + Соединение не удалось: это dApp использует Wallet Connect версии 1.0, которая не поддерживается. Убедитесь, что dApp поддерживает Wallet Connect версии 2.0 для успешного подключения. Будьте в курсе новых функций и новостей Узнавайте первым о новых акциях Хотите использовать Push-уведомления? 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 c446190dcc..25e1a4419d 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -301,7 +301,7 @@ Потрібен дозвіл Рекомендовано Купив %s - Купівля %s... + Купівля %s Купівля %s... Токенів не знайдено. Будь ласка, спробуйте інший запит ID: %s @@ -927,6 +927,7 @@ Ця дія є незворотною. Ви не матимете доступу до старого гаманця. Прикладіть twin-картку з номером %s та не прибирайте її до завершення операції Використовуйте %s або відскануйте картку/кільце, щоб отримати доступ до свого гаманця + Не вдалося встановити з\'єднання: Цей dApp використовує Wallet Connect версії 1.0, яка не підтримується. Будь ласка, переконайтеся, що dApp підтримує Wallet Connect версії 2.0 для успішного підключення. Будьте в курсі останніх функцій та новин Дізнавайтеся першими про нові акції Бажаєте використовувати Push-повідомлення? diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 08a7924ae5..4f1dea27fa 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -1,7 +1,7 @@ Token not found in your portfolio? Check the Markets to find and add it for purchase - Token not found in your portfolio? Check the Markets to find and add it for sell + Token not found in your portfolio? Check the Markets to find and add it for selling Choose the Token Token not found in your portfolio? Check the Markets to find and add it for swap There are no available tokens to swap with the selected token. Please choose another one. @@ -590,8 +590,11 @@ Settings You have not given access to your camera Camera access denied + No memo required %1$s (%2$s) on %3$s network + Sending any other currency will result in its irreversible loss. Send only %s to this address. Sending any other currency will result in its irreversible loss. + Send only %s to this address. Transfer funds from any wallet or exchange Participate Failed to load the information about the referral program. Please try again later. @@ -908,6 +911,7 @@ This action is irreversible. You will not have access to the old wallet. Tap the twin card with number %s and do not remove until the end of the operation Use %s or scan a card/ring to have access to your wallet + Connection failed: This dApp uses Wallet Connect version 1.0, which is not supported. Please ensure the dApp supports Wallet Connect version 2.0 to connect successfully. Stay up to date with the latest features and news Be the first to know about new promotions Would you like to use\nPush-notifications? From b07d4788884b3fa9be9fba24f396db5802c6c8fe Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 22 Nov 2024 19:51:04 +0200 Subject: [PATCH 06/22] Updated on 2026-08-14 --- .../domain/GetSingleWalletWarningsFactory.kt | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt index 81e435fa5e..21f40750f2 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt @@ -9,6 +9,7 @@ import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.usecase.GetWalletsUseCase import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents @@ -25,6 +26,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor( private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase, private val isNeedToBackupUseCase: IsNeedToBackupUseCase, private val hasSingleWalletSignedHashesUseCase: HasSingleWalletSignedHashesUseCase, + private val getWalletsUseCase: GetWalletsUseCase, ) { private var readyForRateAppNotification = false @@ -36,22 +38,32 @@ internal class GetSingleWalletWarningsFactory @Inject constructor( flow = getPrimaryCurrencyStatusUpdatesUseCase(userWallet.walletId), flow2 = isReadyToShowRateAppUseCase().conflate(), flow3 = isNeedToBackupUseCase(userWallet.walletId).conflate(), - ) { primaryCurrencyStatus, isReadyToShowRating, isNeedToBackup -> + flow4 = getWalletsUseCase().conflate(), + ) { maybePrimaryCurrencyStatus, isReadyToShowRating, isNeedToBackup, userWallets -> readyForRateAppNotification = true buildList { - addCriticalNotifications(cardTypesResolver) - - addInformationalNotifications(cardTypesResolver, clickIntents) - - addWarningNotifications( - userWallet, - cardTypesResolver, - primaryCurrencyStatus, - isNeedToBackup, - clickIntents, + addCriticalNotifications( + cardTypesResolver = cardTypesResolver, ) - addRateTheAppNotification(isReadyToShowRating, clickIntents) + addInformationalNotifications( + userWallets = userWallets, + cardTypesResolver = cardTypesResolver, + clickIntents = clickIntents, + ) + + addWarningNotifications( + userWallet = userWallet, + cardTypesResolver = cardTypesResolver, + maybePrimaryCurrencyStatus = maybePrimaryCurrencyStatus, + isNeedToBackup = isNeedToBackup, + clickIntents = clickIntents, + ) + + addRateTheAppNotification( + isReadyToShowRating = isReadyToShowRating, + clickIntents = clickIntents, + ) }.toImmutableList() } } @@ -76,14 +88,19 @@ internal class GetSingleWalletWarningsFactory @Inject constructor( } private fun MutableList.addInformationalNotifications( + userWallets: List, cardTypesResolver: CardTypesResolver, clickIntents: WalletClickIntents, ) { + val userHasWalletOrWallet2 = userWallets.any { + val typesResolver = it.scanResponse.cardTypesResolver + typesResolver.isTangemWallet() || typesResolver.isWallet2() + } addIf( element = WalletNotification.NoteMigration( onClick = { clickIntents.onNoteMigrationButtonClick(NOTE_MIGRATION_URL) }, ), - condition = cardTypesResolver.isTangemNote(), + condition = cardTypesResolver.isTangemNote() && !userHasWalletOrWallet2, ) addIf( From 299f10a1f6cc06f544b31f92382c1cbcd8007975 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 25 Nov 2024 15:32:35 +0300 Subject: [PATCH 07/22] Updated on 2026-08-14 --- gradle/dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 489719b73a..e32d4d13c7 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -87,7 +87,7 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.18-870" +tangemBlockchainSdk = "release-app_5.18-872" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.18-402" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From 486f9a6c340501dd8df2c0e1714d21ccc481ee36 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 25 Nov 2024 14:50:39 +0300 Subject: [PATCH 08/22] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 11 ++++++++++- .../local/preferences/PreferencesDataStore.kt | 3 +++ .../preferences/utils/CleanupKeyMigration.kt | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/preferences/utils/CleanupKeyMigration.kt diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index cc4284cc7a..e456f93295 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -89,6 +89,7 @@ import kotlinx.coroutines.flow.* import timber.log.Timber import javax.inject.Inject import kotlin.coroutines.CoroutineContext +import kotlin.time.Duration.Companion.seconds lateinit var tangemSdkManager: TangemSdkManager lateinit var backupService: BackupService @@ -314,7 +315,11 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac private fun installAppTheme() { appThemeModeFlow = createAppThemeModeFlow() - val mode = runBlocking { appThemeModeFlow.first() } + val mode = runBlocking { + withTimeoutOrNull(APP_THEME_LOAD_TIMEOUT.seconds) { + appThemeModeFlow.first() + } ?: AppThemeMode.DEFAULT + } updateAppTheme(mode) } @@ -581,4 +586,8 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac .onRight { Timber.d("Submitting hashes succeeded") } } } + + companion object { + private const val APP_THEME_LOAD_TIMEOUT = 2 + } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesDataStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesDataStore.kt index 9e9b278b7e..9e326cc62c 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesDataStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesDataStore.kt @@ -10,6 +10,8 @@ import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.emptyPreferences import androidx.datastore.preferences.preferencesDataStoreFile import com.tangem.datasource.local.preferences.PreferencesDataStore.INSTANCE +import com.tangem.datasource.local.preferences.PreferencesKeys.APP_LOGS_KEY +import com.tangem.datasource.local.preferences.utils.CleanupKeyMigration import com.tangem.datasource.local.preferences.utils.SharedPreferencesKeyMigration import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob @@ -77,6 +79,7 @@ internal object PreferencesDataStore { legacyKeyName = LEGACY_DEFAULT_KEY_NAME, keyName = PreferencesKeys.BALANCE_HIDING_SETTINGS_KEY.name, ), + CleanupKeyMigration(key = APP_LOGS_KEY), ) } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/utils/CleanupKeyMigration.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/utils/CleanupKeyMigration.kt new file mode 100644 index 0000000000..8b5e3fa149 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/utils/CleanupKeyMigration.kt @@ -0,0 +1,18 @@ +package com.tangem.datasource.local.preferences.utils + +import androidx.datastore.core.DataMigration +import androidx.datastore.preferences.core.Preferences + +internal class CleanupKeyMigration(private val key: Preferences.Key) : DataMigration { + + override suspend fun cleanUp() { + // do nothing + } + + override suspend fun shouldMigrate(currentData: Preferences): Boolean = currentData.contains(key) + + override suspend fun migrate(currentData: Preferences): Preferences { + currentData.toMutablePreferences().remove(key) + return currentData + } +} \ No newline at end of file From b0694b67985897caab7cd7873d7df88a6dcf7465 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 26 Nov 2024 14:54:02 +0300 Subject: [PATCH 09/22] Updated on 2026-08-14 --- .../models/response/ExpressErrorResponse.kt | 6 ++++++ core/res/src/main/res/values-de/strings.xml | 5 +++-- core/res/src/main/res/values-es/strings.xml | 2 -- core/res/src/main/res/values-fr/strings.xml | 4 +--- core/res/src/main/res/values-ja/strings.xml | 8 +++++--- core/res/src/main/res/values-ru/strings.xml | 4 +--- .../res/src/main/res/values-uk-rUA/strings.xml | 2 -- core/res/src/main/res/values/strings.xml | 8 +++++--- .../swap/converters/ErrorsDataConverter.kt | 17 +++++++++++++++++ .../swap/domain/models/ExpressDataError.kt | 7 +++++++ .../com/tangem/feature/swap/ui/StateBuilder.kt | 18 ++++++++++++++---- .../com/tangem/feature/swap/utils/SwapUtils.kt | 7 +++++++ 12 files changed, 66 insertions(+), 22 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExpressErrorResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExpressErrorResponse.kt index d3e2fd0694..183965a431 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExpressErrorResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExpressErrorResponse.kt @@ -37,4 +37,10 @@ data class ExpressErrorValue( @Json(name = "expressFromDecimals") val expressFromDecimals: Int?, + + @Json(name = "fromAmount") + val fromAmount: String?, + + @Json(name = "fromAmountProvider") + val fromAmountProvider: 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 79686ce460..e278f45b3c 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -6,8 +6,6 @@ Token nicht in Deinem Portfolio gefunden? Überprüfe die Märkte, um es für Swaps zu finden und hinzuzufügen Es gibt keine verfügbaren Token, die mit dem ausgewählten Token getauscht werden können. Bitte wähle einen anderen. Kein verfügbares Paar - Du möchtest erhalten - Du möchtest tauschen Netzwerk wählen Token anlegen Token verwalten @@ -590,8 +588,11 @@ Einstellungen Du hast keinen Zugriff auf deine Kamera gewährt Kamerazugriff verweigert + Kein Memo erforderlich %1$s ( %2$s ) im %3$s Netzwerk + Das Senden einer anderen Währung führt zu deren irreversiblem Verlust. Sende nur %s an diese Adresse. Der Versand einer anderen Währung führt zu ihrem unwiderruflichen Verlust. + Sende nur %s an diese Adresse. Überweise Geld von einem anderen Wallet oder einer anderen Börse Teilnehmen Die Informationen zum Empfehlungsprogramm konnten nicht geladen werden. Bitte versuche es später noch einmal. diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index 38c53c5104..24e4fe0863 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -6,8 +6,6 @@ ¿No encuentras el token en tu billetera? Consulte los mercados para encontrarlo y agregarlo al intercambio No hay tokens disponibles para intercambiar con el token seleccionado. Por favor elige otro. No hay par disponible - Desea recibir - Quiere intercambiar Elige red Agregue un token personalizado Gestionar tokens diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index d2e529b9cb..2b0fc6e1be 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -6,8 +6,6 @@ Jeton non trouvé dans votre portefeuille ? Consultez les marchés pour le trouver et l\'ajouter à l\'échange Il n\'y a pas de token disponible pour échanger avec le token sélectionné. Veuillez en choisir un autre. Aucune paire disponible - Vous souhaitez recevoir - Vous souhaitez échanger Choisissez le réseau Ajouter un jeton personnalisé Gérer les jetons @@ -370,7 +368,7 @@ Choisissez un portefeuille Le portefeuille ne prend pas en charge plus d\'un réseau Pour acheter, échanger ou recevoir cet actif, ajoutez-le à votre portefeuille - Cet actif n\'est plus pris en charge dans le portefeuille + Cet actif n\'est pas pris en charge dans le portefeuille Cet actif n\'est pas disponible pour ce portefeuille Ajouter au portfolio Ajoutez un jeton diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 9f3c536b40..b3c7c07c53 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -6,8 +6,6 @@ ポートフォリオにトークンが見つかりませんか?マーケットから見つけ、スワップのために追加してください 選択したトークンと交換できるトークンがありません。別のトークンを選択してください。 利用可能なペアがありません - 受け取りたい - 交換したい ネットワークを選択 カスタムトークンの追加 トークンの管理 @@ -123,7 +121,7 @@ マーケット 遅い 速度と料金 - アドレスを取得する + アドレスを同期する プロバイダーへ移動 トークンへ移動 時間 @@ -557,6 +555,7 @@ アクセスコードの復元 同一のカード アクセスコード + プロバイダーは取引を促進し、スムーズで効率的なトークン交換を保証します 国で検索 利用不可 通貨で検索 @@ -582,8 +581,11 @@ 設定 カメラへのアクセスを許可していません。 カメラへのアクセスが拒否されました + メモ不要 %3$sネットワーク上の%1$s ( %2$s ) + 他の暗号資産を送信すると、取り返しのつかない損失が発生します。 このアドレスには%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 dfbc4e21cc..6e9a779cef 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -3,8 +3,6 @@ Выберите токен Нет доступных токенов для обмена с выбранным токеном, пожалуйста, выберите другой. Нет доступных пар - Вы хотите получить - Вы хотите обменять Выберите сеть Добавить токен Валюты @@ -129,7 +127,7 @@ По рынку Медленно Скорость и комиссия - Получить ваши адреса + Синхронизировать адреса К провайдеру Перейти в токен час 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 25e1a4419d..0422f45055 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -6,8 +6,6 @@ Токен не знайдено у вашому портфелі? Перевірте ринки, щоб знайти та додати його для обміну Немає доступних токенів для обміну з обраним токеном. Будь ласка, оберіть інший. Немає вільної пари - Ви хочете отримати - Ви хочете обміняти Оберіть мережу Додати токен Токени diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 4f1dea27fa..1f7c527b60 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -6,8 +6,8 @@ Token not found in your portfolio? Check the Markets to find and add it for swap There are no available tokens to swap with the selected token. Please choose another one. No available pair - You want to Receive - You want to Swap + Choose the Token you want to Receive + Choose the Token you want to Swap Choose network Add custom token Manage tokens @@ -126,7 +126,7 @@ Market Slow Speed and fee - Get your addresses + Synchronize addresses Go to provider Go to token hour @@ -251,6 +251,7 @@ Tangem offers token swaps via 3rd-party providers according to each provider\'s terms Choose provider An error occurred. Code: %s + Error %1$s. The selected provider cannot process the specified transaction. Please round the value up to %2$s or change it Selected provider is unavailable at the moment. Please try again later. (Code: %s) Swaps are unavailable at the moment. Please try again later. (Code: %s) Estimated amount @@ -565,6 +566,7 @@ Access code restore Identical cards Access code + Providers facilitate transactions, ensuring smooth and efficient token exchanges Search by country Unavailable Search by currency diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt index 9fc5d1725d..71196ab9a7 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt @@ -30,6 +30,7 @@ internal class ErrorsDataConverter( 2270 -> ExpressDataError.ExchangeNotEnoughBalanceError(code = error.code) 2280 -> ExpressDataError.ExchangeInvalidAddressError(code = error.code) 2290 -> tryParseExchangeInvalidFromDecimalsError(error = error) + 2320 -> tryParseProviderDifferentAmountError(error = error) else -> ExpressDataError.UnknownErrorWithCode(error.code) } } catch (e: Exception) { @@ -79,4 +80,20 @@ internal class ErrorsDataConverter( expressFromDecimals = expressFromDecimals, ) } + + private fun tryParseProviderDifferentAmountError(error: ExpressError): ExpressDataError { + val decimals = error.value?.decimals ?: return ExpressDataError.UnknownErrorWithCode(error.code) + + val fromAmount = error.value?.fromAmount?.toBigDecimalOrNull() + ?: return ExpressDataError.UnknownErrorWithCode(error.code) + val fromAmountProvider = error.value?.fromAmountProvider?.toBigDecimalOrNull() + ?: return ExpressDataError.UnknownErrorWithCode(error.code) + + return ExpressDataError.ProviderDifferentAmountError( + code = error.code, + decimals = decimals, + fromAmount = fromAmount, + fromProviderAmount = fromAmountProvider, + ) + } } \ No newline at end of file diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ExpressDataError.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ExpressDataError.kt index b2ac31292d..1446dd81b2 100644 --- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ExpressDataError.kt +++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ExpressDataError.kt @@ -39,6 +39,13 @@ sealed class ExpressDataError { val expressFromDecimals: Int, ) : ExpressDataError() + data class ProviderDifferentAmountError( + override val code: Int, + val fromAmount: BigDecimal, + val fromProviderAmount: BigDecimal, + val decimals: Int, + ) : ExpressDataError() + data class UnknownErrorWithCode(override val code: Int) : ExpressDataError() data class InvalidSignatureError(override val code: Int = 990) : ExpressDataError() diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index 3e33131d7d..519dd8d27f 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -10,10 +10,7 @@ import com.tangem.core.ui.components.notifications.NotificationConfig import com.tangem.core.ui.event.consumedEvent import com.tangem.core.ui.event.triggeredEvent import com.tangem.core.ui.extensions.* -import com.tangem.core.ui.format.bigdecimal.anyDecimals -import com.tangem.core.ui.format.bigdecimal.crypto -import com.tangem.core.ui.format.bigdecimal.format -import com.tangem.core.ui.format.bigdecimal.uncapped +import com.tangem.core.ui.format.bigdecimal.* import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.core.ui.utils.parseBigDecimal import com.tangem.domain.appcurrency.model.AppCurrency @@ -777,6 +774,19 @@ internal class StateBuilder( iconResId = R.drawable.ic_alert_circle_24, ), ) + is ExpressDataError.ProviderDifferentAmountError -> SwapWarning.GeneralError( + notificationConfig = NotificationConfig( + title = resourceReference(id = R.string.common_error), + subtitle = resourceReference( + R.string.express_error_provider_amount_roundup, + formatArgs = wrappedList( + expressDataError.code, + expressDataError.fromProviderAmount.format { simple(decimals = expressDataError.decimals) }, + ), + ), + iconResId = R.drawable.ic_alert_circle_24, + ), + ) else -> SwapWarning.GeneralWarning( notificationConfig = NotificationConfig( title = providerErrorTitle, diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/utils/SwapUtils.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/utils/SwapUtils.kt index 44c918c906..a0ef72bd20 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/utils/SwapUtils.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/utils/SwapUtils.kt @@ -28,6 +28,13 @@ internal fun getExpressErrorMessage(expressDataError: ExpressDataError): TextRef id = R.string.express_error_swap_pair_unavailable, formatArgs = wrappedList(expressDataError.code), ) + is ExpressDataError.ProviderDifferentAmountError -> resourceReference( + R.string.express_error_provider_amount_roundup, + formatArgs = wrappedList( + expressDataError.code, + expressDataError.fromProviderAmount.format { simple(decimals = expressDataError.decimals) }, + ), + ) else -> resourceReference(R.string.express_error_code, wrappedList(expressDataError.code.toString())) } } From 207da4af08352d51db22fc5c9cc6f8d2a0d3c02b Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 30 Oct 2024 13:56:00 +0400 Subject: [PATCH 10/22] Updated on 2026-08-14 --- .../com/tangem/tap/ApplicationEntryPoint.kt | 3 ++ .../java/com/tangem/tap/TangemApplication.kt | 5 +++ .../tap/proxy/redux/DaggerGraphState.kt | 2 ++ .../di/ExcludedBlockchainsModule.kt | 20 ++++++++++++ .../utils/ExcludedBlockchains.kt | 32 +++++++++++++++++++ 5 files changed, 62 insertions(+) create mode 100644 libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/di/ExcludedBlockchainsModule.kt create mode 100644 libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ExcludedBlockchains.kt diff --git a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt index 81b845f7bc..22e43ff3d2 100644 --- a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt +++ b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt @@ -3,6 +3,7 @@ package com.tangem.tap import com.tangem.TangemSdkLogger import com.tangem.blockchainsdk.BlockchainSDKFactory import com.tangem.blockchainsdk.signer.TransactionSignerFactory +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.filter.OneTimeEventFilter import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager @@ -119,4 +120,6 @@ interface ApplicationEntryPoint { fun getOnboardingV2FeatureToggles(): OnboardingV2FeatureToggles fun getCoroutineDispatcherProvider(): CoroutineDispatcherProvider + + fun getExcludedBlockchains(): ExcludedBlockchains } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/TangemApplication.kt b/app/src/main/java/com/tangem/tap/TangemApplication.kt index ddb2c9f1bc..0cb1183a0c 100644 --- a/app/src/main/java/com/tangem/tap/TangemApplication.kt +++ b/app/src/main/java/com/tangem/tap/TangemApplication.kt @@ -9,6 +9,7 @@ import com.tangem.TangemSdkLogger import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder import com.tangem.blockchainsdk.BlockchainSDKFactory import com.tangem.blockchainsdk.signer.TransactionSignerFactory +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.api.ParamsInterceptor @@ -189,6 +190,9 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { private val dispatchers: CoroutineDispatcherProvider get() = entryPoint.getCoroutineDispatcherProvider() + + private val excludedBlockchains: ExcludedBlockchains + get() = entryPoint.getExcludedBlockchains() // endregion override fun onCreate() { @@ -269,6 +273,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { onrampFeatureToggles = onrampFeatureToggles, environmentConfigStorage = environmentConfigStorage, onboardingV2FeatureToggles = onboardingV2FeatureToggles, + excludedBlockchains = excludedBlockchains, ), ), ) diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt index 075686701f..6827cc546c 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt @@ -2,6 +2,7 @@ package com.tangem.tap.proxy.redux import com.tangem.blockchainsdk.BlockchainSDKFactory import com.tangem.blockchainsdk.signer.TransactionSignerFactory +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.common.routing.AppRouter import com.tangem.core.navigation.share.ShareManager import com.tangem.core.navigation.url.UrlOpener @@ -71,4 +72,5 @@ data class DaggerGraphState( val onrampFeatureToggles: OnrampFeatureToggles? = null, val environmentConfigStorage: EnvironmentConfigStorage? = null, val onboardingV2FeatureToggles: OnboardingV2FeatureToggles? = null, + val excludedBlockchains: ExcludedBlockchains? = null, ) : StateType \ No newline at end of file diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/di/ExcludedBlockchainsModule.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/di/ExcludedBlockchainsModule.kt new file mode 100644 index 0000000000..c63d1dd071 --- /dev/null +++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/di/ExcludedBlockchainsModule.kt @@ -0,0 +1,20 @@ +package com.tangem.blockchainsdk.di + +import com.tangem.blockchainsdk.utils.ExcludedBlockchains +import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +internal object ExcludedBlockchainsModule { + + @Provides + @Singleton + fun bindExcludedBlockchains(excludedBlockchainsManager: ExcludedBlockchainsManager): ExcludedBlockchains { + return ExcludedBlockchains(excludedBlockchainsManager) + } +} \ No newline at end of file diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ExcludedBlockchains.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ExcludedBlockchains.kt new file mode 100644 index 0000000000..b443a9b0e7 --- /dev/null +++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ExcludedBlockchains.kt @@ -0,0 +1,32 @@ +package com.tangem.blockchainsdk.utils + +import com.tangem.blockchain.common.Blockchain +import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager +import javax.inject.Inject + +class ExcludedBlockchains @Inject internal constructor( + private val excludedBlockchainsManager: ExcludedBlockchainsManager, +) : Set { + + private val excludedBlockchains: Set by lazy(mode = LazyThreadSafetyMode.NONE) { + excludedBlockchainsManager.excludedBlockchainsIds.fold(mutableSetOf()) { acc, blockchainId -> + val blockchain = Blockchain.fromId(blockchainId) + acc.add(blockchain) + + blockchain.getTestnetVersion()?.let { acc.add(it) } + + acc + } + } + + override val size: Int + get() = excludedBlockchains.size + + override fun contains(element: Blockchain): Boolean = excludedBlockchains.contains(element) + + override fun containsAll(elements: Collection): Boolean = excludedBlockchains.containsAll(elements) + + override fun isEmpty(): Boolean = excludedBlockchains.isEmpty() + + override fun iterator(): Iterator = excludedBlockchains.iterator() +} \ No newline at end of file From 7aef4046c3dd386ec663664d8f0f1b8156a59101 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 26 Nov 2024 13:17:34 +0400 Subject: [PATCH 11/22] Updated on 2026-08-14 --- .../java/com/tangem/tap/di/ActivityModule.kt | 3 ++ .../com/tangem/tap/di/data/CardDataModule.kt | 4 +- .../card/DefaultDerivationsRepository.kt | 4 ++ .../features/onboarding/OnboardingHelper.kt | 6 ++- .../CryptoCurrencyConverter.kt | 7 ++- .../exchangeServices/DefaultRampManager.kt | 4 +- .../common/currency/CryptoCurrencyFactory.kt | 9 ++-- .../data/common/currency/NetworkOperations.kt | 48 +++++++++++++++---- .../ResponseCryptoCurrenciesFactory.kt | 21 ++++++-- .../DefaultCustomTokensRepository.kt | 27 ++++++++--- .../DefaultManageTokensRepository.kt | 17 ++++--- .../managetokens/di/ManageTokensDataModule.kt | 5 ++ .../utils/ManagedCryptoCurrencyFactory.kt | 19 +++++--- data/markets/build.gradle.kts | 1 + .../markets/DefaultMarketsTokenRepository.kt | 12 +++-- .../converters/TokenMarketInfoConverter.kt | 18 ++++--- .../data/markets/di/MarketsDataModule.kt | 3 ++ .../tangem/data/tokens/di/TokensDataModule.kt | 5 ++ .../repository/DefaultCurrenciesRepository.kt | 8 ++-- .../repository/DefaultNetworksRepository.kt | 10 ++-- .../utils/CardCryptoCurrenciesFactory.kt | 8 +++- .../domain/common/extensions/CardSdk.kt | 32 +++++++++---- .../impl/model/MarketsTokenDetailsModel.kt | 4 +- .../referral/data/ReferralRepositoryImpl.kt | 7 ++- .../referral/di/ReferralRepositoryModule.kt | 3 ++ .../feature/swap/DefaultSwapRepository.kt | 4 +- .../swap/DefaultSwapTransactionRepository.kt | 6 ++- .../SavedSwapTransactionListConverter.kt | 8 ++-- .../tangem/feature/swap/di/SwapDataModule.kt | 5 ++ .../tangem/blockchainsdk/utils/Blockchain.kt | 13 +---- .../com/tangem/lib/crypto/BlockchainUtils.kt | 8 ++-- 31 files changed, 238 insertions(+), 91 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/di/ActivityModule.kt b/app/src/main/java/com/tangem/tap/di/ActivityModule.kt index 646c003c7f..f6252946fb 100644 --- a/app/src/main/java/com/tangem/tap/di/ActivityModule.kt +++ b/app/src/main/java/com/tangem/tap/di/ActivityModule.kt @@ -1,5 +1,6 @@ package com.tangem.tap.di +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.datasource.exchangeservice.swap.SwapServiceLoader import com.tangem.domain.card.ScanCardUseCase import com.tangem.domain.card.repository.CardSdkConfigRepository @@ -49,6 +50,7 @@ internal object ActivityModule { swapServiceLoader: SwapServiceLoader, currenciesRepository: CurrenciesRepository, getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase, + excludedBlockchains: ExcludedBlockchains, dispatchers: CoroutineDispatcherProvider, ): RampStateManager { return DefaultRampManager( @@ -58,6 +60,7 @@ internal object ActivityModule { swapServiceLoader = swapServiceLoader, currenciesRepository = currenciesRepository, getNetworkCoinStatusUseCase = getNetworkCoinStatusUseCase, + excludedBlockchains = excludedBlockchains, dispatchers = dispatchers, ) } diff --git a/app/src/main/java/com/tangem/tap/di/data/CardDataModule.kt b/app/src/main/java/com/tangem/tap/di/data/CardDataModule.kt index 66d63389c9..34411415bf 100644 --- a/app/src/main/java/com/tangem/tap/di/data/CardDataModule.kt +++ b/app/src/main/java/com/tangem/tap/di/data/CardDataModule.kt @@ -1,5 +1,6 @@ package com.tangem.tap.di.data +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.card.repository.DerivationsRepository import com.tangem.sdk.api.TangemSdkManager @@ -20,8 +21,9 @@ internal object CardDataModule { fun providesDerivationsRepository( tangemSdkManager: TangemSdkManager, userWalletsStore: UserWalletsStore, + excludedBlockchains: ExcludedBlockchains, dispatchers: CoroutineDispatcherProvider, ): DerivationsRepository { - return DefaultDerivationsRepository(tangemSdkManager, userWalletsStore, dispatchers) + return DefaultDerivationsRepository(tangemSdkManager, userWalletsStore, excludedBlockchains, dispatchers) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivationsRepository.kt b/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivationsRepository.kt index 45cc75e9da..f9e14a3a11 100644 --- a/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivationsRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivationsRepository.kt @@ -1,6 +1,7 @@ package com.tangem.tap.domain.card import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.common.CompletionResult import com.tangem.common.card.EllipticCurve @@ -32,6 +33,7 @@ private typealias DerivedKeys = Map internal class DefaultDerivationsRepository( private val tangemSdkManager: TangemSdkManager, private val userWalletsStore: UserWalletsStore, + private val excludedBlockchains: ExcludedBlockchains, private val dispatchers: CoroutineDispatcherProvider, ) : DerivationsRepository { @@ -49,6 +51,7 @@ internal class DefaultDerivationsRepository( blockchain = Blockchain.fromNetworkId(it.value) ?: return@mapNotNull null, extraDerivationPath = null, scanResponse = userWallet.scanResponse, + excludedBlockchains = excludedBlockchains, ) }, ) @@ -85,6 +88,7 @@ internal class DefaultDerivationsRepository( blockchain = Blockchain.fromNetworkId(backendId) ?: return@mapNotNull null, extraDerivationPath = extraDerivationPath, scanResponse = userWallet.scanResponse, + excludedBlockchains = excludedBlockchains, ) }, ) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt index 4fc3109010..5ff29dc0d4 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt @@ -24,8 +24,8 @@ import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.AppDialog import com.tangem.tap.common.redux.global.GlobalState import com.tangem.tap.features.demo.DemoHelper -import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE +import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction import com.tangem.tap.features.saveWallet.redux.SaveWalletAction import com.tangem.tap.mainScope import com.tangem.tap.proxy.redux.DaggerGraphState @@ -212,7 +212,9 @@ object OnboardingHelper { fun handleTopUpAction(walletManager: WalletManager, scanResponse: ScanResponse, globalState: GlobalState) { val blockchain = walletManager.wallet.blockchain - val cryptoCurrency = CryptoCurrencyFactory().createCoin( + val excludedBlockchains = store.inject(DaggerGraphState::excludedBlockchains) + + val cryptoCurrency = CryptoCurrencyFactory(excludedBlockchains).createCoin( blockchain = blockchain, extraDerivationPath = null, scanResponse = scanResponse, diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt index 520d262847..8cf25d7f82 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt @@ -2,6 +2,7 @@ package com.tangem.tap.network.exchangeServices import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.tap.common.extensions.inject @@ -10,9 +11,11 @@ import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.store import com.tangem.utils.converter.TwoWayConverter -internal class CryptoCurrencyConverter : TwoWayConverter { +internal class CryptoCurrencyConverter( + private val excludedBlockchains: ExcludedBlockchains, +) : TwoWayConverter { - private val cryptoCurrencyFactory by lazy { CryptoCurrencyFactory() } + private val cryptoCurrencyFactory by lazy { CryptoCurrencyFactory(excludedBlockchains) } override fun convert(value: Currency): CryptoCurrency { return when (value) { diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt index 0186fe0f32..045c5f948e 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt @@ -1,5 +1,6 @@ package com.tangem.tap.network.exchangeServices +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.datasource.api.express.models.TangemExpressValues.EMPTY_CONTRACT_ADDRESS_VALUE import com.tangem.datasource.exchangeservice.swap.SwapServiceLoader import com.tangem.domain.exchange.RampStateManager @@ -25,9 +26,10 @@ internal class DefaultRampManager( private val currenciesRepository: CurrenciesRepository, private val getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase, private val dispatchers: CoroutineDispatcherProvider, + excludedBlockchains: ExcludedBlockchains, ) : RampStateManager { - private val cryptoCurrencyConverter = CryptoCurrencyConverter() + private val cryptoCurrencyConverter = CryptoCurrencyConverter(excludedBlockchains) override fun isSellSupportedByService(cryptoCurrency: CryptoCurrency): Boolean { return exchangeService?.availableForSell( diff --git a/data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt index ff4455dc21..fb8608e78b 100644 --- a/data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt @@ -1,6 +1,7 @@ package com.tangem.data.common.currency import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.blockchainsdk.utils.toCoinId import com.tangem.domain.models.scan.ScanResponse @@ -10,7 +11,9 @@ import timber.log.Timber import com.tangem.blockchain.common.Token as SdkToken // FIXME: Make internal -class CryptoCurrencyFactory { +class CryptoCurrencyFactory( + private val excludedBlockchains: ExcludedBlockchains, +) { @Suppress("LongParameterList") // Yep, it's long fun createToken( @@ -46,7 +49,7 @@ class CryptoCurrencyFactory { return null } - val network = getNetwork(blockchain, extraDerivationPath, scanResponse) ?: return null + val network = getNetwork(blockchain, extraDerivationPath, scanResponse, excludedBlockchains) ?: return null val id = getTokenId(network, sdkToken) return CryptoCurrency.Token( @@ -70,7 +73,7 @@ class CryptoCurrencyFactory { Timber.e("Unable to map the SDK token to the domain token with Unknown blockchain") return null } - val network = getNetwork(blockchain, extraDerivationPath, scanResponse) ?: return null + val network = getNetwork(blockchain, extraDerivationPath, scanResponse, excludedBlockchains) ?: return null return createCoin(network) } diff --git a/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt index f181886484..9d2fd810d9 100644 --- a/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt @@ -2,6 +2,7 @@ package com.tangem.data.common.currency import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.FeePaidCurrency +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.toNetworkId import com.tangem.domain.common.DerivationStyleProvider import com.tangem.domain.common.extensions.canHandleToken @@ -19,10 +20,10 @@ fun getNetwork( blockchain: Blockchain, extraDerivationPath: String?, derivationStyleProvider: DerivationStyleProvider?, + excludedBlockchains: ExcludedBlockchains, canHandleTokens: Boolean, ): Network? { - if (blockchain == Blockchain.Unknown) { - Timber.e("Unable to convert Unknown blockchain to the domain network model") + if (!isBlockchainSupported(blockchain, excludedBlockchains)) { return null } @@ -43,10 +44,14 @@ fun getNetwork( ) } -fun getNetwork(networkId: Network.ID, derivationPath: Network.DerivationPath, scanResponse: ScanResponse): Network? { +fun getNetwork( + networkId: Network.ID, + derivationPath: Network.DerivationPath, + scanResponse: ScanResponse, + excludedBlockchains: ExcludedBlockchains, +): Network? { val blockchain = getBlockchain(networkId) - if (blockchain == Blockchain.Unknown) { - Timber.e("Unable to convert Unknown blockchain to the domain network model") + if (!isBlockchainSupported(blockchain, excludedBlockchains)) { return null } @@ -59,16 +64,43 @@ fun getNetwork(networkId: Network.ID, derivationPath: Network.DerivationPath, sc currencySymbol = blockchain.currency, standardType = getNetworkStandardType(blockchain), hasFiatFeeRate = blockchain.feePaidCurrency() !is FeePaidCurrency.FeeResource, - canHandleTokens = scanResponse.card.canHandleToken(blockchain, scanResponse.cardTypesResolver), + canHandleTokens = scanResponse.card.canHandleToken( + blockchain, + scanResponse.cardTypesResolver, + excludedBlockchains, + ), ) } -fun getNetwork(blockchain: Blockchain, extraDerivationPath: String?, scanResponse: ScanResponse): Network? { +private fun isBlockchainSupported(blockchain: Blockchain, excludedBlockchains: ExcludedBlockchains): Boolean { + if (blockchain == Blockchain.Unknown) { + Timber.w("Unable to convert Unknown blockchain to the domain network model") + return false + } + if (blockchain in excludedBlockchains) { + Timber.w("Unable to convert excluded blockchain to the domain network model") + return false + } + + return true +} + +fun getNetwork( + blockchain: Blockchain, + extraDerivationPath: String?, + scanResponse: ScanResponse, + excludedBlockchains: ExcludedBlockchains, +): Network? { return getNetwork( blockchain = blockchain, extraDerivationPath = extraDerivationPath, derivationStyleProvider = scanResponse.derivationStyleProvider, - canHandleTokens = scanResponse.card.canHandleToken(blockchain, scanResponse.cardTypesResolver), + excludedBlockchains = excludedBlockchains, + canHandleTokens = scanResponse.card.canHandleToken( + blockchain, + scanResponse.cardTypesResolver, + excludedBlockchains, + ), ) } 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 047150c42e..7cda282ecb 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 @@ -3,6 +3,7 @@ package com.tangem.data.common.currency import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token import com.tangem.blockchainsdk.compatibility.l2BlockchainsList +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.blockchainsdk.utils.toCoinId import com.tangem.datasource.api.tangemTech.models.UserTokensResponse @@ -12,7 +13,9 @@ import com.tangem.domain.tokens.model.CryptoCurrency import timber.log.Timber import com.tangem.blockchain.common.Token as SdkToken -class ResponseCryptoCurrenciesFactory { +class ResponseCryptoCurrenciesFactory( + private val excludedBlockchains: ExcludedBlockchains, +) { fun createCurrency(currencyId: String, response: UserTokensResponse, scanResponse: ScanResponse): CryptoCurrency { return response.tokens @@ -65,7 +68,12 @@ class ResponseCryptoCurrenciesFactory { responseToken: UserTokensResponse.Token, scanResponse: ScanResponse, ): CryptoCurrency.Coin? { - val network = getNetwork(blockchain, responseToken.derivationPath, scanResponse) ?: return null + val network = getNetwork( + blockchain, + responseToken.derivationPath, + scanResponse, + excludedBlockchains, + ) ?: return null return CryptoCurrency.Coin( id = getCoinId(network, blockchain.toCoinId()), @@ -111,8 +119,13 @@ class ResponseCryptoCurrenciesFactory { responseDerivationPath: String?, scanResponse: ScanResponse, ): CryptoCurrency.Token? { - val network = getNetwork(blockchain, responseDerivationPath, scanResponse) - ?: return null + val network = getNetwork( + blockchain, + responseDerivationPath, + scanResponse, + excludedBlockchains, + ) ?: return null + val id = getTokenId(network, sdkToken) return CryptoCurrency.Token( diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt index 3c9aabf80e..ba48dfac71 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt @@ -1,6 +1,7 @@ package com.tangem.data.managetokens import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.toNetworkId import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.data.common.api.safeApiCall @@ -36,10 +37,11 @@ internal class DefaultCustomTokensRepository( private val userWalletsStore: UserWalletsStore, private val appPreferencesStore: AppPreferencesStore, private val walletManagersFacade: WalletManagersFacade, + private val excludedBlockchains: ExcludedBlockchains, private val dispatchers: CoroutineDispatcherProvider, ) : CustomTokensRepository { - private val cryptoCurrencyFactory = CryptoCurrencyFactory() + private val cryptoCurrencyFactory = CryptoCurrencyFactory(excludedBlockchains) private val userTokensResponseFactory = UserTokensResponseFactory() private val tokenAddressConverter = TokenAddressesConverter() private val userTokensBackwardCompatibility = UserTokensBackwardCompatibility() @@ -87,7 +89,9 @@ internal class DefaultCustomTokensRepository( val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) { "User wallet [$userWalletId] not found while finding token" } - val network = requireNotNull(getNetwork(networkId, derivationPath, userWallet.scanResponse)) { + val network = requireNotNull( + getNetwork(networkId, derivationPath, userWallet.scanResponse, excludedBlockchains), + ) { "Network [$networkId] not found while finding token" } val tokenAddress = tokenAddressConverter.convertTokenAddress( @@ -97,7 +101,7 @@ internal class DefaultCustomTokensRepository( ) val supportedTokenNetworkIds = userWallet.scanResponse.card - .supportedBlockchains(userWallet.scanResponse.cardTypesResolver) + .supportedBlockchains(userWallet.scanResponse.cardTypesResolver, excludedBlockchains) .filter(Blockchain::canHandleTokens) .map(Blockchain::toNetworkId) @@ -137,7 +141,9 @@ internal class DefaultCustomTokensRepository( val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) { "User wallet [$userWalletId] not found while creating coin" } - val network = requireNotNull(getNetwork(networkId, derivationPath, userWallet.scanResponse)) { + val network = requireNotNull( + getNetwork(networkId, derivationPath, userWallet.scanResponse, excludedBlockchains), + ) { "Network [$networkId] not found while creating coin" } @@ -168,7 +174,9 @@ internal class DefaultCustomTokensRepository( val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) { "User wallet [$userWalletId] not found while creating custom token" } - val network = requireNotNull(getNetwork(networkId, derivationPath, userWallet.scanResponse)) { + val network = requireNotNull( + getNetwork(networkId, derivationPath, userWallet.scanResponse, excludedBlockchains), + ) { "Network [$networkId] not found while creating custom token" } val tokenAddress = tokenAddressConverter.convertTokenAddress( @@ -230,11 +238,18 @@ internal class DefaultCustomTokensRepository( Blockchain.entries .mapNotNull { blockchain -> - if (scanResponse.card.canHandleBlockchain(blockchain, scanResponse.cardTypesResolver)) { + val canHandleBlockchain = scanResponse.card.canHandleBlockchain( + blockchain, + scanResponse.cardTypesResolver, + excludedBlockchains, + ) + + if (canHandleBlockchain) { getNetwork( blockchain = blockchain, extraDerivationPath = null, scanResponse = scanResponse, + excludedBlockchains = excludedBlockchains, ) } else { null diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt index deb08005ef..6e2f02f44c 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt @@ -2,8 +2,8 @@ package com.tangem.data.managetokens import com.tangem.blockchain.common.Blockchain import com.tangem.blockchainsdk.compatibility.l2BlockchainsCoinIds +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId -import com.tangem.blockchainsdk.utils.isSupportedInApp import com.tangem.blockchainsdk.utils.toNetworkId import com.tangem.data.common.api.safeApiCall import com.tangem.data.common.currency.UserTokensResponseFactory @@ -47,12 +47,13 @@ internal class DefaultManageTokensRepository( private val manageTokensUpdateFetcher: ManageTokensUpdateFetcher, private val appPreferencesStore: AppPreferencesStore, private val testnetTokensStorage: TestnetTokensStorage, + private val excludedBlockchains: ExcludedBlockchains, private val dispatchers: CoroutineDispatcherProvider, ) : ManageTokensRepository { - private val managedCryptoCurrencyFactory = ManagedCryptoCurrencyFactory() + private val managedCryptoCurrencyFactory = ManagedCryptoCurrencyFactory(excludedBlockchains) private val userTokensResponseFactory = UserTokensResponseFactory() - private val cardCurrenciesFactory = CardCryptoCurrenciesFactory(DemoConfig()) + private val cardCurrenciesFactory = CardCryptoCurrenciesFactory(DemoConfig(), excludedBlockchains) // region getTokenListBatchFlow override fun getTokenListBatchFlow( @@ -202,9 +203,9 @@ internal class DefaultManageTokensRepository( private fun getSupportedBlockchains(userWallet: UserWallet?): List { return userWallet?.scanResponse?.let { - it.card.supportedBlockchains(it.cardTypesResolver) + it.card.supportedBlockchains(it.cardTypesResolver, excludedBlockchains) } ?: Blockchain.entries.filter { - !it.isTestnet() && it.isSupportedInApp() + !it.isTestnet() && it !in excludedBlockchains } } // endregion @@ -290,6 +291,7 @@ internal class DefaultManageTokensRepository( val canHandleBlockchain = userWallet.scanResponse.card.canHandleBlockchain( blockchain = blockchain, cardTypesResolver = userWallet.cardTypesResolver, + excludedBlockchains = excludedBlockchains, ) return if (!canHandleBlockchain) { @@ -304,7 +306,10 @@ internal class DefaultManageTokensRepository( blockchain: Blockchain, ): CurrencyUnsupportedState.Token? { val cardTypesResolver = userWallet.scanResponse.cardTypesResolver - val supportedTokens = userWallet.scanResponse.card.supportedTokens(cardTypesResolver) + val supportedTokens = userWallet.scanResponse.card.supportedTokens( + cardTypesResolver, + excludedBlockchains, + ) return when { // refactor this later by moving all this logic in card config diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt index a85db459dd..3f64ae5970 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt @@ -1,5 +1,6 @@ package com.tangem.data.managetokens.di +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.data.managetokens.DefaultCustomTokensRepository import com.tangem.data.managetokens.DefaultManageTokensRepository import com.tangem.data.managetokens.utils.ManageTokensUpdateFetcher @@ -30,6 +31,7 @@ internal object ManageTokensDataModule { appPreferencesStore: AppPreferencesStore, testnetTokensStorage: TestnetTokensStorage, dispatchers: CoroutineDispatcherProvider, + excludedBlockchains: ExcludedBlockchains, ): ManageTokensRepository { return DefaultManageTokensRepository( tangemTechApi, @@ -37,6 +39,7 @@ internal object ManageTokensDataModule { manageTokensUpdateFetcher, appPreferencesStore, testnetTokensStorage, + excludedBlockchains, dispatchers, ) } @@ -49,12 +52,14 @@ internal object ManageTokensDataModule { appPreferencesStore: AppPreferencesStore, walletManagersFacade: WalletManagersFacade, dispatchers: CoroutineDispatcherProvider, + excludedBlockchains: ExcludedBlockchains, ): CustomTokensRepository { return DefaultCustomTokensRepository( tangemTechApi, userWalletsStore, appPreferencesStore, walletManagersFacade, + excludedBlockchains, dispatchers, ) } diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt index a5eb111a0d..36475f8fbd 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt @@ -4,8 +4,8 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.blockchainsdk.compatibility.applyL2Compatibility import com.tangem.blockchainsdk.compatibility.getL2CompatibilityTokenComparison import com.tangem.blockchainsdk.compatibility.l2BlockchainsList +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId -import com.tangem.blockchainsdk.utils.isSupportedInApp import com.tangem.blockchainsdk.utils.toCoinId import com.tangem.data.common.currency.getCoinId import com.tangem.data.common.currency.getNetwork @@ -22,7 +22,9 @@ import com.tangem.domain.managetokens.model.ManagedCryptoCurrency.SourceNetwork import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.Network -internal class ManagedCryptoCurrencyFactory { +internal class ManagedCryptoCurrencyFactory( + private val excludedBlockchains: ExcludedBlockchains, +) { fun create( coinsResponse: CoinsResponse, @@ -88,7 +90,7 @@ internal class ManagedCryptoCurrencyFactory { scanResponse: ScanResponse, ): ManagedCryptoCurrency? { val blockchain = Blockchain.fromNetworkId(token.networkId) - ?.takeIf { it.isSupportedInApp() } + ?.takeUnless { it in excludedBlockchains } ?: return null if (!checkIsCustomToken(token, blockchain, scanResponse.derivationStyleProvider)) { @@ -99,6 +101,7 @@ internal class ManagedCryptoCurrencyFactory { blockchain = blockchain, extraDerivationPath = token.derivationPath, scanResponse = scanResponse, + excludedBlockchains = excludedBlockchains, ) ?: return null val contractAddress = token.contractAddress @@ -161,15 +164,16 @@ internal class ManagedCryptoCurrencyFactory { extraDerivationPath: String? = null, ): SourceNetwork? { val blockchain = Blockchain.fromNetworkId(networkId) - ?.takeIf { it.isSupportedInApp() } + ?.takeUnless { it in excludedBlockchains } ?: return null val network = getNetwork( blockchain, extraDerivationPath, scanResponse?.derivationStyleProvider, + excludedBlockchains, canHandleTokens = scanResponse?.let { - it.card.canHandleToken(blockchain, it.cardTypesResolver) + it.card.canHandleToken(blockchain, it.cardTypesResolver, excludedBlockchains) } ?: true, ) ?: return null @@ -200,13 +204,14 @@ internal class ManagedCryptoCurrencyFactory { .mapNotNullTo(mutableSetOf()) { token -> val blockchain = Blockchain.fromNetworkId(token.networkId) - if (blockchain != null && blockchain.isSupportedInApp()) { + if (blockchain != null && blockchain !in excludedBlockchains) { getNetwork( blockchain, token.derivationPath, scanResponse?.derivationStyleProvider, + excludedBlockchains, canHandleTokens = scanResponse?.let { - it.card.canHandleToken(blockchain, it.cardTypesResolver) + it.card.canHandleToken(blockchain, it.cardTypesResolver, excludedBlockchains) } ?: true, ) } else { diff --git a/data/markets/build.gradle.kts b/data/markets/build.gradle.kts index ba16c78bf0..632a570f78 100644 --- a/data/markets/build.gradle.kts +++ b/data/markets/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { implementation(projects.core.pagination) implementation(projects.core.analytics) implementation(projects.core.analytics.models) + implementation(projects.core.configToggles) implementation(projects.domain.legacy) implementation(projects.domain.markets) diff --git a/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt b/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt index be0e41c584..61eb79b5e0 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt @@ -3,6 +3,7 @@ package com.tangem.data.markets import com.tangem.blockchain.common.Blockchain import com.tangem.blockchainsdk.compatibility.applyL2Compatibility import com.tangem.blockchainsdk.compatibility.getTokenIdIfL2Network +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.data.common.cache.CacheRegistry @@ -37,10 +38,14 @@ internal class DefaultMarketsTokenRepository( private val userWalletsStore: UserWalletsStore, private val dispatcherProvider: CoroutineDispatcherProvider, private val analyticsEventHandler: AnalyticsEventHandler, + private val excludedBlockchains: ExcludedBlockchains, private val cacheRegistry: CacheRegistry, private val tokenExchangesStore: RuntimeStateStore>, ) : MarketsTokenRepository { + private val tokenMarketInfoConverter: TokenMarketInfoConverter = TokenMarketInfoConverter(excludedBlockchains) + private val cryptoCurrencyFactory = CryptoCurrencyFactory(excludedBlockchains) + private fun createTokenMarketsFetcher(firstBatchSize: Int, nextBatchSize: Int) = LimitOffsetBatchFetcher( prefetchDistance = firstBatchSize, batchSize = nextBatchSize, @@ -204,7 +209,7 @@ internal class DefaultMarketsTokenRepository( } val resultResponse = result.applyL2Compatibility(tokenId) - return@withContext TokenMarketInfoConverter.convert(resultResponse) + return@withContext tokenMarketInfoConverter.convert(resultResponse) } override suspend fun getTokenQuotes(fiatCurrencyCode: String, tokenId: String, tokenSymbol: String) = @@ -234,7 +239,7 @@ internal class DefaultMarketsTokenRepository( val blockchain = Blockchain.fromNetworkId(network.networkId) ?: error("Unknown network [${network.networkId}]") return if (network.contractAddress == null) { - CryptoCurrencyFactory().createCoin( + cryptoCurrencyFactory.createCoin( blockchain = blockchain, extraDerivationPath = null, scanResponse = userWallet.scanResponse, @@ -244,9 +249,10 @@ internal class DefaultMarketsTokenRepository( blockchain = blockchain, extraDerivationPath = null, scanResponse = userWallet.scanResponse, + excludedBlockchains = excludedBlockchains, ) ?: return null - CryptoCurrencyFactory().createToken( + cryptoCurrencyFactory.createToken( network = currencyNetwork, rawId = token.id, name = token.name, diff --git a/data/markets/src/main/java/com/tangem/data/markets/converters/TokenMarketInfoConverter.kt b/data/markets/src/main/java/com/tangem/data/markets/converters/TokenMarketInfoConverter.kt index 85afc94699..2e0146f681 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/converters/TokenMarketInfoConverter.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/converters/TokenMarketInfoConverter.kt @@ -2,8 +2,8 @@ package com.tangem.data.markets.converters import android.net.Uri import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId -import com.tangem.blockchainsdk.utils.isSupportedInApp import com.tangem.datasource.api.markets.models.response.TokenMarketInfoResponse import com.tangem.domain.markets.BuildConfig import com.tangem.domain.markets.TokenMarketInfo @@ -11,10 +11,9 @@ import com.tangem.domain.markets.TokenQuotes import com.tangem.utils.converter.Converter import java.math.BigDecimal -internal object TokenMarketInfoConverter : Converter { - - private const val PROD_IMAGE_HOST = "https://s3.eu-central-1.amazonaws.com/tangem.api/security_provider/" - private const val DEV_IMAGE_HOST = "https://s3.eu-central-1.amazonaws.com/tangem.api.dev/security_provider/" +internal class TokenMarketInfoConverter( + private val excludedBlockchains: ExcludedBlockchains, +) : Converter { override fun convert(value: TokenMarketInfoResponse): TokenMarketInfo { return with(value) { @@ -68,7 +67,8 @@ internal object TokenMarketInfoConverter : Converter { + blockchain != null && blockchain !in excludedBlockchains && + blockchain.canHandleTokens() -> { TokenMarketInfo.Network( networkId = network.networkId, exchangeable = network.exchangeable, @@ -193,4 +193,10 @@ internal object TokenMarketInfoConverter : Converter { val card = scanResponse.card diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/CardSdk.kt b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/CardSdk.kt index cf827af989..a5129bbb52 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/CardSdk.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/CardSdk.kt @@ -1,7 +1,7 @@ package com.tangem.domain.common.extensions import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchainsdk.utils.isSupportedInApp +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.common.card.EllipticCurve import com.tangem.common.card.FirmwareVersion import com.tangem.domain.common.CardTypesResolver @@ -15,7 +15,10 @@ import com.tangem.domain.models.scan.CardDTO val FirmwareVersion.Companion.SolanaTokensAvailable get() = FirmwareVersion(4, 52) -fun CardDTO.supportedBlockchains(cardTypesResolver: CardTypesResolver): List { +fun CardDTO.supportedBlockchains( + cardTypesResolver: CardTypesResolver, + excludedBlockchains: ExcludedBlockchains, +): List { val supportedBlockchains = if (firmwareVersion < FirmwareVersion.MultiWalletAvailable) { Blockchain.fromCurve(EllipticCurve.Secp256k1).toMutableList() } else if (!cardTypesResolver.isWallet2() && !cardTypesResolver.isTangemWallet()) { @@ -27,11 +30,14 @@ fun CardDTO.supportedBlockchains(cardTypesResolver: CardTypesResolver): List { - val tokensSupportedByBlockchain = supportedBlockchains(cardTypesResolver) +fun CardDTO.supportedTokens( + cardTypesResolver: CardTypesResolver, + excludedBlockchains: ExcludedBlockchains, +): List { + val tokensSupportedByBlockchain = supportedBlockchains(cardTypesResolver, excludedBlockchains) .filter { it.canHandleTokens() } .toMutableList() val tokensSupportedByCard = when { @@ -68,10 +74,14 @@ fun CardDTO.canHandleToken( } } -fun CardDTO.canHandleToken(blockchain: Blockchain, cardTypesResolver: CardTypesResolver): Boolean { +fun CardDTO.canHandleToken( + blockchain: Blockchain, + cardTypesResolver: CardTypesResolver, + excludedBlockchains: ExcludedBlockchains, +): Boolean { val cardConfig = CardConfig.createConfig(this) val primaryCurveForBlockchain = cardConfig.primaryCurve(blockchain) - val isContainsBlockchain = this.supportedTokens(cardTypesResolver).contains(blockchain) + val isContainsBlockchain = blockchain in supportedTokens(cardTypesResolver, excludedBlockchains) val isWalletForCurveExists = wallets.any { it.curve == primaryCurveForBlockchain } // fixme: check for first wallets with 1 curve and remove condition return if (cardTypesResolver.isTangemWallet() || cardTypesResolver.isWallet2()) { @@ -82,10 +92,14 @@ fun CardDTO.canHandleToken(blockchain: Blockchain, cardTypesResolver: CardTypesR } } -fun CardDTO.canHandleBlockchain(blockchain: Blockchain, cardTypesResolver: CardTypesResolver): Boolean { +fun CardDTO.canHandleBlockchain( + blockchain: Blockchain, + cardTypesResolver: CardTypesResolver, + excludedBlockchains: ExcludedBlockchains, +): Boolean { val cardConfig = CardConfig.createConfig(this) val primaryCurveForBlockchain = cardConfig.primaryCurve(blockchain) - val isContainsBlockchain = this.supportedBlockchains(cardTypesResolver).contains(blockchain) + val isContainsBlockchain = blockchain in supportedBlockchains(cardTypesResolver, excludedBlockchains) val isWalletForCurveExists = wallets.any { it.curve == primaryCurveForBlockchain } // fixme: check for first wallets with 1 curve and remove condition return if (cardTypesResolver.isTangemWallet() || cardTypesResolver.isWallet2()) { diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt index b6d4827fda..5121d721b4 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt @@ -3,6 +3,7 @@ package com.tangem.features.markets.details.impl.model import androidx.compose.runtime.Stable import arrow.core.Either import arrow.core.getOrElse +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.common.ui.charts.state.MarketChartData import com.tangem.common.ui.charts.state.MarketChartDataProducer import com.tangem.common.ui.charts.state.sorted @@ -64,6 +65,7 @@ internal class MarketsTokenDetailsModel @Inject constructor( private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val urlOpener: UrlOpener, private val analyticsEventHandler: AnalyticsEventHandler, + private val excludedBlockchains: ExcludedBlockchains, ) : Model() { private var quotesJob = JobHolder() @@ -400,7 +402,7 @@ internal class MarketsTokenDetailsModel @Inject constructor( } val networks = newInfo.networks?.filter { - BlockchainUtils.isSupportedNetworkId(it.networkId) + BlockchainUtils.isSupportedNetworkId(it.networkId, excludedBlockchains) } networksState.value = if (networks.isNullOrEmpty()) { diff --git a/features/referral/data/src/main/java/com/tangem/feature/referral/data/ReferralRepositoryImpl.kt b/features/referral/data/src/main/java/com/tangem/feature/referral/data/ReferralRepositoryImpl.kt index c0c257c1c9..ae6768f793 100644 --- a/features/referral/data/src/main/java/com/tangem/feature/referral/data/ReferralRepositoryImpl.kt +++ b/features/referral/data/src/main/java/com/tangem/feature/referral/data/ReferralRepositoryImpl.kt @@ -2,6 +2,7 @@ package com.tangem.feature.referral.data import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.datasource.api.tangemTech.TangemTechApi @@ -18,14 +19,18 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.withContext import javax.inject.Inject +@Suppress("LongParameterList") internal class ReferralRepositoryImpl @Inject constructor( private val referralApi: TangemTechApi, private val referralConverter: ReferralConverter, private val coroutineDispatcher: CoroutineDispatcherProvider, private val demoModeDatasource: DemoModeDatasource, private val userWalletsStore: UserWalletsStore, + excludedBlockchains: ExcludedBlockchains, ) : ReferralRepository { + private val cryptoCurrencyFactory = CryptoCurrencyFactory(excludedBlockchains) + override val isDemoMode: Boolean get() = demoModeDatasource.isDemoModeActive @@ -65,8 +70,6 @@ internal class ReferralRepositoryImpl @Inject constructor( val blockchain = Blockchain.fromNetworkId(tokenData.networkId) ?: error("Blockchain ${tokenData.networkId} not found") - val cryptoCurrencyFactory = CryptoCurrencyFactory() - val contractAddress = tokenData.contractAddress val decimalCount = tokenData.decimalCount return if (contractAddress != null && decimalCount != null) { diff --git a/features/referral/data/src/main/java/com/tangem/feature/referral/di/ReferralRepositoryModule.kt b/features/referral/data/src/main/java/com/tangem/feature/referral/di/ReferralRepositoryModule.kt index 6c0f5e9c47..7d01957033 100644 --- a/features/referral/data/src/main/java/com/tangem/feature/referral/di/ReferralRepositoryModule.kt +++ b/features/referral/data/src/main/java/com/tangem/feature/referral/di/ReferralRepositoryModule.kt @@ -1,5 +1,6 @@ package com.tangem.feature.referral.di +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.demo.DemoModeDatasource import com.tangem.datasource.local.userwallet.UserWalletsStore @@ -25,6 +26,7 @@ class ReferralRepositoryModule { coroutineDispatcherProvider: CoroutineDispatcherProvider, demoModeDatasource: DemoModeDatasource, userWalletsStore: UserWalletsStore, + excludedBlockchains: ExcludedBlockchains, ): ReferralRepository { return ReferralRepositoryImpl( referralApi = tangemTechApi, @@ -32,6 +34,7 @@ class ReferralRepositoryModule { coroutineDispatcher = coroutineDispatcherProvider, demoModeDatasource = demoModeDatasource, userWalletsStore = userWalletsStore, + excludedBlockchains = excludedBlockchains, ) } } \ No newline at end of file diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt index 0548a65ea7..8e465b9c2b 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt @@ -7,6 +7,7 @@ import arrow.core.raise.either import arrow.core.right import com.squareup.moshi.Moshi import com.tangem.blockchain.common.* +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.datasource.api.common.response.ApiResponse @@ -48,12 +49,13 @@ internal class DefaultSwapRepository( private val errorsDataConverter: ErrorsDataConverter, private val dataSignatureVerifier: DataSignatureVerifier, moshi: Moshi, + excludedBlockchains: ExcludedBlockchains, ) : SwapRepository { private val expressDataConverter = ExpressDataConverter() private val leastTokenInfoConverter = LeastTokenInfoConverter() private val swapPairInfoConverter = SwapPairInfoConverter() - private val cryptoCurrencyFactory = CryptoCurrencyFactory() + private val cryptoCurrencyFactory = CryptoCurrencyFactory(excludedBlockchains) private val exchangeStatusConverter = ExchangeStatusConverter() private val txDetailsMoshiAdapter = moshi.adapter(TxDetails::class.java) 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 9b44aacbef..ed7aa550c5 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 @@ -1,5 +1,6 @@ package com.tangem.feature.swap +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getObjectList @@ -18,12 +19,13 @@ import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext -class DefaultSwapTransactionRepository( +internal class DefaultSwapTransactionRepository( private val appPreferencesStore: AppPreferencesStore, private val dispatchers: CoroutineDispatcherProvider, + excludedBlockchains: ExcludedBlockchains, ) : SwapTransactionRepository { - private val converter = SavedSwapTransactionListConverter() + private val converter = SavedSwapTransactionListConverter(excludedBlockchains) override suspend fun storeTransaction( userWalletId: UserWalletId, 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 33112a9591..d3d6093b01 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,5 +1,6 @@ package com.tangem.feature.swap.converters +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory import com.tangem.data.common.currency.UserTokensResponseFactory import com.tangem.domain.models.scan.ScanResponse @@ -11,10 +12,11 @@ import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionListMode import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionModel import com.tangem.utils.converter.Converter -class SavedSwapTransactionListConverter : - Converter { +internal class SavedSwapTransactionListConverter( + excludedBlockchains: ExcludedBlockchains, +) : Converter { - private val responseCryptoCurrenciesFactory = ResponseCryptoCurrenciesFactory() + private val responseCryptoCurrenciesFactory = ResponseCryptoCurrenciesFactory(excludedBlockchains) private val userTokensResponseFactory = UserTokensResponseFactory() override fun convert(value: SavedSwapTransactionListModel) = SavedSwapTransactionListModelInner( 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 fde540c8ab..5a1b3dcf85 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 @@ -1,6 +1,7 @@ package com.tangem.feature.swap.di import com.squareup.moshi.Moshi +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.datasource.api.express.TangemExpressApi import com.tangem.datasource.api.express.models.response.ExpressErrorResponse import com.tangem.datasource.crypto.DataSignatureVerifier @@ -34,6 +35,7 @@ internal class SwapDataModule { userWalletsListManager: UserWalletsListManager, errorsDataConverter: ErrorsDataConverter, @NetworkMoshi moshi: Moshi, + excludedBlockchains: ExcludedBlockchains, ): SwapRepository { return DefaultSwapRepository( tangemExpressApi = tangemExpressApi, @@ -43,6 +45,7 @@ internal class SwapDataModule { errorsDataConverter = errorsDataConverter, dataSignatureVerifier = dataSignature, moshi = moshi, + excludedBlockchains = excludedBlockchains, ) } @@ -51,10 +54,12 @@ internal class SwapDataModule { fun provideSwapTransactionRepository( appPreferencesStore: AppPreferencesStore, dispatcherProvider: CoroutineDispatcherProvider, + excludedBlockchains: ExcludedBlockchains, ): SwapTransactionRepository { return DefaultSwapTransactionRepository( appPreferencesStore = appPreferencesStore, dispatchers = dispatcherProvider, + excludedBlockchains = excludedBlockchains, ) } diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt index a9830d7036..2d32f24015 100644 --- a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt +++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt @@ -387,10 +387,6 @@ fun Blockchain.toMigratedCointId(): String = when (this) { else -> toCoinId() } -fun Blockchain.isSupportedInApp(): Boolean { - return !excludedBlockchains.contains(this) -} - fun Blockchain.amountToCreateAccount(token: Token? = null): BigDecimal? { return when (this) { Blockchain.Stellar -> if (token?.symbol == NODL) BigDecimal(NODL_AMOUNT_TO_CREATE_ACCOUNT) else BigDecimal.ONE @@ -409,11 +405,4 @@ fun Blockchain.minimalAmount(): BigDecimal { } private const val NODL = "NODL" -private const val NODL_AMOUNT_TO_CREATE_ACCOUNT = 1.5 - -// no need to add testnets -private val excludedBlockchains = listOf( - Blockchain.Unknown, - Blockchain.Nexa, - Blockchain.NexaTestnet, -) \ No newline at end of file +private const val NODL_AMOUNT_TO_CREATE_ACCOUNT = 1.5 \ No newline at end of file diff --git a/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt b/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt index c2205435c2..456959fddd 100644 --- a/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt +++ b/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt @@ -3,8 +3,8 @@ package com.tangem.lib.crypto import com.tangem.blockchain.blockchains.xrp.XrpAddressService import com.tangem.blockchain.common.Blockchain import com.tangem.blockchainsdk.compatibility.l2BlockchainsList +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId -import com.tangem.blockchainsdk.utils.isSupportedInApp import com.tangem.lib.crypto.converter.XrpTaggedAddressConverter import com.tangem.lib.crypto.models.XrpTaggedAddress @@ -64,8 +64,10 @@ object BlockchainUtils { return blockchain == Blockchain.Tron || blockchain == Blockchain.TronTestnet } - fun isSupportedNetworkId(blockchainId: String): Boolean { - return Blockchain.fromNetworkId(blockchainId)?.isSupportedInApp() ?: false + fun isSupportedNetworkId(blockchainId: String, excludedBlockchains: ExcludedBlockchains): Boolean { + val blockchain = Blockchain.fromNetworkId(blockchainId) + + return blockchain != null && blockchain !in excludedBlockchains } fun isArbitrum(blockchainId: String): Boolean { From 9df8eb5ad48a63502530044998988b2cf0806933 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 26 Nov 2024 16:26:53 +0400 Subject: [PATCH 12/22] Updated on 2026-08-14 --- .../tangem/tap/domain/card/CryptoCurrenciesMocks.kt | 3 ++- .../domain/card/DefaultDerivationsRepositoryTest.kt | 2 ++ .../blockchainsdk/utils/ExcludedBlockchains.kt | 13 +++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt b/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt index b44074274b..3ff9b7bf0e 100644 --- a/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt +++ b/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt @@ -3,6 +3,7 @@ package com.tangem.tap.domain.card import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.FeePaidCurrency import com.tangem.blockchain.common.Token +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.toNetworkId import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.data.common.currency.getNetworkDerivationPath @@ -17,7 +18,7 @@ import com.tangem.domain.tokens.model.Network */ internal class CryptoCurrenciesMocks(private val scanResponse: ScanResponse) { - private val factory = CryptoCurrencyFactory() + private val factory = CryptoCurrencyFactory(excludedBlockchains = ExcludedBlockchains()) val cardano by lazy { listOf(createCoin(blockchain = Blockchain.Cardano)) } val chia by lazy { listOf(element = createCoin(Blockchain.Chia)) } diff --git a/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt b/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt index 93a58d5ba5..095156e1c2 100644 --- a/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt +++ b/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt @@ -2,6 +2,7 @@ package com.tangem.tap.domain.card import android.annotation.SuppressLint import com.google.common.truth.Truth +import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.common.CompletionResult import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.card.ScanCardException @@ -29,6 +30,7 @@ internal class DefaultDerivationsRepositoryTest { tangemSdkManager = tangemSdkManager, userWalletsStore = userWalletsStore, dispatchers = TestingCoroutineDispatcherProvider(), + excludedBlockchains = ExcludedBlockchains(), ) private val defaultUserWalletId = UserWalletId("011") diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ExcludedBlockchains.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ExcludedBlockchains.kt index b443a9b0e7..6e2cb4877d 100644 --- a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ExcludedBlockchains.kt +++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ExcludedBlockchains.kt @@ -2,6 +2,7 @@ package com.tangem.blockchainsdk.utils import com.tangem.blockchain.common.Blockchain import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager +import org.jetbrains.annotations.TestOnly import javax.inject.Inject class ExcludedBlockchains @Inject internal constructor( @@ -22,6 +23,18 @@ class ExcludedBlockchains @Inject internal constructor( override val size: Int get() = excludedBlockchains.size + @TestOnly + constructor() : this( + excludedBlockchainsManager = object : ExcludedBlockchainsManager { + + override val excludedBlockchainsIds: Set = emptySet() + + override suspend fun init() { + /* no-op */ + } + }, + ) + override fun contains(element: Blockchain): Boolean = excludedBlockchains.contains(element) override fun containsAll(elements: Collection): Boolean = excludedBlockchains.containsAll(elements) From 8baa8844041029c8c7123c6278e2c44dff7b6c39 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 26 Nov 2024 18:15:27 +0300 Subject: [PATCH 13/22] Updated on 2026-08-14 --- gradle/dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index e32d4d13c7..dae5edfbd0 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -87,9 +87,9 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.18-872" +tangemBlockchainSdk = "release-app_5.18-873" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_5.18-402" +tangemCardSdk = "release-app_5.18-405" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem17" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ From c2c95b8d896050c67b3d4a88b683d7a688e795f4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 26 Nov 2024 18:32:04 +0300 Subject: [PATCH 14/22] Updated on 2026-08-14 --- gradle/dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index dae5edfbd0..c086ede1d7 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -89,7 +89,7 @@ markdownComposeView = "0.5.4" # region Tangem tangemBlockchainSdk = "release-app_5.18-873" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_5.18-405" +tangemCardSdk = "release-app_5.18-406" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem17" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ From bfea5c6ca1a45a45332c6167a7965cc94dd6b66b Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 27 Nov 2024 00:02:33 +0300 Subject: [PATCH 15/22] Updated on 2026-08-14 --- features/qr-scanning/impl/build.gradle.kts | 4 ++++ .../qrscanning/viewmodel/QrScanningViewModel.kt | 14 ++++++++++++++ gradle/dependencies.toml | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/features/qr-scanning/impl/build.gradle.kts b/features/qr-scanning/impl/build.gradle.kts index f2dfb02aa4..87bb1cc68e 100644 --- a/features/qr-scanning/impl/build.gradle.kts +++ b/features/qr-scanning/impl/build.gradle.kts @@ -47,6 +47,9 @@ dependencies { implementation(projects.domain.qrScanning) implementation(projects.domain.qrScanning.models) + /** Data */ + implementation(projects.data.card) + /** Compose */ implementation(deps.compose.foundation) implementation(deps.compose.ui) @@ -57,4 +60,5 @@ dependencies { /** Other dependencies */ implementation(deps.arrow.core) implementation(deps.timber) + implementation(deps.tangem.card.core) } \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningViewModel.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningViewModel.kt index 49b23ff8cd..a504e00e9f 100644 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningViewModel.kt +++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.tangem.common.routing.AppRoute +import com.tangem.data.card.sdk.CardSdkProvider import com.tangem.domain.qrscanning.models.SourceType import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter import com.tangem.feature.qrscanning.presentation.QrScanningState @@ -20,6 +21,7 @@ import javax.inject.Inject internal class QrScanningViewModel @Inject constructor( private val stateHolder: QrScanningStateController, private val clickIntents: QrScanningClickIntentsImplementor, + private val cardSdkProvider: CardSdkProvider, savedStateHandle: SavedStateHandle, ) : ViewModel() { @@ -31,6 +33,12 @@ internal class QrScanningViewModel @Inject constructor( val uiState: StateFlow = stateHolder.uiState val launchGalleryEvent: SharedFlow = clickIntents.launchGallery + init { + // samsung for some reason disables reader mode, and then it works unstable + // to prevent this disable ir manually before scan QR + cardSdkProvider.sdk.forceDisableReaderMode() + } + fun setRouter(router: QrScanningInnerRouter) { clickIntents.initialize( router = router, @@ -49,4 +57,10 @@ internal class QrScanningViewModel @Inject constructor( fun onDismissBottomSheetState() { stateHolder.update(DismissBottomSheetTransformer()) } + + override fun onCleared() { + super.onCleared() + // don't forget enable reader mode after scan complete + cardSdkProvider.sdk.forceEnableReaderMode() + } } \ No newline at end of file diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index c086ede1d7..43982c3906 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -89,7 +89,7 @@ markdownComposeView = "0.5.4" # region Tangem tangemBlockchainSdk = "release-app_5.18-873" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_5.18-406" +tangemCardSdk = "release-app_5.18-407" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem17" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ From bf281c19291f0fa0822b1d48f5aef9785e9e4737 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 27 Nov 2024 15:53:04 +0400 Subject: [PATCH 16/22] Updated on 2026-08-14 --- gradle/dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 43982c3906..baaba703a2 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -89,7 +89,7 @@ markdownComposeView = "0.5.4" # region Tangem tangemBlockchainSdk = "release-app_5.18-873" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_5.18-407" +tangemCardSdk = "release-app_5.18-408" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem17" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ From f347cb2c8cb78e107b2b624c701b3505f0ae1a49 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 28 Nov 2024 14:10:18 +0300 Subject: [PATCH 17/22] Updated on 2026-08-14 --- .../com/tangem/feature/swap/converters/ErrorsDataConverter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt index 71196ab9a7..2df4aa2f11 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt @@ -92,8 +92,8 @@ internal class ErrorsDataConverter( return ExpressDataError.ProviderDifferentAmountError( code = error.code, decimals = decimals, - fromAmount = fromAmount, - fromProviderAmount = fromAmountProvider, + fromAmount = fromAmount.movePointLeft(decimals), + fromProviderAmount = fromAmountProvider.movePointLeft(decimals), ) } } \ No newline at end of file From fef9d0f593a14f356c27df30eff9397eb11974f5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 28 Nov 2024 14:12:38 +0300 Subject: [PATCH 18/22] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- gradle/dependencies.toml | 2 +- .../main/java/com/tangem/blockchainsdk/utils/ProviderTypeExt.kt | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index f859554840..f1aa2f2cbf 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit f859554840df30c25a8fe266de2db7ef71cf5652 +Subproject commit f1aa2f2cbf374ecba5da753d9f51c9df81749ef2 diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index baaba703a2..59dbe7832a 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -87,7 +87,7 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.18-873" +tangemBlockchainSdk = "release-app_5.18-874" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.18-408" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ProviderTypeExt.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ProviderTypeExt.kt index 1d88ec5f27..3b32c69ae9 100644 --- a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ProviderTypeExt.kt +++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/ProviderTypeExt.kt @@ -13,6 +13,7 @@ fun createPrivateProviderType(name: String): ProviderType? { "tangemRosetta" -> ProviderType.Cardano.Rosetta "fireAcademy" -> ProviderType.Chia.FireAcademy "tangemChia" -> ProviderType.Chia.Tangem + "tangemChia3" -> ProviderType.Chia.TangemNew "infura" -> ProviderType.EthereumLike.Infura "getblock" -> ProviderType.GetBlock "arkhiaHedera" -> ProviderType.Hedera.Arkhia From a6569014e5b5bee5273408ed7c742a8415a86103 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 28 Nov 2024 16:00:28 +0300 Subject: [PATCH 19/22] Updated on 2026-08-14 --- gradle/dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 59dbe7832a..2d7317203b 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -89,7 +89,7 @@ markdownComposeView = "0.5.4" # region Tangem tangemBlockchainSdk = "release-app_5.18-874" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_5.18-408" +tangemCardSdk = "release-app_5.18-409" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem17" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ From 164e0718e64088cce57593aa3f21bba1320d31b0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 29 Nov 2024 11:57:20 +0400 Subject: [PATCH 20/22] Updated on 2026-08-14 --- core/res/src/main/res/values-de/strings.xml | 1 + core/res/src/main/res/values-ja/strings.xml | 1 + core/res/src/main/res/values-ru/strings.xml | 1 + core/res/src/main/res/values/strings.xml | 1 + .../ui/components/tokenlist/TokenListItem.kt | 10 +++ .../tokenlist/state/TokensListItemUM.kt | 2 + .../model/AvailableSwapPairsModel.kt | 42 +++++++----- .../SetNothingToFoundStateTransformer.kt | 65 +++++++++++++++++++ .../tokenlist/model/OnrampTokenListModel.kt | 52 ++++++++------- 9 files changed, 138 insertions(+), 37 deletions(-) create mode 100644 features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/entity/transformer/SetNothingToFoundStateTransformer.kt diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index 4197e69d71..7d74f429b0 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -891,6 +891,7 @@ Nicht verfügbar zum Kauf Nicht zum Verkauf verfügbar Nicht verfügbar für Tausch von %s + Nicht zum Tausch verfügbar Vertrag: %s Du hast noch keine Transaktionen Der Transaktionsverlauf konnte nicht geladen werden.\nKlicke auf die Schaltfläche Neu laden, um die Informationen zu aktualisieren. diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 5849f7d083..1b346bf8cf 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -882,6 +882,7 @@ 買付できません 売却できません %sからのスワップは利用できません + スワップはできません コントラクト: %s まだ取引はありません 取引履歴の読み込みに失敗しました。\n情報を更新するには、リロードボタンをクリックしてください。 diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 88c9836ebf..7b9a25c8cd 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -914,6 +914,7 @@ Недоступно для покупки Недоступно для продажи Недоступно для обмена с %s + Недоступно для обмена контракт: %s У вас еще нет транзакций Не удалось загрузить историю транзакций.\nНажмите на кнопку перезагрузки, чтобы обновить информацию. diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index ef80d3a558..18cf4fecf0 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -898,6 +898,7 @@ Unavailable to purchase Unavailable to sell Unavailable for swap from %s + Unavailable for swap contract: %s You don\'t have any transactions yet Failed to load transaction history.\nClick on reload button to update the information. diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/TokenListItem.kt b/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/TokenListItem.kt index b76e11c37c..1a4d6d8dae 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/TokenListItem.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/TokenListItem.kt @@ -1,6 +1,7 @@ package com.tangem.core.ui.components.tokenlist import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -10,6 +11,7 @@ import com.tangem.core.ui.components.tokenlist.internal.GroupTitleItem import com.tangem.core.ui.components.tokenlist.internal.NetworkTitleItem import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.res.TangemTheme /** * Multi-currency content item @@ -39,5 +41,13 @@ fun TokenListItem(state: TokensListItemUM, isBalanceHidden: Boolean, modifier: M is TokensListItemUM.SearchBar -> { SearchBar(state = state.searchBarUM, modifier = modifier.padding(all = 12.dp)) } + is TokensListItemUM.Text -> { + Text( + text = state.text.resolveReference(), + modifier = modifier.padding(all = 12.dp), + color = TangemTheme.colors.text.tertiary, + style = TangemTheme.typography.body2, + ) + } } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/state/TokensListItemUM.kt b/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/state/TokensListItemUM.kt index 2e9417d5ed..23332310aa 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/state/TokensListItemUM.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/state/TokensListItemUM.kt @@ -48,4 +48,6 @@ sealed interface TokensListItemUM { data class Token(val state: TokenItemState) : TokensListItemUM { override val id: String = state.id } + + data class Text(override val id: Any, val text: TextReference) : TokensListItemUM } \ No newline at end of file diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/availablepairs/model/AvailableSwapPairsModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/availablepairs/model/AvailableSwapPairsModel.kt index 4d639a5c46..a84dd28b38 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/availablepairs/model/AvailableSwapPairsModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/availablepairs/model/AvailableSwapPairsModel.kt @@ -22,6 +22,7 @@ import com.tangem.features.onramp.swap.availablepairs.AvailableSwapPairsComponen import com.tangem.features.onramp.swap.availablepairs.entity.transformers.SetLoadingTokenItemsTransformer import com.tangem.features.onramp.tokenlist.entity.TokenListUM import com.tangem.features.onramp.tokenlist.entity.TokenListUMController +import com.tangem.features.onramp.tokenlist.entity.transformer.SetNothingToFoundStateTransformer import com.tangem.features.onramp.tokenlist.entity.transformer.UpdateTokenItemsTransformer import com.tangem.features.onramp.utils.InputManager import com.tangem.features.onramp.utils.UpdateSearchBarActiveStateTransformer @@ -80,24 +81,35 @@ internal class AvailableSwapPairsModel @Inject constructor( } else { val (appCurrency, isBalanceHidden) = appCurrencyAndBalanceHiding - val filterTokenList = currencies + val filterByQueryTokenList = currencies .filter { it.currency != selectedStatus?.currency } .filterByQuery(query = query) - .filterByAvailability(availablePairs = availablePairs) - UpdateTokenItemsTransformer( - appCurrency = appCurrency, - onItemClick = params.onTokenClick, - statuses = filterTokenList, - isBalanceHidden = isBalanceHidden, - hasSearchBar = currencies.isNotEmpty(), - unavailableTokensHeaderReference = resourceReference( - id = R.string.tokens_list_unavailable_to_swap_header, - wrappedList(selectedStatus?.currency?.name?.capitalize() ?: ""), - ), - onQueryChange = ::onSearchQueryChange, - onActiveChange = ::onSearchBarActiveChange, - ) + if (query.isNotEmpty() && filterByQueryTokenList.isEmpty()) { + SetNothingToFoundStateTransformer( + isBalanceHidden = isBalanceHidden, + hasSearchBar = currencies.isNotEmpty(), + emptySearchMessageReference = resourceReference( + id = R.string.action_buttons_swap_empty_search_message, + ), + onQueryChange = ::onSearchQueryChange, + onActiveChange = ::onSearchBarActiveChange, + ) + } else { + UpdateTokenItemsTransformer( + appCurrency = appCurrency, + onItemClick = params.onTokenClick, + statuses = filterByQueryTokenList.filterByAvailability(availablePairs = availablePairs), + isBalanceHidden = isBalanceHidden, + hasSearchBar = currencies.isNotEmpty(), + unavailableTokensHeaderReference = resourceReference( + id = R.string.tokens_list_unavailable_to_swap_header, + wrappedList(selectedStatus?.currency?.name?.capitalize() ?: ""), + ), + onQueryChange = ::onSearchQueryChange, + onActiveChange = ::onSearchBarActiveChange, + ) + } } } .onEach(tokenListUMController::update) diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/entity/transformer/SetNothingToFoundStateTransformer.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/entity/transformer/SetNothingToFoundStateTransformer.kt new file mode 100644 index 0000000000..a3ec0c3e4e --- /dev/null +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/entity/transformer/SetNothingToFoundStateTransformer.kt @@ -0,0 +1,65 @@ +package com.tangem.features.onramp.tokenlist.entity.transformer + +import com.tangem.core.ui.components.fields.entity.SearchBarUM +import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.features.onramp.impl.R +import com.tangem.features.onramp.tokenlist.entity.TokenListUM +import com.tangem.features.onramp.tokenlist.entity.TokenListUMTransformer +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList + +internal class SetNothingToFoundStateTransformer( + private val isBalanceHidden: Boolean, + private val hasSearchBar: Boolean, + private val emptySearchMessageReference: TextReference, + private val onQueryChange: (String) -> Unit, + private val onActiveChange: (Boolean) -> Unit, +) : TokenListUMTransformer { + + override fun transform(prevState: TokenListUM): TokenListUM { + val searchBarItem = if (hasSearchBar) { + prevState.getSearchBar() ?: createSearchBarItem() + } else { + null + } + + return prevState.copy( + availableItems = buildList { + if (searchBarItem != null) { + add(searchBarItem) + } + + createGroupTitle( + textReference = resourceReference(id = R.string.exchange_tokens_available_tokens_header), + ) + .let(::add) + + TokensListItemUM.Text( + id = emptySearchMessageReference.hashCode(), + text = emptySearchMessageReference, + ).let(::add) + } + .toImmutableList(), + unavailableItems = persistentListOf(), + isBalanceHidden = isBalanceHidden, + ) + } + + private fun createSearchBarItem(): TokensListItemUM.SearchBar { + return TokensListItemUM.SearchBar( + searchBarUM = SearchBarUM( + placeholderText = resourceReference(id = R.string.common_search), + query = "", + onQueryChange = onQueryChange, + isActive = false, + onActiveChange = onActiveChange, + ), + ) + } + + private fun createGroupTitle(textReference: TextReference): TokensListItemUM.GroupTitle { + return TokensListItemUM.GroupTitle(id = textReference.hashCode(), text = textReference) + } +} \ No newline at end of file diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/model/OnrampTokenListModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/model/OnrampTokenListModel.kt index c86d5ec70f..4df19b9727 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/model/OnrampTokenListModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/model/OnrampTokenListModel.kt @@ -4,7 +4,6 @@ import arrow.core.getOrElse import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase @@ -19,6 +18,7 @@ import com.tangem.features.onramp.tokenlist.OnrampTokenListComponent import com.tangem.features.onramp.tokenlist.entity.OnrampOperation import com.tangem.features.onramp.tokenlist.entity.TokenListUM import com.tangem.features.onramp.tokenlist.entity.TokenListUMController +import com.tangem.features.onramp.tokenlist.entity.transformer.SetNothingToFoundStateTransformer import com.tangem.features.onramp.tokenlist.entity.transformer.UpdateTokenItemsTransformer import com.tangem.features.onramp.utils.InputManager import com.tangem.features.onramp.utils.UpdateSearchBarActiveStateTransformer @@ -65,30 +65,38 @@ internal class OnrampTokenListModel @Inject constructor( ) .flattenCurrencies() - val filterTokenList = currencies + val filterByQueryTokenList = currencies .filterByQuery(query = query) - .filterByAvailability() - UpdateTokenItemsTransformer( - appCurrency = appCurrency, - onItemClick = params.onTokenClick, - statuses = filterTokenList, - isBalanceHidden = isBalanceHidden, - hasSearchBar = params.hasSearchBar && currencies.isNotEmpty(), - unavailableTokensHeaderReference = when (params.filterOperation) { - OnrampOperation.BUY -> resourceReference(id = R.string.tokens_list_unavailable_to_purchase_header) - OnrampOperation.SELL -> resourceReference(id = R.string.tokens_list_unavailable_to_sell_header) - OnrampOperation.SWAP -> { - // TODO: [REDACTED_JIRA] - resourceReference( - id = R.string.tokens_list_unavailable_to_swap_header, - wrappedList(""), - ) + if (query.isNotEmpty() && filterByQueryTokenList.isEmpty()) { + SetNothingToFoundStateTransformer( + isBalanceHidden = isBalanceHidden, + hasSearchBar = params.hasSearchBar && currencies.isNotEmpty(), + emptySearchMessageReference = when (params.filterOperation) { + OnrampOperation.BUY -> R.string.action_buttons_buy_empty_search_message + OnrampOperation.SELL -> R.string.action_buttons_sell_empty_search_message + OnrampOperation.SWAP -> R.string.action_buttons_swap_empty_search_message } - }, - onQueryChange = ::onSearchQueryChange, - onActiveChange = ::onSearchBarActiveChange, - ) + .let(::resourceReference), + onQueryChange = ::onSearchQueryChange, + onActiveChange = ::onSearchBarActiveChange, + ) + } else { + UpdateTokenItemsTransformer( + appCurrency = appCurrency, + onItemClick = params.onTokenClick, + statuses = filterByQueryTokenList.filterByAvailability(), + isBalanceHidden = isBalanceHidden, + hasSearchBar = params.hasSearchBar && currencies.isNotEmpty(), + unavailableTokensHeaderReference = when (params.filterOperation) { + OnrampOperation.BUY -> R.string.tokens_list_unavailable_to_purchase_header + OnrampOperation.SELL -> R.string.tokens_list_unavailable_to_sell_header + OnrampOperation.SWAP -> R.string.tokens_list_unavailable_to_swap_source_header + }.let(::resourceReference), + onQueryChange = ::onSearchQueryChange, + onActiveChange = ::onSearchBarActiveChange, + ) + } } .onEach(tokenListUMController::update) .flowOn(dispatchers.main) From ab1b0b082cfc17bff3d352bf034717c677a4abb6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 28 Nov 2024 17:53:01 +0200 Subject: [PATCH 21/22] Updated on 2026-08-14 --- .../presentation/state/StakingStateController.kt | 1 + .../impl/presentation/state/StakingStateRouter.kt | 13 +++++++++++-- .../impl/presentation/state/StakingUiState.kt | 1 + .../transformers/SetInitialDataStateTransformer.kt | 1 + .../presentation/ui/StakingConfirmationContent.kt | 4 +++- .../staking/impl/presentation/ui/StakingScreen.kt | 2 ++ 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt index 36229ac7ff..e66c38a778 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt @@ -75,6 +75,7 @@ internal class StakingStateController @Inject constructor( walletName = "", cryptoCurrencyName = "", cryptoCurrencySymbol = "", + cryptoCurrencyBlockchainId = "", currentStep = StakingStep.InitialInfo, initialInfoState = StakingStates.InitialInfoState.Empty(), amountState = AmountState.Empty(), 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 5e717bb916..d7e8d24c25 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 @@ -5,6 +5,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType import com.tangem.domain.staking.analytics.StakingAnalyticsEvent import com.tangem.features.staking.impl.analytics.utils.StakingAnalyticSender +import com.tangem.lib.crypto.BlockchainUtils.isSolana internal class StakingStateRouter( private val appRouter: AppRouter, @@ -23,7 +24,13 @@ internal class StakingStateRouter( fun onNextClick() { when (stateController.value.currentStep) { StakingStep.InitialInfo -> when (stateController.value.actionType) { - StakingActionCommonType.Enter, StakingActionCommonType.Exit -> showAmount() + StakingActionCommonType.Enter -> showAmount() + // TODO staking [REDACTED_TASK_KEY] support solana multisize hashes signing + StakingActionCommonType.Exit -> if (isSolana(stateController.value.cryptoCurrencyBlockchainId)) { + showConfirmation() + } else { + showAmount() + } StakingActionCommonType.Pending.Other, StakingActionCommonType.Pending.Rewards, -> showConfirmation() @@ -50,7 +57,9 @@ internal class StakingStateRouter( val isEnter = uiState.actionType == StakingActionCommonType.Enter val isExit = uiState.actionType == StakingActionCommonType.Exit - if (isEnter || isExit) { + // TODO staking [REDACTED_TASK_KEY] support solana multisize hashes signing + val isSolana = isSolana(uiState.cryptoCurrencyBlockchainId) + if (isEnter || isExit && !isSolana) { showAmount() } else { showInitial() diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt index f2f28dd8af..c8c0be08e6 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt @@ -29,6 +29,7 @@ internal data class StakingUiState( val walletName: String, val cryptoCurrencyName: String, val cryptoCurrencySymbol: String, + val cryptoCurrencyBlockchainId: String, val currentStep: StakingStep, val initialInfoState: StakingStates.InitialInfoState, val amountState: AmountState, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt index 9d819bcbf8..6825aeb4f6 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt @@ -64,6 +64,7 @@ internal class SetInitialDataStateTransformer( title = TextReference.EMPTY, cryptoCurrencyName = cryptoCurrency.name, cryptoCurrencySymbol = cryptoCurrency.symbol, + cryptoCurrencyBlockchainId = cryptoCurrency.network.id.value, clickIntents = clickIntents, currentStep = StakingStep.InitialInfo, initialInfoState = createInitialInfoState(), diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmationContent.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmationContent.kt index d36ad76e77..2df8cdd525 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmationContent.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmationContent.kt @@ -40,9 +40,10 @@ internal fun StakingConfirmationContent( validatorState: StakingStates.ValidatorState, clickIntents: StakingClickIntents, type: StakingActionCommonType, + isSolana: Boolean, // TODO staking [REDACTED_TASK_KEY] support solana multisize hashes signing ) { if (state !is StakingStates.ConfirmationState.Data) return - val isAmountEditable = type == StakingActionCommonType.Enter || type == StakingActionCommonType.Exit + val isAmountEditable = type == StakingActionCommonType.Enter || type == StakingActionCommonType.Exit && !isSolana val isTransactionSent = state.innerState == InnerConfirmationStakingState.COMPLETED val isTransactionInProgress = state.notifications.any { it is StakingNotification.Warning.TransactionInProgress } Column( @@ -90,6 +91,7 @@ private fun Preview_StakingConfirmationContent() { validatorState = ValidatorStatePreviewData.validatorState, clickIntents = StakingClickIntentsStub, type = StakingActionCommonType.Enter, + isSolana = false, ) } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt index 21be700364..8e6b03d04c 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt @@ -28,6 +28,7 @@ import com.tangem.features.staking.impl.presentation.state.bottomsheet.StakingAc import com.tangem.features.staking.impl.presentation.state.bottomsheet.StakingInfoBottomSheetConfig import com.tangem.features.staking.impl.presentation.ui.bottomsheet.StakingActionSelectorBottomSheet import com.tangem.features.staking.impl.presentation.ui.bottomsheet.StakingInfoBottomSheet +import com.tangem.lib.crypto.BlockchainUtils.isSolana import kotlinx.coroutines.delay import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map @@ -170,6 +171,7 @@ private fun StakingScreenContent(uiState: StakingUiState, modifier: Modifier = M validatorState = uiState.validatorState, clickIntents = uiState.clickIntents, type = uiState.actionType, + isSolana = isSolana(uiState.cryptoCurrencyBlockchainId), ) StakingStep.RestakeValidator, StakingStep.Validators, From 2b41ded8afebfc9c81ff9a3b1402cc090c16eb1b Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 28 Nov 2024 14:59:56 +0300 Subject: [PATCH 22/22] Updated on 2026-08-14 --- app/build.gradle.kts | 4 +- .../DefaultLegacyWalletConnectRepository.kt | 42 ++++++++----------- gradle/dependencies.toml | 8 ++-- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e6d30a7cc6..c939548392 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -228,8 +228,8 @@ dependencies { implementation(deps.armadillo) implementation(deps.mviCore.watcher) implementation(deps.kotlin.serialization) - implementation(deps.walletConnectCore) - implementation(deps.walletConnectWeb3) + implementation(deps.reownCore) + implementation(deps.reownWeb3) implementation(deps.prettyLogger) /** Testing libraries */ diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/DefaultLegacyWalletConnectRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/DefaultLegacyWalletConnectRepository.kt index bcf6ba147c..776836a294 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/DefaultLegacyWalletConnectRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/DefaultLegacyWalletConnectRepository.kt @@ -2,6 +2,11 @@ package com.tangem.tap.domain.walletconnect2.data import android.app.Application import arrow.core.flatten +import com.reown.android.Core +import com.reown.android.CoreClient +import com.reown.android.relay.ConnectionType +import com.reown.walletkit.client.Wallet +import com.reown.walletkit.client.WalletKit import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.tap.common.analytics.events.WalletConnect import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository @@ -9,11 +14,6 @@ import com.tangem.tap.domain.walletconnect2.domain.WcJrpcMethods import com.tangem.tap.domain.walletconnect2.domain.WcJrpcRequestsDeserializer import com.tangem.tap.domain.walletconnect2.domain.WcRequest import com.tangem.tap.domain.walletconnect2.domain.models.* -import com.walletconnect.android.Core -import com.walletconnect.android.CoreClient -import com.walletconnect.android.relay.ConnectionType -import com.walletconnect.web3.wallet.client.Wallet -import com.walletconnect.web3.wallet.client.Web3Wallet import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow @@ -72,7 +72,7 @@ internal class DefaultLegacyWalletConnectRepository( } } - Web3Wallet.initialize(Wallet.Params.Init(core = CoreClient)) { error -> + WalletKit.initialize(Wallet.Params.Init(core = CoreClient)) { error -> Timber.e("Error while initializing Web3Wallet: $error") scope.launch { _events.emit( @@ -84,11 +84,11 @@ internal class DefaultLegacyWalletConnectRepository( } val walletDelegate = defineWalletDelegate() - Web3Wallet.setWalletDelegate(walletDelegate) + WalletKit.setWalletDelegate(walletDelegate) } - private fun defineWalletDelegate(): Web3Wallet.WalletDelegate { - return object : Web3Wallet.WalletDelegate { + private fun defineWalletDelegate(): WalletKit.WalletDelegate { + return object : WalletKit.WalletDelegate { override fun onSessionProposal( sessionProposal: Wallet.Model.SessionProposal, verifyContext: Wallet.Model.VerifyContext, @@ -188,14 +188,6 @@ internal class DefaultLegacyWalletConnectRepository( } } - override fun onAuthRequest( - authRequest: Wallet.Model.AuthRequest, - verifyContext: Wallet.Model.VerifyContext, - ) { - // Triggered when Dapp / Requester makes an authorization request - Timber.i("onAuthRequest: $authRequest") - } - override fun onSessionDelete(sessionDelete: Wallet.Model.SessionDelete) { // Triggered when the session is deleted by the peer if (sessionDelete is Wallet.Model.SessionDelete.Success) { @@ -251,7 +243,7 @@ internal class DefaultLegacyWalletConnectRepository( } override fun pair(uri: String) { - Web3Wallet.pair( + WalletKit.pair( params = Wallet.Params.Pair(uri), onSuccess = { Timber.i("Paired successfully: $it") @@ -303,7 +295,7 @@ internal class DefaultLegacyWalletConnectRepository( Timber.i("Session approval is prepared for sending: $sessionApproval") - Web3Wallet.approveSession( + WalletKit.approveSession( params = sessionApproval, onSuccess = { Timber.i("Approved successfully: $it") @@ -364,7 +356,7 @@ internal class DefaultLegacyWalletConnectRepository( ) } - Web3Wallet.respondSessionRequest( + WalletKit.respondSessionRequest( params = Wallet.Params.SessionRequestResponse( sessionTopic = requestData.topic, jsonRpcResponse = Wallet.Model.JsonRpcResponse.JsonRpcResult( @@ -409,7 +401,7 @@ internal class DefaultLegacyWalletConnectRepository( } override fun cancelRequest(topic: String, id: Long, message: String) { - Web3Wallet.respondSessionRequest( + WalletKit.respondSessionRequest( params = Wallet.Params.SessionRequestResponse( sessionTopic = topic, jsonRpcResponse = Wallet.Model.JsonRpcResponse.JsonRpcError( @@ -424,7 +416,7 @@ internal class DefaultLegacyWalletConnectRepository( } override fun reject() { - Web3Wallet.rejectSession( + WalletKit.rejectSession( params = Wallet.Params.SessionReject( proposerPublicKey = sessionProposal?.proposerPublicKey ?: "", reason = "", @@ -440,7 +432,7 @@ internal class DefaultLegacyWalletConnectRepository( override fun disconnect(topic: String) { val session = currentSessions.find { it.topic == topic } - Web3Wallet.disconnectSession( + WalletKit.disconnectSession( params = Wallet.Params.SessionDisconnect(topic), onSuccess = { analyticsHandler.send( @@ -459,7 +451,7 @@ internal class DefaultLegacyWalletConnectRepository( } fun send(topic: String, id: Long, data: String) { - Web3Wallet.respondSessionRequest( + WalletKit.respondSessionRequest( params = Wallet.Params.SessionRequestResponse( sessionTopic = topic, jsonRpcResponse = Wallet.Model.JsonRpcResponse.JsonRpcResult( @@ -477,7 +469,7 @@ internal class DefaultLegacyWalletConnectRepository( } private fun updateSessionsInternal(): Job = scope.launch { - val availableSessions = Web3Wallet.getListOfActiveSessions() + val availableSessions = WalletKit.getListOfActiveSessions() .map { WalletConnectSession( topic = it.topic, diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index cbd909be0e..42c41b11d8 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -70,8 +70,8 @@ zxingQrCode = "3.5.1" mviCore = "1.3.1" kotlinSerialization = "1.4.1" arrow = "1.2.3" -walletConnectCore = "1.35.2" -walletConnectWeb3 = "1.35.2" +reownCore = "1.0.2" +reownWeb3 = "1.0.2" prettyLogger = "2.2.0" okHttp-prettyLogging = "3.1.0" chucker = "4.0.0" @@ -251,8 +251,8 @@ mviCore-watcher = { module = "com.github.badoo.mvicore:mvicore-diff", version.re kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinSerialization" } arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" } arrow-fx = { module = "io.arrow-kt:arrow-fx-coroutines", version.ref = "arrow" } -walletConnectCore = { module = "com.walletconnect:android-core", version.ref = "walletConnectCore" } -walletConnectWeb3 = { module = "com.walletconnect:web3wallet", version.ref = "walletConnectWeb3" } +reownCore = { module = "com.reown:android-core", version.ref = "reownCore" } +reownWeb3 = { module = "com.reown:walletkit", version.ref = "reownWeb3" } prettyLogger = { module = "com.orhanobut:logger", version.ref = "prettyLogger" } chucker = { module = "com.github.chuckerteam.chucker:library", version.ref = "chucker" } chuckerStub = { module = "com.github.chuckerteam.chucker:library-no-op", version.ref = "chucker" }