From 0f27f563ef453bfd05da9b378e482517e1ae1131 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 10 Jul 2023 18:55:36 +0300 Subject: [PATCH 01/36] Updated on 2026-08-14 --- .../wallet/ui/utils/WalletDataOperations.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt index 4f9f9d5453..3f72a34acb 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt @@ -12,6 +12,7 @@ import com.tangem.tap.common.extensions.toFormattedCurrencyString import com.tangem.tap.common.extensions.toFormattedFiatValue import com.tangem.tap.domain.model.WalletDataModel import com.tangem.tap.domain.model.WalletStoreModel +import com.tangem.tap.features.wallet.models.PendingTransactionType import com.tangem.tap.features.wallet.models.WalletWarning import com.tangem.tap.features.wallet.redux.WalletMainButton import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN @@ -26,15 +27,14 @@ internal fun WalletDataModel.mainButton(blockchainAmount: BigDecimal): WalletMai internal fun WalletDataModel.hasPendingTransactions(): Boolean { // for now check pending ongoing only just for BTC, later test and add other utxo networks - // disabled for release 4.8, test and enable in 4.9 - // val isBitcoinBlockchain = - // currency.blockchain == Blockchain.Bitcoin || currency.blockchain == Blockchain.BitcoinTestnet - // if (currency.isBlockchain() && isBitcoinBlockchain) { - // val outgoingTransactions = status.pendingTransactions.filter { - // it.type == PendingTransactionType.Outgoing - // } - // return outgoingTransactions.isEmpty() - // } + val isBitcoinBlockchain = + currency.blockchain == Blockchain.Bitcoin || currency.blockchain == Blockchain.BitcoinTestnet + if (currency.isBlockchain() && isBitcoinBlockchain) { + val outgoingTransactions = status.pendingTransactions.filter { + it.type == PendingTransactionType.Outgoing + } + return outgoingTransactions.isEmpty() + } return status.pendingTransactions.isEmpty() } From c2c8ae351820fe2e85274088b6619587647c3955 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 10 Jul 2023 18:57:16 +0300 Subject: [PATCH 02/36] Updated on 2026-08-14 --- .../src/main/assets/configs/feature_toggles_config.json | 2 +- gradle/dependencies.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json index 5dc4db710d..d0e3fddbe4 100644 --- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json @@ -9,7 +9,7 @@ }, { "name": "NEW_CARD_SCANNING_ENABLED", - "version": "4.9.0" + "version": "4.10.0" }, { "name": "REDESIGNED_WALLET_SCREEN_ENABLED", diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 515c8832d2..bab54848a3 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -78,9 +78,9 @@ walletConnectWeb3 = "1.10.0" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "develop-268" +tangemBlockchainSdk = "release-app_4.9-274" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "develop-266" +tangemCardSdk = "release-app_4.9-274" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds # endregion Tangem From 28537f24233534d551a1d2dde6f7fee3c7e3f2e7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 11 Jul 2023 18:25:04 +0300 Subject: [PATCH 03/36] Updated on 2026-08-14 --- .../src/main/assets/configs/feature_toggles_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json index d0e3fddbe4..b5005743ed 100644 --- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json @@ -17,7 +17,7 @@ }, { "name": "1INCH_LEARN_2_EARN_ENABLED", - "version": "undefined" + "version": "4.9.0" }, { "name": "REDESIGNED_TOKEN_DETAIL_SCREEN_ENABLED", From 63b2961c3935bcb220610cb5510c744886bc9555 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 11 Jul 2023 18:25:04 +0300 Subject: [PATCH 04/36] Updated on 2026-08-14 --- .../src/main/assets/configs/feature_toggles_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json index d0e3fddbe4..b5005743ed 100644 --- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json @@ -17,7 +17,7 @@ }, { "name": "1INCH_LEARN_2_EARN_ENABLED", - "version": "undefined" + "version": "4.9.0" }, { "name": "REDESIGNED_TOKEN_DETAIL_SCREEN_ENABLED", From 9028347b31b77af9d0d42f8de4ed1cb4c0f5e02e Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 11 Jul 2023 18:31:42 +0300 Subject: [PATCH 05/36] Updated on 2026-08-14 --- .../moonpay/MoonPayService.kt | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt index 0754f6c305..472fd9e6a5 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt @@ -7,7 +7,6 @@ import com.tangem.common.services.Result import com.tangem.common.services.performRequest import com.tangem.datasource.api.common.createRetrofitInstance import com.tangem.domain.common.extensions.withIOContext -import com.tangem.tap.common.extensions.urlEncode import com.tangem.tap.common.redux.global.CryptoCurrencyName import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager @@ -103,39 +102,37 @@ class MoonPayService( cryptoCurrencyName: CryptoCurrencyName, fatCurrency: String, walletAddress: String, - ): String? { + ): String { if (action == CurrencyExchangeManager.Action.Buy) throw UnsupportedOperationException() val uri = Uri.Builder() .scheme(SCHEME) .authority(URL_SELL) - .appendQueryParameter("apiKey", apiKey.urlEncode()) - .appendQueryParameter("baseCurrencyCode", cryptoCurrencyName.urlEncode()) - .appendQueryParameter("refundWalletAddress", walletAddress.urlEncode()) - .appendQueryParameter("redirectURL", "tangem://sell-request.tangem.com".urlEncode()) + .appendQueryParameter("apiKey", apiKey) + .appendQueryParameter("baseCurrencyCode", cryptoCurrencyName) + .appendQueryParameter("refundWalletAddress", walletAddress) + .appendQueryParameter("redirectURL", "tangem://sell-request.tangem.com") - val originalQuery = uri.build().toString() + val originalQuery = uri.build().encodedQuery ?: uri.build().toString() val signature = createSignature(originalQuery) - uri.appendQueryParameter("signature", signature.urlEncode()) + uri.appendQueryParameter("signature", signature) - val url = uri.build().toString() - return url + return uri.build().toString() } - override fun getSellCryptoReceiptUrl(action: CurrencyExchangeManager.Action, transactionId: String): String? { - val url = Uri.Builder() + override fun getSellCryptoReceiptUrl(action: CurrencyExchangeManager.Action, transactionId: String): String { + return Uri.Builder() .scheme(SCHEME) .authority(URL_SELL) .appendPath("transaction_receipt") .appendQueryParameter("transactionId", transactionId).build().toString() - return url } private fun createSignature(data: String): String { val sha256Hmac = Mac.getInstance("HmacSHA256") val secretKey = SecretKeySpec(secretKey.toByteArray(), "HmacSHA256") sha256Hmac.init(secretKey) - val sha256encoded = sha256Hmac.doFinal(data.toByteArray()) + val sha256encoded = sha256Hmac.doFinal("?$data".toByteArray()) return Base64.encodeToString(sha256encoded, Base64.NO_WRAP) } From 587377f71083287eebd14c8c28054ac606919182 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 12 Jul 2023 17:43:53 +0300 Subject: [PATCH 06/36] 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 bab54848a3..8366dd472c 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -78,7 +78,7 @@ walletConnectWeb3 = "1.10.0" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_4.9-274" +tangemBlockchainSdk = "release-app_4.9-282" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_4.9-274" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds From fb8e73b12bbcc8489509bb1a7027b61a69a87975 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 13 Jul 2023 18:01:44 +0400 Subject: [PATCH 07/36] Updated on 2026-08-14 --- .../data/WalletConnectRepositoryImpl.kt | 48 ++++++++++++++----- .../walletconnect2/domain/WcJrpcMethods.kt | 44 +++++++++++++++-- gradle/dependencies.toml | 4 +- 3 files changed, 78 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt index dcd79b0985..9890f9863f 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/data/WalletConnectRepositoryImpl.kt @@ -6,6 +6,7 @@ import com.tangem.core.analytics.Analytics import com.tangem.tap.common.analytics.events.WalletConnect import com.tangem.tap.domain.walletconnect2.domain.WalletConnectRepository 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 @@ -87,7 +88,10 @@ class WalletConnectRepositoryImpl @Inject constructor( private fun defineWalletDelegate(): Web3Wallet.WalletDelegate { return object : Web3Wallet.WalletDelegate { - override fun onSessionProposal(sessionProposal: Wallet.Model.SessionProposal) { + override fun onSessionProposal( + sessionProposal: Wallet.Model.SessionProposal, + verifyContext: Wallet.Model.VerifyContext, + ) { // Triggered when wallet receives the session proposal sent by a Dapp Timber.d("sessionProposal: $sessionProposal") this@WalletConnectRepositoryImpl.sessionProposal = sessionProposal @@ -106,7 +110,10 @@ class WalletConnectRepositoryImpl @Inject constructor( } } - override fun onSessionRequest(sessionRequest: Wallet.Model.SessionRequest) { + override fun onSessionRequest( + sessionRequest: Wallet.Model.SessionRequest, + verifyContext: Wallet.Model.VerifyContext, + ) { // Triggered when a Dapp sends SessionRequest to sign a transaction or a message Timber.d("sessionRequest: $sessionRequest") val request = wcRequestDeserializer.deserialize( @@ -115,22 +122,38 @@ class WalletConnectRepositoryImpl @Inject constructor( ) Timber.d("sessionRequestParsed: $request") - scope.launch { - _events.emit( - WalletConnectEvents.SessionRequest( - request = request, - chainId = sessionRequest.chainId, + when (request) { + is WcRequest.AddChain -> { + // we can send approval automatically, because in WC 2.0 the list of chains is approved when + // initial connection is established + sendRequest( topic = sessionRequest.topic, id = sessionRequest.request.id, - metaUrl = sessionRequest.peerMetaData?.url ?: "", - metaName = sessionRequest.peerMetaData?.name ?: "", - ), - ) + result = "", + ) + } + else -> + scope.launch { + _events.emit( + WalletConnectEvents.SessionRequest( + request = request, + chainId = sessionRequest.chainId, + topic = sessionRequest.topic, + id = sessionRequest.request.id, + metaUrl = sessionRequest.peerMetaData?.url ?: "", + metaName = sessionRequest.peerMetaData?.name ?: "", + ), + ) + } } } - override fun onAuthRequest(authRequest: Wallet.Model.AuthRequest) { + override fun onAuthRequest( + authRequest: Wallet.Model.AuthRequest, + verifyContext: Wallet.Model.VerifyContext, + ) { // Triggered when Dapp / Requester makes an authorization request + Timber.d("onAuthRequest: $authRequest") } override fun onSessionDelete(sessionDelete: Wallet.Model.SessionDelete) { @@ -174,6 +197,7 @@ class WalletConnectRepositoryImpl @Inject constructor( override fun onError(error: Wallet.Model.Error) { // Triggered whenever there is an issue inside the SDK + Timber.d("onError: $error") } } } diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcJrpcMethods.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcJrpcMethods.kt index 86ae71084c..9a0da6c971 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcJrpcMethods.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcJrpcMethods.kt @@ -1,9 +1,6 @@ package com.tangem.tap.domain.walletconnect2.domain -import com.squareup.moshi.JsonAdapter -import com.squareup.moshi.JsonClass -import com.squareup.moshi.Moshi -import com.squareup.moshi.Types +import com.squareup.moshi.* import com.tangem.datasource.di.SdkMoshi import com.tangem.tap.domain.walletconnect2.domain.models.binance.WCBinanceTxConfirmParam import com.tangem.tap.domain.walletconnect2.domain.models.binance.WcBinanceCancelOrder @@ -24,6 +21,7 @@ enum class WcJrpcMethods(val code: String) { BNB_SIGN("bnb_sign"), BNB_TRANSACTION_CONFIRM("bnb_tx_confirmation"), SIGN_TRANSACTION("trust_signTransaction"), + WALLET_ADD_ETHEREUM_CHAIN("wallet_addEthereumChain"), ; companion object { @@ -33,13 +31,25 @@ enum class WcJrpcMethods(val code: String) { @JsonClass(generateAdapter = true) data class WCSignTransaction( + @Json(name = "network") val network: Int, + + @Json(name = "transaction") val transaction: String, ) : WcRequestData +@JsonClass(generateAdapter = true) +data class WcAddChain( + @Json(name = "chainId") + val chainId: String, +) : WcRequestData + @JsonClass(generateAdapter = true) data class WcEthereumSignMessage( + @Json(name = "raw") val raw: List, + + @Json(name = "type") val type: WCSignType, ) : WcRequestData { enum class WCSignType { @@ -71,15 +81,34 @@ data class WcEthereumSignMessage( @JsonClass(generateAdapter = true) data class WcEthereumTransaction( + @Json(name = "from") val from: String, + + @Json(name = "to") val to: String?, + + @Json(name = "nonce") val nonce: String?, + + @Json(name = "gasPrice") val gasPrice: String?, + + @Json(name = "maxFeePerGas") val maxFeePerGas: String?, + + @Json(name = "maxPriorityFeePerGas") val maxPriorityFeePerGas: String?, + + @Json(name = "gas") val gas: String?, + + @Json(name = "gasLimit") val gasLimit: String?, + + @Json(name = "value") val value: String?, + + @Json(name = "data") val data: String, ) : WcRequestData @@ -96,6 +125,7 @@ sealed class WcRequest(open val data: WcRequestData) { data class BnbTransfer(override val data: WcBinanceTransferOrder) : WcRequest(data) data class BnbTxConfirm(override val data: WCBinanceTxConfirmParam) : WcRequest(data) data class SignTransaction(override val data: WCSignTransaction) : WcRequest(data) + data class AddChain(override val data: WcAddChain) : WcRequest(data) data class CustomRequest(override val data: WcCustomRequestData) : WcRequest(data) } @@ -167,6 +197,12 @@ class WcJrpcRequestsDeserializer @Inject constructor(@SdkMoshi private val moshi ).fromJsonFirstOrNull(params) ?: return customRequest WcRequest.SignTransaction(data = deserializedParams) } + WcJrpcMethods.WALLET_ADD_ETHEREUM_CHAIN -> { + val deserializedParams: WcAddChain = moshi.adapter>( + Types.newParameterizedType(List::class.java, WcAddChain::class.java), + ).fromJsonFirstOrNull(params) ?: return customRequest + WcRequest.AddChain(data = deserializedParams) + } } } diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 8366dd472c..f2b0e53a58 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -73,8 +73,8 @@ mviCore = "1.3.1" kotlinSerialization = "1.4.1" arrow = "1.2.0-RC" reactiveNetwork = "3.0.8" -walletConnectCore = "1.17.0" -walletConnectWeb3 = "1.10.0" +walletConnectCore = "1.18.0" +walletConnectWeb3 = "1.11.0" # endregion Other libraries # region Tangem From ebe5d28c3f2db4b89aec59a3b524e8612a19b486 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 14 Jul 2023 10:13:13 +0300 Subject: [PATCH 08/36] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt | 4 +--- .../feature/learn2earn/domain/DefaultLearn2earnInteractor.kt | 2 +- .../learn2earn/domain/api/Learn2earnDependencyProvider.kt | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt b/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt index 371f1e21bf..157be09a4a 100644 --- a/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt +++ b/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt @@ -56,9 +56,7 @@ class ProxyModule { @Singleton fun provideLear2earnDependencies(appStateHolder: AppStateHolder): Learn2earnDependencyProvider { return object : Learn2earnDependencyProvider { - override fun getUserCountryCodeProvider(): () -> String = { - appStateHolder.mainStore?.state?.globalState?.userCountryCode ?: Locale.current.language - } + override fun getLocaleProvider(): () -> String = { Locale.current.language } override fun getWebViewAuthCredentialsProvider(): () -> String? = { appStateHolder.mainStore?.state?.globalState?.configManager?.config?.tangemComAuthorization diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt index 402f88ee82..a4b7493e39 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt @@ -34,7 +34,7 @@ internal class DefaultLearn2earnInteractor( private val webViewUriBuilder: WebViewUriBuilder by lazy { WebViewUriBuilder( authCredentialsProvider = dependencyProvider.getWebViewAuthCredentialsProvider(), - userCountryCodeProvider = dependencyProvider.getUserCountryCodeProvider(), + userCountryCodeProvider = dependencyProvider.getLocaleProvider(), promoCodeProvider = { repository.getUserData().promoCode }, ) } diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt index b0261884ec..3c4178d472 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt @@ -7,7 +7,7 @@ package com.tangem.feature.learn2earn.domain.api */ interface Learn2earnDependencyProvider { - fun getUserCountryCodeProvider(): () -> String + fun getLocaleProvider(): () -> String fun getWebViewAuthCredentialsProvider(): () -> String? } \ No newline at end of file From c1d0f97f0b5c995ba81682821ec9c70e69e2b8b8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 14 Jul 2023 12:25:12 +0300 Subject: [PATCH 09/36] Updated on 2026-08-14 --- .../implementation/BiometricUserWalletsListManager.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt index 18ec89cb9c..f28f3b06ee 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt @@ -100,7 +100,7 @@ internal class BiometricUserWalletsListManager( } else { val isWalletSaved = state.value.userWallets .any { - it.walletId == userWallet.walletId || it.cardsInWallet.contains(userWallet.cardId) + it.walletId == userWallet.walletId } if (isWalletSaved) { From 4880781ad2290adcb027a6f09431e3d3e55b6b85 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 14 Jul 2023 14:58:18 +0300 Subject: [PATCH 10/36] Updated on 2026-08-14 --- .../main/java/com/tangem/domain/common/extensions/Blockchain.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt index 15fb408bde..9bd2291a93 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt @@ -185,4 +185,6 @@ fun Blockchain.isSupportedInApp(): Boolean { private val excludedBlockchains = listOf( Blockchain.Unknown, Blockchain.Ducatus, + Blockchain.Telos, // disable in 4.9 + Blockchain.TelosTestnet, // disable in 4.9 ) \ No newline at end of file From a7d324ef9860c25028f9be431254a2205e7642a1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 14 Jul 2023 15:08:50 +0300 Subject: [PATCH 11/36] Updated on 2026-08-14 --- .../src/main/assets/configs/feature_toggles_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json index b5005743ed..7acffe7244 100644 --- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json @@ -17,7 +17,7 @@ }, { "name": "1INCH_LEARN_2_EARN_ENABLED", - "version": "4.9.0" + "version": "4.10.0" }, { "name": "REDESIGNED_TOKEN_DETAIL_SCREEN_ENABLED", From 6bb82257c242c244f232c12d96be2f727eb8bc39 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Jul 2023 17:33:27 +0300 Subject: [PATCH 12/36] Updated on 2026-08-14 --- .../presentation/Learn2earnViewModel.kt | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt index 8c3cbfb221..e32041e0c2 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt @@ -72,14 +72,17 @@ class Learn2earnViewModel @Inject constructor( } private fun onButtonMainClick() { - if (!interactor.isUserHadPromoCode() && !interactor.isUserRegisteredInPromotion()) { + if (interactor.isUserHadPromoCode() || interactor.isUserRegisteredInPromotion()) { + analytics.send(Learn2earnEvents.MainScreen.NoticeLear2earn(AnalyticsParam.ClientType.Old())) + requestAward() + } else { analytics.send(Learn2earnEvents.MainScreen.NoticeLear2earn(AnalyticsParam.ClientType.New())) subscribeToWebViewResultEvents() router.openWebView(interactor.buildUriForOldUser(), interactor.getBasicAuthHeaders()) - return } + } - analytics.send(Learn2earnEvents.MainScreen.NoticeLear2earn(AnalyticsParam.ClientType.Old())) + private fun requestAward() { viewModelScope.launch(dispatchers.io) { updateUi { uiState.updateProgress(showProgress = true) } @@ -171,9 +174,16 @@ class Learn2earnViewModel @Inject constructor( private fun subscribeToWebViewResultEvents() { interactor.webViewResultHandler = object : WebViewResultHandler { override fun handleResult(result: WebViewResult) { - interactor.webViewResultHandler = null - if (result is WebViewResult.ReadyForAward) { - updateMainScreenViews() + when (result) { + is WebViewResult.PromoCode -> { + interactor.webViewResultHandler = null + } + WebViewResult.ReadyForAward -> { + interactor.webViewResultHandler = null + updateMainScreenViews() + requestAward() + } + WebViewResult.Empty, is WebViewResult.Learn2earnAnalyticsEvent -> Unit } } } From 05e9c45b7c08df74924d6cad7fe85a161fc5e7cd Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Jul 2023 16:49:24 +0300 Subject: [PATCH 13/36] Updated on 2026-08-14 --- .../tangem/feature/learn2earn/presentation/ui/GetBonusView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/GetBonusView.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/GetBonusView.kt index 5c4aff6b96..a36d44f760 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/GetBonusView.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/GetBonusView.kt @@ -77,7 +77,7 @@ internal fun GetBonusView(state: MainScreenState, modifier: Modifier = Modifier) Text( text = state.description.subtitle.resolveReference(), style = TangemTypography.caption, - color = TangemTheme.colors.text.secondary, + color = TangemTheme.colors.text.tertiary, ) } } From e5f2121aeab5472dead4898bebe31f2df4a77b4c Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Jul 2023 16:35:06 +0300 Subject: [PATCH 14/36] Updated on 2026-08-14 --- .../feature/learn2earn/domain/DefaultLearn2earnInteractor.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt index a4b7493e39..28842e8e24 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt @@ -289,9 +289,9 @@ internal class DefaultLearn2earnInteractor( private fun Promotion.PromotionInfo.getData(promoCode: String?): PromotionInfoResponse.Data { return if (promoCode == null) { - newCard - } else { oldCard + } else { + newCard } } From f7a4e4ddbbf59054825254216164d61cc367b8ea Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Jul 2023 19:37:30 +0400 Subject: [PATCH 15/36] Updated on 2026-08-14 --- .../walletconnect2/domain/WalletConnectInteractor.kt | 8 ++++++++ .../redux/walletconnect/WalletConnectMiddleware.kt | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt index 5bd6d8f0a1..e37d7c2949 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WalletConnectInteractor.kt @@ -227,7 +227,15 @@ class WalletConnectInteractor( } } + fun isWalletConnectUri(uri: String): Boolean { + return uri.lowercase().startsWith(WC_SCHEME) + } + private suspend fun prepareRequestData(sessionRequest: WalletConnectEvents.SessionRequest): WcPreparedRequest? { return sessionRequestConverter.prepareRequest(sessionRequest, userWalletId) } + + companion object { + private const val WC_SCHEME = "wc" + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt index 802ad1b140..b3b5057a76 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt @@ -70,7 +70,7 @@ class WalletConnectMiddleware { } is WalletConnectAction.StartWalletConnect -> { val uri = action.copiedUri - if (uri != null && WalletConnectManager.isCorrectWcUri(uri)) { + if (uri != null && isWalletConnectUri(uri)) { store.dispatchOnMain(WalletConnectAction.ShowClipboardOrScanQrDialog(uri)) } else { store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.QrScan)) @@ -442,4 +442,8 @@ class WalletConnectMiddleware { ) return walletState.getWalletManager(blockchainNetwork) } + + private fun isWalletConnectUri(uri: String): Boolean { + return WalletConnectManager.isCorrectWcUri(uri) || walletConnectInteractor.isWalletConnectUri(uri) + } } \ No newline at end of file From 4b2711380634e5d0c46799c4b1ae4eb42281bda1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Jul 2023 14:14:46 +0300 Subject: [PATCH 16/36] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/MainActivity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 2eb8371482..186fe79feb 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -283,9 +283,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac store.dispatchOnMain(WelcomeAction.SetInitialIntent(intentWhichStartedActivity)) scope.launch { val handler = BackgroundScanIntentHandler(hasSavedUserWalletsProvider = { true }) - val isBackgroundScanNotHandled = handler.handleIntent(intentWhichStartedActivity) + val isBackgroundScanHandled = handler.handleIntent(intentWhichStartedActivity) val hasNotIncompletedBackup = !backupService.hasIncompletedBackup - if (isBackgroundScanNotHandled && hasNotIncompletedBackup) { + if (!isBackgroundScanHandled && hasNotIncompletedBackup) { store.dispatchOnMain(WelcomeAction.ProceedWithBiometrics) } } From 02735926061a44752865b5ecd22ddc129c9a8ef7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Jul 2023 16:47:29 +0300 Subject: [PATCH 17/36] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- .../tap/common/shop/TangemShopService.kt | 20 ++++++++++--------- .../common/shop/googlepay/GooglePayService.kt | 9 +++------ .../datasource/config/models/ShopifyShop.kt | 4 +++- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index fad890b2a0..b791bd4cf6 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit fad890b2a0b552be60d124949ca0a3a4d672dac1 +Subproject commit b791bd4cf6c5eca9778f89e87cd62b72d24f5ce9 diff --git a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt index 335228e10f..3032ef611a 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt @@ -18,7 +18,8 @@ import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope import java.math.BigDecimal -import java.util.* +import java.util.Currency +import java.util.UUID class TangemShopService(application: Application, shopifyShop: ShopifyShop) { @@ -82,16 +83,18 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { suspend fun checkIfGooglePayAvailable(googlePayService: GooglePayService): Result { this.googlePayService = googlePayService - return googlePayService.checkIfGooglePayAvailable() + return googlePayService.checkIfGooglePayAvailable(shopifyService.shop.merchantID != null) } fun buyWithGooglePay(productType: ProductType) { - val totalPrice = checkouts[productType]!!.totalPriceV2.amount - googlePayService.payWithGooglePay( - totalPriceCents = totalPrice, - currencyCode = checkouts[productType]!!.currencyCode.name, - merchantID = shopifyService.shop.merchantID, - ) + shopifyService.shop.merchantID?.let { merchantId -> + val totalPrice = checkouts[productType]!!.totalPriceV2.amount + googlePayService.payWithGooglePay( + totalPriceCents = totalPrice, + currencyCode = checkouts[productType]!!.currencyCode.name, + merchantID = merchantId, + ) + } } // fun subscribeToGooglePayResult( @@ -185,7 +188,6 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { ), appliedDiscount = it.getAppliedDiscount(), ), - ) } return Result.failure(result.exceptionOrNull()!!) diff --git a/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayService.kt b/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayService.kt index 757b207741..7526224414 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayService.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayService.kt @@ -6,11 +6,7 @@ import android.app.Activity.RESULT_OK import android.content.Intent import android.util.Log import com.google.android.gms.common.api.ApiException -import com.google.android.gms.wallet.AutoResolveHelper -import com.google.android.gms.wallet.IsReadyToPayRequest -import com.google.android.gms.wallet.PaymentData -import com.google.android.gms.wallet.PaymentDataRequest -import com.google.android.gms.wallet.PaymentsClient +import com.google.android.gms.wallet.* import com.tangem.common.core.TangemSdkError import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -24,7 +20,8 @@ class GooglePayService(private val paymentsClient: PaymentsClient, private val a // var responseCallback: ((Result) -> Unit)? = null - suspend fun checkIfGooglePayAvailable(): Result { + suspend fun checkIfGooglePayAvailable(isMerchantAvailable: Boolean): Result { + if (!isMerchantAvailable) return Result.success(false) val isReadyToPayJson = GooglePayUtil.isReadyToPayRequest() ?: return Result.success(false) val request = IsReadyToPayRequest.fromJson(isReadyToPayJson.toString()) diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/ShopifyShop.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/ShopifyShop.kt index cdda42d58c..c4a09adcfe 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/models/ShopifyShop.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/ShopifyShop.kt @@ -5,8 +5,10 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class ShopifyShop( + @Json(name = "domain") val domain: String, @Json(name = "storefrontApiKeyAndroid") val storefrontApiKey: String, - val merchantID: String, + @Json(name = "merchantID") + val merchantID: String?, ) \ No newline at end of file From 3ac090126342110a3f9c7d2f9c4ef273f755dd4d Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Jul 2023 17:10:17 +0300 Subject: [PATCH 18/36] 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 f2b0e53a58..cb8ecb3892 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -78,7 +78,7 @@ walletConnectWeb3 = "1.11.0" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_4.9-282" +tangemBlockchainSdk = "release-app_4.9-286" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_4.9-274" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds From 03e155d1a5e07c76d88d99eec0ecb75dc5a6075e Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Jul 2023 20:04:58 +0300 Subject: [PATCH 19/36] Updated on 2026-08-14 --- .../domain/DefaultLearn2earnInteractor.kt | 41 +++++++--------- .../domain/api/Learn2earnInteractor.kt | 5 +- .../presentation/Learn2earnViewModel.kt | 48 ++++++++++++++++--- .../presentation/ui/state/StateBuilder.kt | 5 ++ 4 files changed, 66 insertions(+), 33 deletions(-) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt index 28842e8e24..4fecdc2d67 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt @@ -2,7 +2,6 @@ package com.tangem.feature.learn2earn.domain import android.net.Uri import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.datasource.api.promotion.models.AbstractPromotionResponse import com.tangem.datasource.api.promotion.models.PromotionInfoResponse import com.tangem.feature.learn2earn.data.api.Learn2earnRepository import com.tangem.feature.learn2earn.data.models.PromoUserData @@ -51,25 +50,18 @@ internal class DefaultLearn2earnInteractor( return repository.getUserData().promoCode != null } - override fun isNeedToShowViewOnStoriesScreen(): Boolean { - return promotionIsActive() - } - - override suspend fun isNeedToShowViewOnMainScreen(): Boolean { - if (!promotionIsActive()) return false - + override suspend fun validateUserWallet(): PromotionError? { val promoCode = repository.getUserData().promoCode val userWalletId = userWalletManager.getWalletId() - return if (promoCode == null) { - val response = repository.validate(userWalletId) - response.valid == true + + val domainError = if (promoCode == null) { + repository.validate(userWalletId).error } else { - val response = repository.validateCode(userWalletId, promoCode) - when (val error = response.error?.toDomainError()) { - null -> response.valid == true - else -> error !is PromotionError.CodeWasNotAppliedInShop - } - } + repository.validateCode(userWalletId, promoCode).error + }?.toDomainError() + + return domainError + ?.also { handlePromotionError(it) } } override fun isUserRegisteredInPromotion(): Boolean { @@ -96,22 +88,21 @@ internal class DefaultLearn2earnInteractor( val walletId = userWalletManager.getWalletId() val promoCode = repository.getUserData().promoCode - val error = if (promoCode == null) { + val domainError = if (promoCode == null) { requestAward(walletId, awardCurrency) } else { requestAwardWithPromoCode(walletId, awardCurrency, promoCode) } - return if (error == null) { + return if (domainError == null) { Result.success(Unit) } else { - val domainError = error.toDomainError() handlePromotionError(domainError) Result.failure(domainError) } } - private suspend fun requestAward(walletId: String, awardCurrency: Currency): AbstractPromotionResponse.Error? { + private suspend fun requestAward(walletId: String, awardCurrency: Currency): PromotionError? { val validateResponse = repository.validate(walletId) return if (validateResponse.valid == true) { val address = getWalletAddressForAward(awardCurrency) @@ -124,14 +115,14 @@ internal class DefaultLearn2earnInteractor( } } else { validateResponse.error - } + }?.toDomainError() } private suspend fun requestAwardWithPromoCode( walletId: String, awardCurrency: Currency, promoCode: String, - ): AbstractPromotionResponse.Error? { + ): PromotionError? { val codeValidateResponse = repository.validateCode(walletId, promoCode) return if (codeValidateResponse.valid == true) { val address = getWalletAddressForAward(awardCurrency) @@ -144,7 +135,7 @@ internal class DefaultLearn2earnInteractor( } } else { codeValidateResponse.error - } + }?.toDomainError() } private suspend fun getWalletAddressForAward(currency: Currency): String { @@ -215,7 +206,7 @@ internal class DefaultLearn2earnInteractor( return result.toWebViewAction() } - private fun promotionIsActive(): Boolean { + override fun isPromotionActive(): Boolean { val userData = repository.getUserData() val isActive = when { !featureToggleManager.isLearn2earnEnabled -> false diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt index 95bb9d7ad9..d004288477 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt @@ -1,6 +1,7 @@ package com.tangem.feature.learn2earn.domain.api import android.net.Uri +import com.tangem.feature.learn2earn.domain.models.PromotionError /** [REDACTED_AUTHOR] @@ -13,9 +14,9 @@ interface Learn2earnInteractor : WebViewRedirectHandler { fun isUserHadPromoCode(): Boolean - fun isNeedToShowViewOnStoriesScreen(): Boolean + fun isPromotionActive(): Boolean - suspend fun isNeedToShowViewOnMainScreen(): Boolean + suspend fun validateUserWallet(): PromotionError? fun isUserRegisteredInPromotion(): Boolean diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt index e32041e0c2..ff443d1b04 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt @@ -42,7 +42,7 @@ class Learn2earnViewModel @Inject constructor( private set init { - uiState = uiState.updateStoriesVisibility(interactor.isNeedToShowViewOnStoriesScreen()) + uiState = uiState.updateViewsVisibility(isVisible = interactor.isPromotionActive()) } fun onMainScreenCreated() { @@ -54,15 +54,51 @@ class Learn2earnViewModel @Inject constructor( } private fun updateMainScreenViews() { + if (!interactor.isPromotionActive()) { + uiState = uiState.updateViewsVisibility(isVisible = false) + return + } + viewModelScope.launch(dispatchers.io) { - if (interactor.isNeedToShowViewOnMainScreen()) { - updateUi { - uiState.changeGetBounsDescription(getBonusDescription()) - .updateGetBonusVisibility(isVisible = true) + val error = interactor.validateUserWallet() + when { + error == null -> { + updateUi { uiState.updateViewsVisibility(isVisible = true) } } - } else { + // additional check after the error has been handled by interactor + !interactor.isPromotionActive() -> { + updateUi { uiState.updateViewsVisibility(isVisible = false) } + } + else -> { + updateViewsVisibilityOnError(error) + } + } + } + } + + private suspend fun updateViewsVisibilityOnError(error: PromotionError) { + when (error) { + is PromotionError.ProgramNotFound, + is PromotionError.ProgramWasEnd, + is PromotionError.CodeWasAlreadyUsed, + is PromotionError.WalletAlreadyHasAward, + is PromotionError.CardAlreadyHasAward, + -> { + updateUi { uiState.updateViewsVisibility(isVisible = false) } + } + is PromotionError.CodeWasNotAppliedInShop -> { updateUi { uiState.updateGetBonusVisibility(isVisible = false) } } + is PromotionError.CodeNotFound, + -> { + updateUi { + uiState.updateViewsVisibility(isVisible = true) + .changeGetBounsDescription(getBonusDescription()) + } + } + is PromotionError.UnknownError, + PromotionError.NetworkUnreachable, + -> Unit } } diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt index 90e41829ab..c97472b8b5 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt @@ -43,6 +43,11 @@ internal fun Learn2earnState.updateGetBonusVisibility(isVisible: Boolean): Learn } } +internal fun Learn2earnState.updateViewsVisibility(isVisible: Boolean): Learn2earnState { + return updateStoriesVisibility(isVisible) + .updateGetBonusVisibility(isVisible) +} + internal fun Learn2earnState.changeGetBounsDescription(description: MainScreenState.Description): Learn2earnState { return if (mainScreenState.description == description) { this From 22141e15d8eba9ab4fab241f4c6af5033ef88e53 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Jul 2023 18:06:59 +0300 Subject: [PATCH 20/36] Updated on 2026-08-14 --- features/learn2earn/impl/build.gradle.kts | 1 + .../webView/Learn2earnWebViewActivity.kt | 87 ++++++++++--------- .../webView/Learn2earnWebViewClient.kt | 4 +- .../src/main/res/layout/activity_web_view.xml | 38 -------- 4 files changed, 47 insertions(+), 83 deletions(-) delete mode 100644 features/learn2earn/impl/src/main/res/layout/activity_web_view.xml diff --git a/features/learn2earn/impl/build.gradle.kts b/features/learn2earn/impl/build.gradle.kts index 26d0179187..52671d615a 100644 --- a/features/learn2earn/impl/build.gradle.kts +++ b/features/learn2earn/impl/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { implementation(deps.compose.foundation) implementation(deps.compose.ui) implementation(deps.compose.ui.tooling) + implementation(deps.compose.accompanist.webView) /** Preferences */ implementation(deps.krateSharedPref) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt index 7300fcdb06..f88f31dd0d 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt @@ -1,12 +1,19 @@ package com.tangem.feature.learn2earn.presentation.webView import android.os.Bundle -import android.view.MenuItem -import android.webkit.WebView +import androidx.activity.compose.BackHandler +import androidx.activity.compose.setContent import androidx.activity.viewModels -import androidx.appcompat.app.ActionBar import androidx.appcompat.app.AppCompatActivity -import com.tangem.feature.learn2earn.impl.R +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import com.google.accompanist.web.WebView +import com.google.accompanist.web.rememberWebViewState +import com.tangem.core.ui.components.appbar.AppBarWithBackButton +import com.tangem.core.ui.res.TangemTheme import dagger.hilt.android.AndroidEntryPoint /** @@ -17,53 +24,47 @@ class Learn2earnWebViewActivity : AppCompatActivity() { private val viewModel by viewModels() - private lateinit var actionBar: ActionBar - private lateinit var webView: WebView - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_web_view) - val webViewData = viewModel.extractData(intent) - setSupportActionBar(findViewById(R.id.toolbar)) - actionBar = supportActionBar!! - actionBar.setDisplayHomeAsUpEnabled(true) - actionBar.setDisplayShowHomeEnabled(true) - actionBar.title = webViewData.uri.authority - webView = findViewById(R.id.web_view) - - webView.settings.javaScriptEnabled = true - webView.settings.domStorageEnabled = true - webView.settings.loadsImagesAutomatically = true - - webView.webViewClient = Learn2earnWebViewClient( - redirectHandler = viewModel, - headers = webViewData.headers, - finishSessionHandler = { finish() }, - ) - webView.loadUrl( - webViewData.uri.toString(), - webViewData.headers, - ) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { - android.R.id.home -> { - finish() - true + setContent { + TangemTheme { + BackHandler(onBack = { finish() }) + ScreenContent(webViewData) } - else -> super.onOptionsItemSelected(item) } } - override fun onDestroy() { - webView.clearHistory() - webView.clearCache(true) - webView.destroy() - - super.onDestroy() + @Composable + private fun ScreenContent(webViewData: WebViewData) { + Column { + AppBarWithBackButton( + modifier = Modifier.background(TangemTheme.colors.background.secondary), + text = webViewData.uri.authority, + onBackClick = { finish() }, + ) + WebView( + state = rememberWebViewState( + url = webViewData.uri.toString(), + additionalHttpHeaders = webViewData.headers + ), + onCreated = { + it.settings.apply { + javaScriptEnabled = true + domStorageEnabled = true + loadsImagesAutomatically = true + } + }, + client = remember { + Learn2earnWebViewClient( + redirectHandler = viewModel, + headers = webViewData.headers, + finishSessionHandler = { finish() }, + ) + }, + ) + } } companion object { diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt index 7a96dbc90b..575b074b03 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt @@ -2,7 +2,7 @@ package com.tangem.feature.learn2earn.presentation.webView import android.webkit.WebResourceRequest import android.webkit.WebView -import android.webkit.WebViewClient +import com.google.accompanist.web.AccompanistWebViewClient import com.tangem.feature.learn2earn.domain.api.WebViewAction import com.tangem.feature.learn2earn.domain.api.WebViewRedirectHandler import timber.log.Timber @@ -11,7 +11,7 @@ internal class Learn2earnWebViewClient( private val redirectHandler: WebViewRedirectHandler, private val headers: Map, private val finishSessionHandler: () -> Unit, -) : WebViewClient() { +) : AccompanistWebViewClient() { override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean { Timber.d("url: ${request.url}") diff --git a/features/learn2earn/impl/src/main/res/layout/activity_web_view.xml b/features/learn2earn/impl/src/main/res/layout/activity_web_view.xml deleted file mode 100644 index 8737917c56..0000000000 --- a/features/learn2earn/impl/src/main/res/layout/activity_web_view.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file From c4f743745cd4989b3c5476210d11e1101fa6bb28 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Jul 2023 12:08:59 +0300 Subject: [PATCH 21/36] Updated on 2026-08-14 --- .../domain/DefaultLearn2earnInteractor.kt | 2 +- .../learn2earn/domain/WebViewUriBuilder.kt | 17 +++++++++++++++-- .../presentation/Learn2earnViewModel.kt | 6 ++++-- .../presentation/ui/Learn2earnDialogs.kt | 3 ++- .../presentation/ui/state/Learn2earnState.kt | 3 +-- .../webView/Learn2earnWebViewActivity.kt | 3 ++- 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt index 4fecdc2d67..924c7f2e1a 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt @@ -33,7 +33,7 @@ internal class DefaultLearn2earnInteractor( private val webViewUriBuilder: WebViewUriBuilder by lazy { WebViewUriBuilder( authCredentialsProvider = dependencyProvider.getWebViewAuthCredentialsProvider(), - userCountryCodeProvider = dependencyProvider.getLocaleProvider(), + localeLanguageProvider = dependencyProvider.getLocaleProvider(), promoCodeProvider = { repository.getUserData().promoCode }, ) } diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriBuilder.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriBuilder.kt index 0b2f6f6450..89ac185bcd 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriBuilder.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriBuilder.kt @@ -8,7 +8,7 @@ import com.tangem.feature.learn2earn.impl.BuildConfig */ internal class WebViewUriBuilder( private val authCredentialsProvider: () -> String?, - private val userCountryCodeProvider: () -> String, + private val localeLanguageProvider: () -> String, private val promoCodeProvider: () -> String?, ) { @@ -46,10 +46,19 @@ internal class WebViewUriBuilder( } else { authority(BASE_URL) } - appendPath(userCountryCodeProvider.invoke()) + appendPath(getLocaleLanguage(localeLanguageProvider.invoke())) appendPath(PATH_PROMOTION) } + // TODO: locale: This can be used by another feature. Move it to the appropriate location + private fun getLocaleLanguage(language: String): String { + return if (LOCALE_LANG_RU.equals(language, true) || LOCALE_LANG_BY.equals(language, true)) { + LOCALE_LANG_RU + } else { + LOCALE_LANG_EN + } + } + private companion object { const val SCHEME = "https" @@ -60,5 +69,9 @@ internal class WebViewUriBuilder( const val QUERY_EXISTED_CARD = "existed-card" const val DEV_BASE_URL = "devweb.tangem.com" + + const val LOCALE_LANG_RU = "ru" + const val LOCALE_LANG_BY = "by" + const val LOCALE_LANG_EN = "en" } } \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt index ff443d1b04..a37a6a3427 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt @@ -6,12 +6,14 @@ import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.ui.extensions.TextReference import com.tangem.feature.learn2earn.analytics.AnalyticsParam import com.tangem.feature.learn2earn.analytics.Learn2earnEvents import com.tangem.feature.learn2earn.domain.api.Learn2earnInteractor import com.tangem.feature.learn2earn.domain.api.WebViewResult import com.tangem.feature.learn2earn.domain.api.WebViewResultHandler import com.tangem.feature.learn2earn.domain.models.PromotionError +import com.tangem.feature.learn2earn.impl.R import com.tangem.feature.learn2earn.presentation.ui.state.* import com.tangem.lib.crypto.models.errors.UserCancelledException import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider @@ -191,7 +193,7 @@ class Learn2earnViewModel @Inject constructor( .updateGetBonusVisibility(isVisible = false) } MainScreenState.Dialog.Error( - error = error, + textReference = TextReference.Str(error.description), onOk = onHideDialog, onDismissRequest = onHideDialog, ) @@ -199,7 +201,7 @@ class Learn2earnViewModel @Inject constructor( is PromotionError.UnknownError, PromotionError.NetworkUnreachable -> { val onHideDialog = { uiState = uiState.hideDialog() } MainScreenState.Dialog.Error( - error = error, + textReference = TextReference.Res(R.string.common_server_unavailable), onOk = onHideDialog, onDismissRequest = onHideDialog, ) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnDialogs.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnDialogs.kt index 9a21f29231..3c855863ac 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnDialogs.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/Learn2earnDialogs.kt @@ -5,6 +5,7 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import com.tangem.core.ui.components.TextButton +import com.tangem.core.ui.extensions.resolveReference import com.tangem.feature.learn2earn.impl.R import com.tangem.feature.learn2earn.presentation.ui.state.MainScreenState @@ -72,7 +73,7 @@ private fun ErrorDialog(dialog: MainScreenState.Dialog.Error) { Text(text = stringResource(id = R.string.common_error)) }, text = { - Text(text = dialog.error.description) + Text(text = dialog.textReference.resolveReference()) }, confirmButton = { TextButton( diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/Learn2earnState.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/Learn2earnState.kt index 4ba08f14bb..4e0e2054cd 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/Learn2earnState.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/Learn2earnState.kt @@ -2,7 +2,6 @@ package com.tangem.feature.learn2earn.presentation.ui.state import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.WrappedList -import com.tangem.feature.learn2earn.domain.models.PromotionError import com.tangem.feature.learn2earn.impl.R /** @@ -62,7 +61,7 @@ data class MainScreenState( ) : Dialog() data class Error( - val error: PromotionError, + val textReference: TextReference, val onOk: () -> Unit, val onDismissRequest: () -> Unit, ) : Dialog() diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt index f88f31dd0d..40e8a9e775 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt @@ -36,6 +36,7 @@ class Learn2earnWebViewActivity : AppCompatActivity() { } } + @Suppress("TopLevelComposableFunctions") @Composable private fun ScreenContent(webViewData: WebViewData) { Column { @@ -47,7 +48,7 @@ class Learn2earnWebViewActivity : AppCompatActivity() { WebView( state = rememberWebViewState( url = webViewData.uri.toString(), - additionalHttpHeaders = webViewData.headers + additionalHttpHeaders = webViewData.headers, ), onCreated = { it.settings.apply { From 7daafed11b766a6fcb9c005eacfd1ebb41759d23 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Jul 2023 12:16:52 +0300 Subject: [PATCH 22/36] Updated on 2026-08-14 --- core/res/src/main/res/values-ru/strings.xml | 2 +- .../domain/DefaultLearn2earnInteractor.kt | 19 ++++++++++++------- .../domain/api/Learn2earnInteractor.kt | 4 ++++ .../presentation/Learn2earnViewModel.kt | 15 +++++++++++---- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 797b9dea53..ded2d07b72 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -165,7 +165,7 @@ Пройдите 3 урока и получите %d 1INCH токен на свой кошелек Пройдите 3 урока и получите %d 1INCH токена на свой кошелек - Пройдите 3 урока и получите %d 1INCH токена на свой кошелек + Пройдите 3 урока и получите %d 1INCH токенов на свой кошелек Пройдите 3 урока и получите %d 1INCH токенов на свой кошелек Управление токенами diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt index 924c7f2e1a..6b3f438e02 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt @@ -207,20 +207,25 @@ internal class DefaultLearn2earnInteractor( } override fun isPromotionActive(): Boolean { - val userData = repository.getUserData() val isActive = when { !featureToggleManager.isLearn2earnEnabled -> false - userData.isAlreadyReceivedAward -> false - promotion.isError() -> false - else -> { - val data = promotion.getPromotionInfo().getData(userData.promoCode) - data.status == PromotionInfoResponse.Status.ACTIVE - } + repository.getUserData().isAlreadyReceivedAward -> false + else -> !promotion.isError() } return isActive } + override fun isPromotionActiveOnStories(): Boolean { + val isActiveStatus = promotion.getPromotionInfo().newCard.status == PromotionInfoResponse.Status.ACTIVE + return isPromotionActive() && isActiveStatus + } + + override fun isPromotionActiveOnMain(): Boolean { + val isActiveStatus = promotion.getPromotionInfo().oldCard.status == PromotionInfoResponse.Status.ACTIVE + return isPromotionActive() && isActiveStatus + } + private suspend fun initPromotionInfo() { promotion = if (featureToggleManager.isLearn2earnEnabled) { repository.getPromotionInfo() diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt index d004288477..8498c9483e 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt @@ -16,6 +16,10 @@ interface Learn2earnInteractor : WebViewRedirectHandler { fun isPromotionActive(): Boolean + fun isPromotionActiveOnStories(): Boolean + + fun isPromotionActiveOnMain(): Boolean + suspend fun validateUserWallet(): PromotionError? fun isUserRegisteredInPromotion(): Boolean diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt index a37a6a3427..18613b0f54 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt @@ -44,7 +44,9 @@ class Learn2earnViewModel @Inject constructor( private set init { - uiState = uiState.updateViewsVisibility(isVisible = interactor.isPromotionActive()) + uiState = uiState + .updateStoriesVisibility(isVisible = interactor.isPromotionActiveOnStories()) + .updateGetBonusVisibility(isVisible = interactor.isPromotionActiveOnMain()) } fun onMainScreenCreated() { @@ -56,8 +58,8 @@ class Learn2earnViewModel @Inject constructor( } private fun updateMainScreenViews() { - if (!interactor.isPromotionActive()) { - uiState = uiState.updateViewsVisibility(isVisible = false) + if (!interactor.isPromotionActiveOnMain()) { + uiState = uiState.updateGetBonusVisibility(isVisible = false) return } @@ -65,7 +67,12 @@ class Learn2earnViewModel @Inject constructor( val error = interactor.validateUserWallet() when { error == null -> { - updateUi { uiState.updateViewsVisibility(isVisible = true) } + updateUi { + uiState + .updateStoriesVisibility(isVisible = interactor.isPromotionActiveOnStories()) + .updateGetBonusVisibility(isVisible = interactor.isPromotionActiveOnMain()) + .changeGetBounsDescription(getBonusDescription()) + } } // additional check after the error has been handled by interactor !interactor.isPromotionActive() -> { From f6ae66e7b75786671d84f4eb4afabba90f18ba3f Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Jul 2023 15:57:36 +0300 Subject: [PATCH 23/36] Updated on 2026-08-14 --- .../com/tangem/tap/proxy/di/ProxyModule.kt | 6 ++++ core/res/src/main/res/values-ru/strings.xml | 8 ++--- core/res/src/main/res/values/strings.xml | 4 +-- features/learn2earn/impl/build.gradle.kts | 1 + .../data/DefaultLearn2earnRepository.kt | 1 + .../learn2earn/data/models/PromoUserData.kt | 1 + .../domain/DefaultLearn2earnInteractor.kt | 35 ++++++++++++++----- .../learn2earn/domain/WebViewUriBuilder.kt | 16 +++++---- .../learn2earn/domain/WebViewUriParser.kt | 27 +++++++------- .../api/Learn2earnDependencyProvider.kt | 4 +++ .../domain/api/WebViewResultHandler.kt | 8 ++++- .../domain/di/Learn2earnDomainModule.kt | 2 +- .../presentation/Learn2earnViewModel.kt | 7 ++-- 13 files changed, 82 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt b/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt index 157be09a4a..90c5bc1691 100644 --- a/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt +++ b/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt @@ -2,6 +2,8 @@ package com.tangem.tap.proxy.di import androidx.compose.ui.text.intl.Locale import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.domain.common.CardTypesResolver +import com.tangem.domain.common.util.cardTypesResolver import com.tangem.feature.learn2earn.domain.api.Learn2earnDependencyProvider import com.tangem.lib.crypto.DerivationManager import com.tangem.lib.crypto.TransactionManager @@ -56,6 +58,10 @@ class ProxyModule { @Singleton fun provideLear2earnDependencies(appStateHolder: AppStateHolder): Learn2earnDependencyProvider { return object : Learn2earnDependencyProvider { + override fun getCardTypeResolver(): CardTypesResolver? { + return appStateHolder.userWalletsListManager?.selectedUserWalletSync?.scanResponse?.cardTypesResolver + } + override fun getLocaleProvider(): () -> String = { Locale.current.language } override fun getWebViewAuthCredentialsProvider(): () -> String? = { diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index ded2d07b72..983a156305 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -163,10 +163,10 @@ Вы обновили данные биометрии, отсканируйте свою карту для входа Вы успешно прошли все уроки и теперь можете получить 1INCH токены - Пройдите 3 урока и получите %d 1INCH токен на свой кошелек - Пройдите 3 урока и получите %d 1INCH токена на свой кошелек - Пройдите 3 урока и получите %d 1INCH токенов на свой кошелек - Пройдите 3 урока и получите %d 1INCH токенов на свой кошелек + Пройдите 3 урока и получите %d 1INCH токен на свой кошелек + Пройдите 3 урока и получите %d 1INCH токена на свой кошелек + Пройдите 3 урока и получите %d 1INCH токенов на свой кошелек + Пройдите 3 урока и получите %d 1INCH токенов на свой кошелек Управление токенами Чтобы защитить свои активы, мы советуем вам выполнить эту процедуру diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index cd659ff14e..90489aa58e 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -161,8 +161,8 @@ You have updated biometrics, scan your card to enter You have completed all of the lessons, and are now eligible to receive your 1INCH tokens - Complete three lessons and receive %d 1INCH token to your wallet - Complete three lessons and receive %d 1INCH tokens to your wallet + Complete three lessons and receive %d 1INCH token to your wallet + Complete three lessons and receive %d 1INCH tokens to your wallet Manage tokens To protect your assets, we advise you to carry out this procedure diff --git a/features/learn2earn/impl/build.gradle.kts b/features/learn2earn/impl/build.gradle.kts index 52671d615a..ce9914d94f 100644 --- a/features/learn2earn/impl/build.gradle.kts +++ b/features/learn2earn/impl/build.gradle.kts @@ -10,6 +10,7 @@ plugins { dependencies { /** Core modules */ implementation(project(":common")) + implementation(project(":domain:legacy")) implementation(project(":core:analytics")) implementation(project(":core:featuretoggles")) implementation(project(":core:datasource")) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultLearn2earnRepository.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultLearn2earnRepository.kt index c10f0d57bb..0eefb517be 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultLearn2earnRepository.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/DefaultLearn2earnRepository.kt @@ -121,6 +121,7 @@ internal class DefaultLearn2earnRepository( promoCode = null, isRegisteredInPromotion = false, isAlreadyReceivedAward = false, + isLearningStageFinished = false, ) private companion object { diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/models/PromoUserData.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/models/PromoUserData.kt index 7edf1bc122..b5553c544e 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/models/PromoUserData.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/data/models/PromoUserData.kt @@ -5,6 +5,7 @@ package com.tangem.feature.learn2earn.data.models */ data class PromoUserData( val promoCode: String?, + val isLearningStageFinished: Boolean, val isRegisteredInPromotion: Boolean, val isAlreadyReceivedAward: Boolean, ) \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt index 6b3f438e02..12f37ee9f8 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt @@ -3,6 +3,8 @@ package com.tangem.feature.learn2earn.domain import android.net.Uri import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.datasource.api.promotion.models.PromotionInfoResponse +import com.tangem.feature.learn2earn.analytics.AnalyticsParam +import com.tangem.feature.learn2earn.analytics.Learn2earnEvents.* import com.tangem.feature.learn2earn.data.api.Learn2earnRepository import com.tangem.feature.learn2earn.data.models.PromoUserData import com.tangem.feature.learn2earn.data.toggles.Learn2earnFeatureToggleManager @@ -22,8 +24,8 @@ internal class DefaultLearn2earnInteractor( private val repository: Learn2earnRepository, private val userWalletManager: UserWalletManager, private val derivationManager: DerivationManager, - private val analyticsEventHandler: AnalyticsEventHandler, - dependencyProvider: Learn2earnDependencyProvider, + private val analytics: AnalyticsEventHandler, + private val dependencyProvider: Learn2earnDependencyProvider, ) : Learn2earnInteractor { override var webViewResultHandler: WebViewResultHandler? = null @@ -171,11 +173,11 @@ internal class DefaultLearn2earnInteractor( } override fun buildUriForNewUser(): Uri { - return webViewUriBuilder.buildUriForNewUser() + return webViewUriBuilder.buildUriForNewUser(repository.getUserData().isLearningStageFinished) } override fun buildUriForOldUser(): Uri { - return webViewUriBuilder.buildUriForOldUser() + return webViewUriBuilder.buildUriForOldUser(repository.getUserData().isLearningStageFinished) } override fun getBasicAuthHeaders(): ArrayList { @@ -185,11 +187,22 @@ internal class DefaultLearn2earnInteractor( override fun handleRedirect(uri: Uri): WebViewAction { val result = webViewUriParser.parse(uri) when (result) { - is WebViewResult.PromoCode -> { + is WebViewResult.NewUserLearningFinished -> { + analytics.send(PromoScreen.SuccessScreenOpened(AnalyticsParam.ClientType.New())) updateUserData { it.copy( promoCode = result.promoCode, isRegisteredInPromotion = true, + isLearningStageFinished = true, + ) + } + } + is WebViewResult.OldUserLearningFinished -> { + analytics.send(PromoScreen.SuccessScreenOpened(AnalyticsParam.ClientType.Old())) + updateUserData { + it.copy( + promoCode = null, + isLearningStageFinished = true, ) } } @@ -197,7 +210,7 @@ internal class DefaultLearn2earnInteractor( updateUserData { it.copy(isRegisteredInPromotion = true) } } is WebViewResult.Learn2earnAnalyticsEvent -> { - analyticsEventHandler.send(result.event) + analytics.send(result.event) } WebViewResult.Empty -> Unit } @@ -222,6 +235,8 @@ internal class DefaultLearn2earnInteractor( } override fun isPromotionActiveOnMain(): Boolean { + if (dependencyProvider.getCardTypeResolver()?.isTangemWallet() != true) return false + val isActiveStatus = promotion.getPromotionInfo().oldCard.status == PromotionInfoResponse.Status.ACTIVE return isPromotionActive() && isActiveStatus } @@ -293,10 +308,12 @@ internal class DefaultLearn2earnInteractor( private fun WebViewResult.toWebViewAction(): WebViewAction { return when (this) { - WebViewResult.Empty -> WebViewAction.PROCEED + is WebViewResult.NewUserLearningFinished, + WebViewResult.OldUserLearningFinished, + is WebViewResult.Learn2earnAnalyticsEvent, + -> WebViewAction.NOTHING WebViewResult.ReadyForAward -> WebViewAction.FINISH_SESSION - is WebViewResult.Learn2earnAnalyticsEvent -> WebViewAction.NOTHING - is WebViewResult.PromoCode -> WebViewAction.NOTHING + WebViewResult.Empty -> WebViewAction.PROCEED } } } \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriBuilder.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriBuilder.kt index 89ac185bcd..ac763f5a52 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriBuilder.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriBuilder.kt @@ -12,8 +12,8 @@ internal class WebViewUriBuilder( private val promoCodeProvider: () -> String?, ) { - fun buildUriForNewUser(): Uri { - val builder = makeWebViewUriBuilder() + fun buildUriForNewUser(learningIsFinished: Boolean): Uri { + val builder = makeWebViewUriBuilder(learningIsFinished) .appendQueryParameter("type", QUERY_NEW_CARD) promoCodeProvider.invoke()?.let { @@ -23,9 +23,9 @@ internal class WebViewUriBuilder( return builder.build() } - fun buildUriForOldUser(): Uri { - val builder = makeWebViewUriBuilder() - .appendQueryParameter("type", QUERY_EXISTED_CARD) + fun buildUriForOldUser(learningIsFinished: Boolean): Uri { + val builder = makeWebViewUriBuilder(learningIsFinished) + .appendQueryParameter("type", QUERY_EXISTING_CARD) return builder.build() } @@ -39,7 +39,7 @@ internal class WebViewUriBuilder( } } - private fun makeWebViewUriBuilder(): Uri.Builder = Uri.Builder().apply { + private fun makeWebViewUriBuilder(learningIsFinished: Boolean): Uri.Builder = Uri.Builder().apply { scheme(SCHEME) if (BuildConfig.DEBUG) { authority(DEV_BASE_URL) @@ -48,6 +48,7 @@ internal class WebViewUriBuilder( } appendPath(getLocaleLanguage(localeLanguageProvider.invoke())) appendPath(PATH_PROMOTION) + appendQueryParameter(QUERY_FINISHED, learningIsFinished.toString()) } // TODO: locale: This can be used by another feature. Move it to the appropriate location @@ -66,7 +67,8 @@ internal class WebViewUriBuilder( const val PATH_PROMOTION = "promotion" const val QUERY_NEW_CARD = "new-card" - const val QUERY_EXISTED_CARD = "existed-card" + const val QUERY_EXISTING_CARD = "existing-card" + const val QUERY_FINISHED = "finished" const val DEV_BASE_URL = "devweb.tangem.com" diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriParser.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriParser.kt index f8d1d18e22..d169613478 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriParser.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/WebViewUriParser.kt @@ -1,7 +1,6 @@ package com.tangem.feature.learn2earn.domain import android.net.Uri -import com.tangem.feature.learn2earn.analytics.AnalyticsParam import com.tangem.feature.learn2earn.analytics.Learn2earnEvents import com.tangem.feature.learn2earn.analytics.Learn2earnEvents.PromoScreen import com.tangem.feature.learn2earn.domain.api.WebViewResult @@ -22,14 +21,17 @@ internal class WebViewUriParser( WebViewResult.Learn2earnAnalyticsEvent(event) } } - isPromoCodeRedirect(uri) -> { + isSuccessNewUserRedirect(uri) -> { val promoCode = extractPromoCode(uri) if (promoCode == null) { WebViewResult.Empty } else { - WebViewResult.PromoCode(promoCode) + WebViewResult.NewUserLearningFinished(promoCode) } } + isSuccessOldUserRedirect(uri) -> { + WebViewResult.OldUserLearningFinished + } isReadyForAwardRedirect(uri) -> { WebViewResult.ReadyForAward } @@ -40,13 +42,18 @@ internal class WebViewUriParser( return uri.lastPathSegment == PATH_READY_FOR_AWARD } - private fun isPromoCodeRedirect(uri: Uri): Boolean { - return uri.lastPathSegment == PATH_PROMO_CODE_CREATED && + private fun isSuccessNewUserRedirect(uri: Uri): Boolean { + return uri.lastPathSegment == PATH_LEARNING_SUCCESS && uri.queryParameterNames.contains(QUERY_PROMO_CODE) } + private fun isSuccessOldUserRedirect(uri: Uri): Boolean { + return uri.lastPathSegment == PATH_LEARNING_SUCCESS && + !uri.queryParameterNames.contains(QUERY_PROMO_CODE) + } + private fun extractPromoCode(uri: Uri): String? { - return if (isPromoCodeRedirect(uri)) { + return if (isSuccessNewUserRedirect(uri)) { uri.getQueryParameter(QUERY_PROMO_CODE) } else { null @@ -68,16 +75,14 @@ internal class WebViewUriParser( val analyticsEvent = when (event) { EVENT_PROMO_BUY -> PromoScreen.ButtonBuy() - EVENT_PROMO_SUCCESS_NEW_USER -> PromoScreen.SuccessScreenOpened(AnalyticsParam.ClientType.New()) - EVENT_PROMO_SUCCESS_OLD_USER -> PromoScreen.SuccessScreenOpened(AnalyticsParam.ClientType.Old()) else -> null } return analyticsEvent } private companion object { - const val PATH_PROMO_CODE_CREATED = "code-created" - const val PATH_READY_FOR_AWARD = "ready-for-existed-card-award" + const val PATH_LEARNING_SUCCESS = "success" + const val PATH_READY_FOR_AWARD = "ready-for-existing-card-award" const val PATH_ANALYTICS = "analytics" const val QUERY_PROMO_CODE = "code" @@ -85,7 +90,5 @@ internal class WebViewUriParser( const val QUERY_PROGRAM_NAME = "programName" const val EVENT_PROMO_BUY = "promotion-buy" - const val EVENT_PROMO_SUCCESS_NEW_USER = "promotion-success-new-user" - const val EVENT_PROMO_SUCCESS_OLD_USER = "promotion-success-old-user" } } \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt index 3c4178d472..9c650e8be0 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt @@ -1,5 +1,7 @@ package com.tangem.feature.learn2earn.domain.api +import com.tangem.domain.common.CardTypesResolver + /** * Interface, a wrapper that allows us to get values from the AppStateHolder located in the app module * @@ -7,6 +9,8 @@ package com.tangem.feature.learn2earn.domain.api */ interface Learn2earnDependencyProvider { + fun getCardTypeResolver(): CardTypesResolver? + fun getLocaleProvider(): () -> String fun getWebViewAuthCredentialsProvider(): () -> String? diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/WebViewResultHandler.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/WebViewResultHandler.kt index 6b7c851a69..5f5ab27959 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/WebViewResultHandler.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/WebViewResultHandler.kt @@ -12,8 +12,14 @@ interface WebViewResultHandler { } sealed class WebViewResult { + object Empty : WebViewResult() - data class PromoCode(val promoCode: String) : WebViewResult() + + data class NewUserLearningFinished(val promoCode: String?) : WebViewResult() + + object OldUserLearningFinished : WebViewResult() + object ReadyForAward : WebViewResult() + data class Learn2earnAnalyticsEvent(val event: AnalyticsEvent) : WebViewResult() } \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt index 72c05a6953..437a8eb716 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt @@ -51,7 +51,7 @@ internal class Learn2earnDomainModule { repository = repository, userWalletManager = userWalletManager, derivationManager = derivationManager, - analyticsEventHandler = analyticsEventHandler, + analytics = analyticsEventHandler, dependencyProvider = dependencyProvider, ) } diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt index 18613b0f54..aa563091c9 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt @@ -220,7 +220,7 @@ class Learn2earnViewModel @Inject constructor( interactor.webViewResultHandler = object : WebViewResultHandler { override fun handleResult(result: WebViewResult) { when (result) { - is WebViewResult.PromoCode -> { + is WebViewResult.NewUserLearningFinished -> { interactor.webViewResultHandler = null } WebViewResult.ReadyForAward -> { @@ -228,7 +228,10 @@ class Learn2earnViewModel @Inject constructor( updateMainScreenViews() requestAward() } - WebViewResult.Empty, is WebViewResult.Learn2earnAnalyticsEvent -> Unit + is WebViewResult.OldUserLearningFinished, + is WebViewResult.Learn2earnAnalyticsEvent, + WebViewResult.Empty, + -> Unit } } } From 91f06dfc1eb367203bb88bc7c9ebfb7342038b73 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Jul 2023 16:03:43 +0300 Subject: [PATCH 24/36] Updated on 2026-08-14 --- .../src/main/assets/configs/feature_toggles_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json index 7acffe7244..b5005743ed 100644 --- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json @@ -17,7 +17,7 @@ }, { "name": "1INCH_LEARN_2_EARN_ENABLED", - "version": "4.10.0" + "version": "4.9.0" }, { "name": "REDESIGNED_TOKEN_DETAIL_SCREEN_ENABLED", From 53be8c54f0a3d3d71d2cb42e0c4fc2bc34422c19 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Jul 2023 17:06:35 +0300 Subject: [PATCH 25/36] Updated on 2026-08-14 --- core/res/src/main/res/values-ru/strings.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 983a156305..4cb99df94d 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -68,7 +68,6 @@ Обменять Посмотреть историю транзакций Обозреватель - Учись и получай бонусы! Нравится Основная сеть Нет From aacbd8d71506a1b598328630b63b3fad135c825b Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Jul 2023 18:23:32 +0300 Subject: [PATCH 26/36] Updated on 2026-08-14 --- .../java/com/tangem/tap/domain/TangemSdkManager.kt | 2 +- app/src/main/java/com/tangem/tap/domain/TapErrors.kt | 2 +- .../tangem/tap/domain/scanCard/LegacyScanProcessor.kt | 9 ++++++++- .../domain/scanCard/chains/CheckForOnboardingChain.kt | 9 ++++++++- .../tangem/tap/domain/tasks/product/ScanProductTask.kt | 10 ++++++---- .../tangem/tap/features/onboarding/OnboardingHelper.kt | 6 +++++- core/res/src/main/res/values-ru/strings.xml | 1 + core/res/src/main/res/values/strings.xml | 1 + .../tangem/domain/common/TangemCardTypesResolver.kt | 3 ++- .../java/com/tangem/domain/common/TapWorkarounds.kt | 5 +++++ gradle/dependencies.toml | 2 +- 11 files changed, 39 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt index c395569c5c..ec8103cbe2 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -256,7 +256,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co allowUntrustedCards = true, filter = CardFilter( allowedCardTypes = FirmwareVersion.FirmwareType.values().toList(), - maxFirmwareVersion = FirmwareVersion(major = 4, minor = 52), + maxFirmwareVersion = FirmwareVersion(major = 6, minor = 21), ), ) } diff --git a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt index fc7bdedd39..b986f9f247 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt @@ -64,7 +64,7 @@ sealed class TapSdkError(override val messageResId: Int?) : TangemError(code = 5 override var customMessage: String = code.toString() object CardForDifferentApp : TapSdkError(R.string.alert_unsupported_card) - object CardNotSupportedByRelease : TapSdkError(R.string.error_update_app) + object CardNotSupportedByRelease : TapSdkError(R.string.error_wrong_card_type) } fun TapErrors.assembleErrors(): MutableList?>> { diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt index e83d2496ff..b2b40dd547 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt @@ -9,6 +9,7 @@ import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.AnalyticsEvent import com.tangem.core.navigation.AppScreen import com.tangem.core.navigation.NavigationAction +import com.tangem.domain.common.TapWorkarounds.canSkipBackup import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.util.twinsIsTwinned import com.tangem.domain.models.scan.ScanResponse @@ -153,7 +154,13 @@ internal object LegacyScanProcessor { if (OnboardingHelper.isOnboardingCase(scanResponse)) { Analytics.addContext(scanResponse) onWalletNotCreated() - store.dispatchOnMain(GlobalAction.Onboarding.Start(scanResponse, canSkipBackup = true)) + // must check skip backup using card canSkipBackup + store.dispatchOnMain( + GlobalAction.Onboarding.Start( + scanResponse = scanResponse, + canSkipBackup = scanResponse.card.canSkipBackup, + ), + ) val appScreen = OnboardingHelper.whereToNavigate(scanResponse) navigateTo(appScreen) { onProgressStateChange(it) } } else { diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForOnboardingChain.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForOnboardingChain.kt index baa5c93445..4f5729135c 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForOnboardingChain.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/chains/CheckForOnboardingChain.kt @@ -7,6 +7,7 @@ import com.tangem.core.analytics.Analytics import com.tangem.core.navigation.AppScreen import com.tangem.data.source.preferences.PreferencesDataSource import com.tangem.domain.card.ScanCardException +import com.tangem.domain.common.TapWorkarounds.canSkipBackup import com.tangem.domain.common.util.twinsIsTwinned import com.tangem.domain.core.chain.Chain import com.tangem.domain.models.scan.ScanResponse @@ -50,7 +51,13 @@ class CheckForOnboardingChain( return when { OnboardingHelper.isOnboardingCase(previousChainResult) -> { Analytics.addContext(previousChainResult) - store.dispatchOnMain(GlobalAction.Onboarding.Start(previousChainResult, canSkipBackup = true)) + // must check skip backup using card canSkipBackup + store.dispatchOnMain( + GlobalAction.Onboarding.Start( + scanResponse = previousChainResult, + canSkipBackup = previousChainResult.card.canSkipBackup, + ), + ) val appScreen = OnboardingHelper.whereToNavigate(previousChainResult) ScanChainException.OnboardingNeeded(appScreen).left() } diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt index 663e931472..c3f23eb9b4 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt @@ -51,7 +51,7 @@ class ScanProductTask( } val cardDto = CardDTO(card) - val error = getErrorIfExcludedCard(cardDto) + val error = getErrorIfExcludedCard(cardDto, card) if (error != null) { callback(CompletionResult.Failure(error)) return @@ -81,9 +81,11 @@ class ScanProductTask( } } - private fun getErrorIfExcludedCard(card: CardDTO): TangemError? { - if (card.isExcluded) return TapSdkError.CardForDifferentApp - if (card.isNotSupportedInThatRelease) return TapSdkError.CardNotSupportedByRelease + private fun getErrorIfExcludedCard(cardDto: CardDTO, card: Card): TangemError? { + if (cardDto.isExcluded) return TapSdkError.CardForDifferentApp + if (cardDto.isNotSupportedInThatRelease) return TapSdkError.CardNotSupportedByRelease + // todo check isImported to prevent using old app with imported wallet, remove before wallet 2.0 enabled ([REDACTED_TASK_KEY]) + if (card.wallets.any { it.isImported }) return TapSdkError.CardNotSupportedByRelease return null } } 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 477ab679c6..624ecfb185 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 @@ -6,6 +6,7 @@ import com.tangem.common.extensions.guard import com.tangem.core.analytics.Analytics import com.tangem.core.navigation.AppScreen import com.tangem.core.navigation.NavigationAction +import com.tangem.domain.common.TapWorkarounds.canSkipBackup import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.common.util.twinsIsTwinned import com.tangem.domain.models.scan.ProductType @@ -37,7 +38,10 @@ object OnboardingHelper { } } - response.cardTypesResolver.isWallet2() -> { + // TODO for Shiba disabled check wallet 2, and only check canSkipBackup, enable when release wallet 2 + // ([REDACTED_TASK_KEY]) + // response.cardTypesResolver.isWallet2() -> { + !response.card.canSkipBackup -> { val emptyWallets = response.card.wallets.isEmpty() val activationInProgress = cardInfoStorage.isActivationInProgress(cardId) val backupNotActive = response.card.backupStatus?.isActive != true diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 4cb99df94d..e211f2f00e 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -138,6 +138,7 @@ Проверьте подключение с интернетом или переключитесь на другую сеть Условия использования К сожалению, текущая версия приложения не готова к работе с этой картой, проверьте наличие обновлений + Данное приложение не предназначено для работы с этой картой или требует обновления Вы использовали карту от другого кошелька. Приложите карту, связанную с этим кошельком. Вы получаете Вы отправляете diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 90489aa58e..2be8d9db1b 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -137,6 +137,7 @@ Check your internet connection or switch to a different network Terms of Service Oops, the current version of the application is not ready to work with this card, please check for updates. + This application is not designed to work with this card or needs to be updated You have used a card from another wallet. Tap the card associated with this wallet You Receive You Send diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt b/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt index 39991063b5..9f993a407b 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/TangemCardTypesResolver.kt @@ -29,7 +29,8 @@ internal class TangemCardTypesResolver( } override fun isWallet2(): Boolean { - return card.firmwareVersion >= FirmwareVersion.KeysImportAvailable && card.settings.isKeysImportAllowed + // todo for now disabled to prevent Shiba cards using as wallet 2, enable when release wallet 2.0 ([REDACTED_TASK_KEY]) + return false // card.firmwareVersion >= FirmwareVersion.KeysImportAvailable && card.settings.isKeysImportAllowed } override fun isTangemTwins(): Boolean = productType == ProductType.Twins diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/TapWorkarounds.kt b/domain/legacy/src/main/java/com/tangem/domain/common/TapWorkarounds.kt index 5d25521277..ccd30b6eb0 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/TapWorkarounds.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/TapWorkarounds.kt @@ -3,6 +3,7 @@ package com.tangem.domain.common import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.DerivationStyle import com.tangem.common.card.Card +import com.tangem.common.card.FirmwareVersion import com.tangem.domain.models.scan.CardDTO import java.util.* @@ -23,6 +24,10 @@ object TapWorkarounds { val CardDTO.isTestCard: Boolean get() = batchId == TEST_CARD_BATCH && cardId.startsWith(TEST_CARD_ID_STARTS_WITH) + // for cards 6.21 and higher backup is not skippable + val CardDTO.canSkipBackup: Boolean + get() = this.firmwareVersion < FirmwareVersion.KeysImportAvailable + val CardDTO.useOldStyleDerivation: Boolean get() = batchId == "AC01" || batchId == "AC02" || batchId == "CB95" diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index cb8ecb3892..8a64ca11a7 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -80,7 +80,7 @@ walletConnectWeb3 = "1.11.0" # region Tangem tangemBlockchainSdk = "release-app_4.9-286" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_4.9-274" +tangemCardSdk = "release-app_4.9-276" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds # endregion Tangem From 510f312c33aeba0c9cf735e902ae376cf1edf5f4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Jul 2023 18:44:20 +0300 Subject: [PATCH 27/36] Updated on 2026-08-14 --- .../domain/DefaultLearn2earnInteractor.kt | 20 ++++++++++++++----- .../domain/di/Learn2earnDomainModule.kt | 3 +++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt index 12f37ee9f8..69422e16ed 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt @@ -3,6 +3,7 @@ package com.tangem.feature.learn2earn.domain import android.net.Uri import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.datasource.api.promotion.models.PromotionInfoResponse +import com.tangem.datasource.demo.DemoModeDatasource import com.tangem.feature.learn2earn.analytics.AnalyticsParam import com.tangem.feature.learn2earn.analytics.Learn2earnEvents.* import com.tangem.feature.learn2earn.data.api.Learn2earnRepository @@ -19,12 +20,14 @@ import com.tangem.lib.crypto.models.Currency /** [REDACTED_AUTHOR] */ +@Suppress("LongParameterList") internal class DefaultLearn2earnInteractor( private val featureToggleManager: Learn2earnFeatureToggleManager, private val repository: Learn2earnRepository, private val userWalletManager: UserWalletManager, private val derivationManager: DerivationManager, private val analytics: AnalyticsEventHandler, + private val demoModeDatasource: DemoModeDatasource, private val dependencyProvider: Learn2earnDependencyProvider, ) : Learn2earnInteractor { @@ -221,6 +224,7 @@ internal class DefaultLearn2earnInteractor( override fun isPromotionActive(): Boolean { val isActive = when { + demoModeDatasource.isDemoModeActive -> false !featureToggleManager.isLearn2earnEnabled -> false repository.getUserData().isAlreadyReceivedAward -> false else -> !promotion.isError() @@ -230,15 +234,21 @@ internal class DefaultLearn2earnInteractor( } override fun isPromotionActiveOnStories(): Boolean { - val isActiveStatus = promotion.getPromotionInfo().newCard.status == PromotionInfoResponse.Status.ACTIVE - return isPromotionActive() && isActiveStatus + return if (isPromotionActive()) { + promotion.getPromotionInfo().newCard.status == PromotionInfoResponse.Status.ACTIVE + } else { + false + } } override fun isPromotionActiveOnMain(): Boolean { - if (dependencyProvider.getCardTypeResolver()?.isTangemWallet() != true) return false + val cardTypesResolver = dependencyProvider.getCardTypeResolver() ?: return false - val isActiveStatus = promotion.getPromotionInfo().oldCard.status == PromotionInfoResponse.Status.ACTIVE - return isPromotionActive() && isActiveStatus + return when { + !isPromotionActive() -> false + !cardTypesResolver.isTangemWallet() -> false + else -> promotion.getPromotionInfo().oldCard.status == PromotionInfoResponse.Status.ACTIVE + } } private suspend fun initPromotionInfo() { diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt index 437a8eb716..8aabf0ded3 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt @@ -3,6 +3,7 @@ package com.tangem.feature.learn2earn.domain.di import android.content.Context import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.featuretoggle.manager.FeatureTogglesManager +import com.tangem.datasource.demo.DemoModeDatasource import com.tangem.feature.learn2earn.data.api.Learn2earnRepository import com.tangem.feature.learn2earn.data.toggles.DefaultLearn2earnFeatureToggleManager import com.tangem.feature.learn2earn.data.toggles.Learn2earnFeatureToggleManager @@ -45,6 +46,7 @@ internal class Learn2earnDomainModule { userWalletManager: UserWalletManager, analyticsEventHandler: AnalyticsEventHandler, derivationManager: DerivationManager, + demoModeDatasource: DemoModeDatasource, ): Learn2earnInteractor { return DefaultLearn2earnInteractor( featureToggleManager = featureToggleManager, @@ -52,6 +54,7 @@ internal class Learn2earnDomainModule { userWalletManager = userWalletManager, derivationManager = derivationManager, analytics = analyticsEventHandler, + demoModeDatasource = demoModeDatasource, dependencyProvider = dependencyProvider, ) } From 5e858587003c971fa240d4eaa7ea94f519ef1ab0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Jul 2023 22:56:23 +0300 Subject: [PATCH 28/36] Updated on 2026-08-14 --- .../products/wallet/redux/OnboardingWalletMiddleware.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 67921cce64..1819011b64 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -9,6 +9,7 @@ import com.tangem.core.analytics.Analytics import com.tangem.core.navigation.AppScreen import com.tangem.core.navigation.NavigationAction import com.tangem.domain.common.BlockchainNetwork +import com.tangem.domain.common.TapWorkarounds.canSkipBackup import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.models.scan.CardDTO @@ -338,7 +339,9 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) is CompletionResult.Failure -> { val error = result.error if (error is TangemSdkError.BackupFailedNotEmptyWallets && - onboardingWalletState.wallet2State != null + // todo disabled this check in task with shiba ([REDACTED_TASK_KEY]) and added canSkipBackup + // && onboardingWalletState.wallet2State != null + card?.canSkipBackup == false ) { store.dispatchOnMain( GlobalAction.ShowDialog( From 332bdabfbacd7f5dca35a401bc61b0b2db73b091 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 Jul 2023 15:04:19 +0300 Subject: [PATCH 29/36] Updated on 2026-08-14 --- core/res/src/main/res/values-ru/strings.xml | 1 + core/res/src/main/res/values-zh-rTW/strings.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index e211f2f00e..00f29ea502 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -214,6 +214,7 @@ В этом случае вам будет необходимо начать процесс заново. Вы хотите выйти из процесса активации? Подготовка + Другой кошелек уже был создан на карте, которую вы пытаетесь добавить. Хотите сбросить его и использовать карту для бэкапа? Код доступа Подключиться Резервная копия diff --git a/core/res/src/main/res/values-zh-rTW/strings.xml b/core/res/src/main/res/values-zh-rTW/strings.xml index ccb6abe736..0b2d148627 100644 --- a/core/res/src/main/res/values-zh-rTW/strings.xml +++ b/core/res/src/main/res/values-zh-rTW/strings.xml @@ -187,6 +187,7 @@ 這此情況,您必須要重新開始 您想要離開啟用程序嗎? 開始 + 您要添加的卡上已經創建了另一個錢包。你想重置它並將卡用於新錢包嗎 PIN 碼 連接 創建備份 From 4b72ca5252c452e24fbf289f4b429529626fe651 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 Jul 2023 15:05:31 +0300 Subject: [PATCH 30/36] 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 8a64ca11a7..951a9904dc 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -80,7 +80,7 @@ walletConnectWeb3 = "1.11.0" # region Tangem tangemBlockchainSdk = "release-app_4.9-286" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_4.9-276" +tangemCardSdk = "release-app_4.9-277" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds # endregion Tangem From 8611aca9e06a5dbeb9c1a92c01e9119869861172 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 Jul 2023 18:41:34 +0300 Subject: [PATCH 31/36] Updated on 2026-08-14 --- .../com/tangem/tap/proxy/AppStateHolder.kt | 11 ++++++ .../com/tangem/tap/proxy/di/ProxyModule.kt | 13 +++++-- .../wallets/legacy/WalletsStateHolder.kt | 4 +++ .../domain/DefaultLearn2earnInteractor.kt | 34 +++++++++++++++++-- .../api/Learn2earnDependencyProvider.kt | 3 +- .../domain/api/Learn2earnInteractor.kt | 3 ++ .../domain/di/Learn2earnDomainModule.kt | 3 ++ .../presentation/Learn2earnViewModel.kt | 16 ++++++++- 8 files changed, 80 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt index cf6015d446..e2d0137b1a 100644 --- a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt +++ b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt @@ -13,6 +13,8 @@ import com.tangem.tap.domain.TangemSdkManager import com.tangem.tap.domain.tokens.UserTokensRepository import com.tangem.tap.domain.walletStores.WalletStoresManager import com.tangem.tap.features.wallet.redux.WalletState +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow import org.rekotlin.Store import javax.inject.Inject @@ -23,6 +25,15 @@ import javax.inject.Inject class AppStateHolder @Inject constructor() : WalletsStateHolder, NavigationStateHolder { override var userWalletsListManager: UserWalletsListManager? = null + set(value) { + field = value + _userWalletsListManagerFlow.value = value + } + + override val userWalletListManagerFlow: Flow + get() = _userWalletsListManagerFlow + + private val _userWalletsListManagerFlow = MutableStateFlow(null) @Deprecated("Use scan response from selected user wallet") var scanResponse: ScanResponse? = null diff --git a/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt b/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt index 90c5bc1691..89f1b31c15 100644 --- a/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt +++ b/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt @@ -16,6 +16,8 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.* import javax.inject.Singleton @Module @@ -58,8 +60,15 @@ class ProxyModule { @Singleton fun provideLear2earnDependencies(appStateHolder: AppStateHolder): Learn2earnDependencyProvider { return object : Learn2earnDependencyProvider { - override fun getCardTypeResolver(): CardTypesResolver? { - return appStateHolder.userWalletsListManager?.selectedUserWalletSync?.scanResponse?.cardTypesResolver + + @OptIn(ExperimentalCoroutinesApi::class) + override fun getCardTypeResolverFlow(): Flow { + return appStateHolder.userWalletListManagerFlow + .flatMapLatest { manager -> + manager?.selectedUserWallet + ?.map { it.scanResponse.cardTypesResolver } + ?: flowOf(null) + } } override fun getLocaleProvider(): () -> String = { Locale.current.language } diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/legacy/WalletsStateHolder.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/legacy/WalletsStateHolder.kt index 3c7b38bbbe..7aa875c6af 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/legacy/WalletsStateHolder.kt +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/legacy/WalletsStateHolder.kt @@ -1,6 +1,10 @@ package com.tangem.domain.wallets.legacy +import kotlinx.coroutines.flow.Flow + interface WalletsStateHolder { val userWalletsListManager: UserWalletsListManager? + + val userWalletListManagerFlow: Flow } \ No newline at end of file diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt index 69422e16ed..13ffe1db9b 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt @@ -16,6 +16,14 @@ import com.tangem.feature.learn2earn.domain.models.toDomainError import com.tangem.lib.crypto.DerivationManager import com.tangem.lib.crypto.UserWalletManager import com.tangem.lib.crypto.models.Currency +import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider +import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach /** [REDACTED_AUTHOR] @@ -29,12 +37,19 @@ internal class DefaultLearn2earnInteractor( private val analytics: AnalyticsEventHandler, private val demoModeDatasource: DemoModeDatasource, private val dependencyProvider: Learn2earnDependencyProvider, + dispatchers: AppCoroutineDispatcherProvider, ) : Learn2earnInteractor { override var webViewResultHandler: WebViewResultHandler? = null private lateinit var promotion: Promotion + private val scope = CoroutineScope(Job() + dispatchers.io + FeatureCoroutineExceptionHandler.create("mainScope")) + + private val isTangemWalletFlow = MutableStateFlow(false) + private var isTangemWalletFlowJob: Job? = null + private var isTangemWalletFlowSync = false + private val webViewUriBuilder: WebViewUriBuilder by lazy { WebViewUriBuilder( authCredentialsProvider = dependencyProvider.getWebViewAuthCredentialsProvider(), @@ -51,6 +66,8 @@ internal class DefaultLearn2earnInteractor( initPromotionInfo() } + override fun getIsTangemWalletFlow(): Flow = isTangemWalletFlow + override fun isUserHadPromoCode(): Boolean { return repository.getUserData().promoCode != null } @@ -223,6 +240,8 @@ internal class DefaultLearn2earnInteractor( } override fun isPromotionActive(): Boolean { + subscribeToCardTypeResolverFlow() + val isActive = when { demoModeDatasource.isDemoModeActive -> false !featureToggleManager.isLearn2earnEnabled -> false @@ -242,11 +261,9 @@ internal class DefaultLearn2earnInteractor( } override fun isPromotionActiveOnMain(): Boolean { - val cardTypesResolver = dependencyProvider.getCardTypeResolver() ?: return false - return when { !isPromotionActive() -> false - !cardTypesResolver.isTangemWallet() -> false + !isTangemWalletFlowSync -> false else -> promotion.getPromotionInfo().oldCard.status == PromotionInfoResponse.Status.ACTIVE } } @@ -308,6 +325,17 @@ internal class DefaultLearn2earnInteractor( } } + private fun subscribeToCardTypeResolverFlow() { + if (isTangemWalletFlowJob == null || isTangemWalletFlowJob?.isCancelled == true) { + isTangemWalletFlowJob = dependencyProvider.getCardTypeResolverFlow() + .onEach { + isTangemWalletFlowSync = it?.isTangemWallet() ?: false + isTangemWalletFlow.emit(isTangemWalletFlowSync) + } + .launchIn(scope) + } + } + private fun Promotion.PromotionInfo.getData(promoCode: String?): PromotionInfoResponse.Data { return if (promoCode == null) { oldCard diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt index 9c650e8be0..60a23a88fb 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnDependencyProvider.kt @@ -1,6 +1,7 @@ package com.tangem.feature.learn2earn.domain.api import com.tangem.domain.common.CardTypesResolver +import kotlinx.coroutines.flow.Flow /** * Interface, a wrapper that allows us to get values from the AppStateHolder located in the app module @@ -9,7 +10,7 @@ import com.tangem.domain.common.CardTypesResolver */ interface Learn2earnDependencyProvider { - fun getCardTypeResolver(): CardTypesResolver? + fun getCardTypeResolverFlow(): Flow fun getLocaleProvider(): () -> String diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt index 8498c9483e..e4571a9420 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt @@ -2,6 +2,7 @@ package com.tangem.feature.learn2earn.domain.api import android.net.Uri import com.tangem.feature.learn2earn.domain.models.PromotionError +import kotlinx.coroutines.flow.Flow /** [REDACTED_AUTHOR] @@ -12,6 +13,8 @@ interface Learn2earnInteractor : WebViewRedirectHandler { suspend fun init() + fun getIsTangemWalletFlow(): Flow + fun isUserHadPromoCode(): Boolean fun isPromotionActive(): Boolean diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt index 8aabf0ded3..ae96ed3668 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/di/Learn2earnDomainModule.kt @@ -14,6 +14,7 @@ import com.tangem.feature.learn2earn.domain.api.WebViewRedirectHandler import com.tangem.feature.learn2earn.presentation.Learn2earnRouter import com.tangem.lib.crypto.DerivationManager import com.tangem.lib.crypto.UserWalletManager +import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -47,6 +48,7 @@ internal class Learn2earnDomainModule { analyticsEventHandler: AnalyticsEventHandler, derivationManager: DerivationManager, demoModeDatasource: DemoModeDatasource, + dispatchers: AppCoroutineDispatcherProvider, ): Learn2earnInteractor { return DefaultLearn2earnInteractor( featureToggleManager = featureToggleManager, @@ -56,6 +58,7 @@ internal class Learn2earnDomainModule { analytics = analyticsEventHandler, demoModeDatasource = demoModeDatasource, dependencyProvider = dependencyProvider, + dispatchers = dispatchers, ) } diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt index aa563091c9..082e51488c 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt @@ -44,11 +44,25 @@ class Learn2earnViewModel @Inject constructor( private set init { + subscribeToWalletChanges() uiState = uiState .updateStoriesVisibility(isVisible = interactor.isPromotionActiveOnStories()) .updateGetBonusVisibility(isVisible = interactor.isPromotionActiveOnMain()) } + private fun subscribeToWalletChanges() { + viewModelScope.launch(dispatchers.io) { + interactor.getIsTangemWalletFlow() + .collect { isTangemWallet -> + updateUi { + uiState + .updateGetBonusVisibility(isVisible = isTangemWallet) + .changeGetBounsDescription(getBonusDescription()) + } + } + } + } + fun onMainScreenCreated() { updateMainScreenViews() } @@ -137,7 +151,7 @@ class Learn2earnViewModel @Inject constructor( onSuccess = { analytics.send(Learn2earnEvents.MainScreen.NoticeClaimSuccess()) val onHideDialog = { - uiState = uiState.updateGetBonusVisibility(isVisible = false) + uiState = uiState.updateViewsVisibility(isVisible = false) .hideDialog() } val successDialog = MainScreenState.Dialog.Claimed( From 6c97b14db7891a725b151956051d6ed672dce9e2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 Jul 2023 18:44:56 +0300 Subject: [PATCH 32/36] Updated on 2026-08-14 --- .../webView/Learn2earnWebViewActivity.kt | 89 +++++++++---------- .../webView/Learn2earnWebViewClient.kt | 4 +- .../src/main/res/layout/activity_web_view.xml | 31 +++++++ 3 files changed, 77 insertions(+), 47 deletions(-) create mode 100644 features/learn2earn/impl/src/main/res/layout/activity_web_view.xml diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt index 40e8a9e775..b5d341df31 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewActivity.kt @@ -1,19 +1,12 @@ package com.tangem.feature.learn2earn.presentation.webView import android.os.Bundle -import androidx.activity.compose.BackHandler -import androidx.activity.compose.setContent +import android.view.MenuItem +import android.webkit.WebView import androidx.activity.viewModels +import androidx.appcompat.app.ActionBar import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import com.google.accompanist.web.WebView -import com.google.accompanist.web.rememberWebViewState -import com.tangem.core.ui.components.appbar.AppBarWithBackButton -import com.tangem.core.ui.res.TangemTheme +import com.tangem.feature.learn2earn.impl.R import dagger.hilt.android.AndroidEntryPoint /** @@ -24,48 +17,54 @@ class Learn2earnWebViewActivity : AppCompatActivity() { private val viewModel by viewModels() + private lateinit var actionBar: ActionBar + private lateinit var webView: WebView + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setContentView(R.layout.activity_web_view) + val webViewData = viewModel.extractData(intent) - setContent { - TangemTheme { - BackHandler(onBack = { finish() }) - ScreenContent(webViewData) + setSupportActionBar(findViewById(R.id.toolbar)) + actionBar = supportActionBar!! + actionBar.setDisplayHomeAsUpEnabled(true) + actionBar.setDisplayShowHomeEnabled(true) + actionBar.title = webViewData.uri.authority + webView = findViewById(R.id.web_view) + + webView.settings.javaScriptEnabled = true + webView.settings.domStorageEnabled = true + webView.settings.loadsImagesAutomatically = true + + webView.webViewClient = Learn2earnWebViewClient( + redirectHandler = viewModel, + headers = webViewData.headers, + finishSessionHandler = { finish() }, + ) + + webView.loadUrl( + webViewData.uri.toString(), + webViewData.headers, + ) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + android.R.id.home -> { + finish() + true } + else -> super.onOptionsItemSelected(item) } } - @Suppress("TopLevelComposableFunctions") - @Composable - private fun ScreenContent(webViewData: WebViewData) { - Column { - AppBarWithBackButton( - modifier = Modifier.background(TangemTheme.colors.background.secondary), - text = webViewData.uri.authority, - onBackClick = { finish() }, - ) - WebView( - state = rememberWebViewState( - url = webViewData.uri.toString(), - additionalHttpHeaders = webViewData.headers, - ), - onCreated = { - it.settings.apply { - javaScriptEnabled = true - domStorageEnabled = true - loadsImagesAutomatically = true - } - }, - client = remember { - Learn2earnWebViewClient( - redirectHandler = viewModel, - headers = webViewData.headers, - finishSessionHandler = { finish() }, - ) - }, - ) - } + override fun onDestroy() { + webView.clearHistory() + webView.clearCache(true) + webView.destroy() + + super.onDestroy() } companion object { diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt index 575b074b03..7a96dbc90b 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/webView/Learn2earnWebViewClient.kt @@ -2,7 +2,7 @@ package com.tangem.feature.learn2earn.presentation.webView import android.webkit.WebResourceRequest import android.webkit.WebView -import com.google.accompanist.web.AccompanistWebViewClient +import android.webkit.WebViewClient import com.tangem.feature.learn2earn.domain.api.WebViewAction import com.tangem.feature.learn2earn.domain.api.WebViewRedirectHandler import timber.log.Timber @@ -11,7 +11,7 @@ internal class Learn2earnWebViewClient( private val redirectHandler: WebViewRedirectHandler, private val headers: Map, private val finishSessionHandler: () -> Unit, -) : AccompanistWebViewClient() { +) : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean { Timber.d("url: ${request.url}") diff --git a/features/learn2earn/impl/src/main/res/layout/activity_web_view.xml b/features/learn2earn/impl/src/main/res/layout/activity_web_view.xml new file mode 100644 index 0000000000..8925162b7e --- /dev/null +++ b/features/learn2earn/impl/src/main/res/layout/activity_web_view.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + \ No newline at end of file From 3babc020c837e6523288262b59e0d4c72ac7093a Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 Jul 2023 19:12:08 +0300 Subject: [PATCH 33/36] Updated on 2026-08-14 --- .../learn2earn/domain/DefaultLearn2earnInteractor.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt index 13ffe1db9b..9bf458c7ff 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt @@ -24,6 +24,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import timber.log.Timber /** [REDACTED_AUTHOR] @@ -90,11 +91,12 @@ internal class DefaultLearn2earnInteractor( return repository.getUserData().isRegisteredInPromotion } - override fun getAwardAmount(): Int { + override fun getAwardAmount(): Int = try { val promoCode = repository.getUserData().promoCode - val awardAmount = promotion.getPromotionInfo().getData(promoCode).award.toInt() - - return awardAmount + promotion.getPromotionInfo().getData(promoCode).award.toInt() + } catch (ex: NullPointerException) { + Timber.e(ex) + 0 } override fun getAwardNetworkName(): String { From 87d25f513b570fd5f3a3586e49c1af92be47aca2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sat, 22 Jul 2023 15:05:30 +0300 Subject: [PATCH 34/36] Updated on 2026-08-14 --- .../domain/DefaultLearn2earnInteractor.kt | 10 +++-- .../domain/api/Learn2earnInteractor.kt | 3 +- .../presentation/Learn2earnViewModel.kt | 44 +++++++++++-------- .../presentation/ui/state/StateBuilder.kt | 2 +- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt index 9bf458c7ff..c2cfa092b7 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/DefaultLearn2earnInteractor.kt @@ -73,7 +73,7 @@ internal class DefaultLearn2earnInteractor( return repository.getUserData().promoCode != null } - override suspend fun validateUserWallet(): PromotionError? { + override suspend fun validateUserWallet(): Result { val promoCode = repository.getUserData().promoCode val userWalletId = userWalletManager.getWalletId() @@ -83,8 +83,12 @@ internal class DefaultLearn2earnInteractor( repository.validateCode(userWalletId, promoCode).error }?.toDomainError() - return domainError - ?.also { handlePromotionError(it) } + return if (domainError == null) { + Result.success(Unit) + } else { + handlePromotionError(domainError) + Result.failure(domainError) + } } override fun isUserRegisteredInPromotion(): Boolean { diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt index e4571a9420..85f15629df 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/domain/api/Learn2earnInteractor.kt @@ -1,7 +1,6 @@ package com.tangem.feature.learn2earn.domain.api import android.net.Uri -import com.tangem.feature.learn2earn.domain.models.PromotionError import kotlinx.coroutines.flow.Flow /** @@ -23,7 +22,7 @@ interface Learn2earnInteractor : WebViewRedirectHandler { fun isPromotionActiveOnMain(): Boolean - suspend fun validateUserWallet(): PromotionError? + suspend fun validateUserWallet(): Result fun isUserRegisteredInPromotion(): Boolean diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt index 082e51488c..1d14fb5c7f 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt @@ -20,6 +20,7 @@ import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import timber.log.Timber import javax.inject.Inject /** @@ -57,7 +58,7 @@ class Learn2earnViewModel @Inject constructor( updateUi { uiState .updateGetBonusVisibility(isVisible = isTangemWallet) - .changeGetBounsDescription(getBonusDescription()) + .changeGetBonusDescription(getBonusDescription()) } } } @@ -78,24 +79,31 @@ class Learn2earnViewModel @Inject constructor( } viewModelScope.launch(dispatchers.io) { - val error = interactor.validateUserWallet() - when { - error == null -> { - updateUi { - uiState - .updateStoriesVisibility(isVisible = interactor.isPromotionActiveOnStories()) - .updateGetBonusVisibility(isVisible = interactor.isPromotionActiveOnMain()) - .changeGetBounsDescription(getBonusDescription()) - } + runCatching { interactor.validateUserWallet() } + .onSuccess { result -> + result.fold( + onSuccess = { + updateUi { + uiState + .updateStoriesVisibility(isVisible = interactor.isPromotionActiveOnStories()) + .updateGetBonusVisibility(isVisible = interactor.isPromotionActiveOnMain()) + .changeGetBonusDescription(getBonusDescription()) + } + }, + onFailure = { + if (interactor.isPromotionActive()) { + val error = it as? PromotionError ?: return@launch + updateViewsVisibilityOnError(error) + } else { + updateUi { uiState.updateViewsVisibility(isVisible = false) } + } + }, + ) } - // additional check after the error has been handled by interactor - !interactor.isPromotionActive() -> { - updateUi { uiState.updateViewsVisibility(isVisible = false) } + .onFailure { + Timber.e(it) + updateUi { uiState.updateGetBonusVisibility(isVisible = false) } } - else -> { - updateViewsVisibilityOnError(error) - } - } } } @@ -116,7 +124,7 @@ class Learn2earnViewModel @Inject constructor( -> { updateUi { uiState.updateViewsVisibility(isVisible = true) - .changeGetBounsDescription(getBonusDescription()) + .changeGetBonusDescription(getBonusDescription()) } } is PromotionError.UnknownError, diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt index c97472b8b5..a473dd04d2 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/ui/state/StateBuilder.kt @@ -48,7 +48,7 @@ internal fun Learn2earnState.updateViewsVisibility(isVisible: Boolean): Learn2ea .updateGetBonusVisibility(isVisible) } -internal fun Learn2earnState.changeGetBounsDescription(description: MainScreenState.Description): Learn2earnState { +internal fun Learn2earnState.changeGetBonusDescription(description: MainScreenState.Description): Learn2earnState { return if (mainScreenState.description == description) { this } else { From 4305165952811b94decb3c3cea3b98475c898705 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 23 Jul 2023 22:29:12 +0300 Subject: [PATCH 35/36] Updated on 2026-08-14 --- .../feature/learn2earn/presentation/Learn2earnViewModel.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt index 1d14fb5c7f..fe171ddbda 100644 --- a/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt +++ b/features/learn2earn/impl/src/main/java/com/tangem/feature/learn2earn/presentation/Learn2earnViewModel.kt @@ -57,7 +57,9 @@ class Learn2earnViewModel @Inject constructor( .collect { isTangemWallet -> updateUi { uiState - .updateGetBonusVisibility(isVisible = isTangemWallet) + .updateGetBonusVisibility( + isVisible = isTangemWallet && interactor.isPromotionActiveOnMain(), + ) .changeGetBonusDescription(getBonusDescription()) } } From 025e41aa3863e3c1689f65c0ef8420ba23aa3e89 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 24 Jul 2023 15:08:14 +0300 Subject: [PATCH 36/36] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt index 5ab4d720a3..5bac8dc2b2 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -7,6 +7,7 @@ import com.tangem.TangemSdk import com.tangem.blockchain.common.Blockchain import com.tangem.common.* import com.tangem.common.biometric.BiometricManager +import com.tangem.common.card.FirmwareVersion import com.tangem.common.core.* import com.tangem.common.extensions.ByteArrayKey import com.tangem.common.usersCode.UserCodeRepository