From fb4020ac9127381200cfecc45346a1f8004c42d1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 9 Dec 2025 16:11:28 +0400 Subject: [PATCH 01/11] Updated on 2026-08-14 --- .../DefaultTangemPayCryptoCurrencyFactory.kt | 64 ++++++++++++++ .../pay/DefaultTangemPaySwapDataFactory.kt | 85 ------------------- .../tangem/data/pay/di/TangemPayDataModule.kt | 8 +- .../DefaultTangemPayCardDetailsRepository.kt | 1 + .../pay/TangemPayCryptoCurrencyFactory.kt | 11 +++ .../domain/pay/model/TangemPayCardBalance.kt | 1 + .../TangemPayTopUpData.kt} | 16 +--- .../components/TangemPayAddFundsComponent.kt | 2 +- .../tangempay/model/TangemPayAddFundsModel.kt | 37 +++++--- .../tangempay/model/TangemPayDetailsModel.kt | 41 ++++----- .../transformers/DetailsBalanceTransformer.kt | 33 +++++-- .../TangemPayAddFundsUMConverter.kt | 2 +- .../tangempay/ui/TangemPayDetailsScreen.kt | 11 ++- 13 files changed, 160 insertions(+), 152 deletions(-) create mode 100644 data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayCryptoCurrencyFactory.kt delete mode 100644 data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPaySwapDataFactory.kt create mode 100644 domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPayCryptoCurrencyFactory.kt rename domain/visa/src/main/kotlin/com/tangem/domain/pay/{TangemPaySwapDataFactory.kt => model/TangemPayTopUpData.kt} (51%) diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayCryptoCurrencyFactory.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayCryptoCurrencyFactory.kt new file mode 100644 index 0000000000..a768bf84b1 --- /dev/null +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayCryptoCurrencyFactory.kt @@ -0,0 +1,64 @@ +package com.tangem.data.pay + +import arrow.core.Either +import arrow.core.Either.Companion.catch +import com.squareup.moshi.Moshi +import com.tangem.blockchain.blockchains.ethereum.Chain +import com.tangem.blockchainsdk.utils.ExcludedBlockchains +import com.tangem.core.error.UniversalError +import com.tangem.data.common.currency.CryptoCurrencyFactory +import com.tangem.data.common.network.NetworkFactory +import com.tangem.data.pay.util.TangemPayErrorConverter +import com.tangem.datasource.di.NetworkMoshi +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.pay.TangemPayCryptoCurrencyFactory +import timber.log.Timber +import javax.inject.Inject + +private const val TAG = "TangemPay: DefaultTangemPayCryptoCurrencyFactory" +/** + * Custom token parameters. Will be used only for F&F. + */ +private const val TOKEN_ID = "usd-coin" +private const val TOKEN_NAME = "USDC" +private const val TOKEN_CONTRACT_ADDRESS = "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359" +private const val TOKEN_DECIMALS = 6 + +internal class DefaultTangemPayCryptoCurrencyFactory @Inject constructor( + @NetworkMoshi moshi: Moshi, + excludedBlockchains: ExcludedBlockchains, +) : TangemPayCryptoCurrencyFactory { + + private val cryptoCurrencyFactory by lazy(mode = LazyThreadSafetyMode.NONE) { + CryptoCurrencyFactory(excludedBlockchains) + } + private val networkFactory by lazy(mode = LazyThreadSafetyMode.NONE) { + NetworkFactory(excludedBlockchains) + } + + private val errorConverter by lazy(mode = LazyThreadSafetyMode.NONE) { TangemPayErrorConverter(moshi) } + + override fun create(userWallet: UserWallet, chainId: Int): Either { + return catch { + val chain = requireNotNull(Chain.entries.find { it.id == chainId }) { "Can not find chain with $chainId" } + val blockchain = requireNotNull(chain.blockchain) + val network = networkFactory.create( + blockchain = blockchain, + extraDerivationPath = null, + userWallet = userWallet, + ) + cryptoCurrencyFactory.createToken( + network = requireNotNull(network), + rawId = CryptoCurrency.RawID(TOKEN_ID), + name = TOKEN_NAME, + symbol = TOKEN_NAME, + contractAddress = TOKEN_CONTRACT_ADDRESS, + decimals = TOKEN_DECIMALS, + ) + }.mapLeft { exception -> + Timber.tag(TAG).e(exception) + errorConverter.convert(exception) + } + } +} \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPaySwapDataFactory.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPaySwapDataFactory.kt deleted file mode 100644 index 8533ae4744..0000000000 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPaySwapDataFactory.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.tangem.data.pay - -import arrow.core.Either -import arrow.core.Either.Companion.catch -import com.squareup.moshi.Moshi -import com.tangem.blockchain.blockchains.ethereum.Chain -import com.tangem.blockchainsdk.utils.ExcludedBlockchains -import com.tangem.core.error.UniversalError -import com.tangem.data.common.currency.CryptoCurrencyFactory -import com.tangem.data.common.network.NetworkFactory -import com.tangem.data.pay.util.TangemPayErrorConverter -import com.tangem.datasource.di.NetworkMoshi -import com.tangem.domain.models.ReceiveAddressModel -import com.tangem.domain.models.ReceiveAddressModel.NameService -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.pay.TangemPayTopUpData -import com.tangem.domain.pay.TangemPaySwapDataFactory -import timber.log.Timber -import java.math.BigDecimal -import javax.inject.Inject - -private const val TAG = "TangemPay: DefaultDataForTopUpFactory" -/** - * Custom token parameters. Will be used only for F&F. - */ -private const val TOKEN_ID = "usd-coin" -private const val TOKEN_NAME = "USDC" -private const val TOKEN_CONTRACT_ADDRESS = "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359" -private const val TOKEN_DECIMALS = 6 - -internal class DefaultTangemPaySwapDataFactory @Inject constructor( - @NetworkMoshi moshi: Moshi, - excludedBlockchains: ExcludedBlockchains, -) : TangemPaySwapDataFactory { - - private val cryptoCurrencyFactory by lazy(mode = LazyThreadSafetyMode.NONE) { - CryptoCurrencyFactory(excludedBlockchains) - } - private val networkFactory by lazy(mode = LazyThreadSafetyMode.NONE) { - NetworkFactory(excludedBlockchains) - } - private val errorConverter by lazy(mode = LazyThreadSafetyMode.NONE) { TangemPayErrorConverter(moshi) } - - private fun getCurrency(userWallet: UserWallet, chainId: Int): CryptoCurrency { - val chain = requireNotNull(Chain.entries.find { it.id == chainId }) { "Can not find chain with $chainId" } - val blockchain = requireNotNull(chain.blockchain) - val network = networkFactory.create( - blockchain = blockchain, - extraDerivationPath = null, - userWallet = userWallet, - ) - return cryptoCurrencyFactory.createToken( - network = requireNotNull(network), - rawId = CryptoCurrency.RawID(TOKEN_ID), - name = TOKEN_NAME, - symbol = TOKEN_NAME, - contractAddress = TOKEN_CONTRACT_ADDRESS, - decimals = TOKEN_DECIMALS, - ) - } - - override fun create( - userWallet: UserWallet, - depositAddress: String, - chainId: Int, - cryptoBalance: BigDecimal, - fiatBalance: BigDecimal, - ): Either { - return catch { - val currency = getCurrency(userWallet, chainId) - TangemPayTopUpData( - currency = currency, - walletId = userWallet.walletId, - cryptoBalance = cryptoBalance, - fiatBalance = fiatBalance, - depositAddress = depositAddress, - receiveAddress = listOf(ReceiveAddressModel(nameService = NameService.Default, value = depositAddress)), - ) - }.mapLeft { exception -> - Timber.tag(TAG).e(exception) - errorConverter.convert(exception) - } - } -} \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/di/TangemPayDataModule.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/di/TangemPayDataModule.kt index 49bc15d0db..bae2d97baf 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/di/TangemPayDataModule.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/di/TangemPayDataModule.kt @@ -1,10 +1,10 @@ package com.tangem.data.pay.di -import com.tangem.data.pay.DefaultTangemPaySwapDataFactory +import com.tangem.data.pay.DefaultTangemPayCryptoCurrencyFactory import com.tangem.data.pay.repository.* import com.tangem.data.pay.usecase.DefaultGetTangemPayCurrencyStatusUseCase import com.tangem.data.pay.usecase.DefaultTangemPayWithdrawUseCase -import com.tangem.domain.pay.TangemPaySwapDataFactory +import com.tangem.domain.pay.TangemPayCryptoCurrencyFactory import com.tangem.domain.pay.repository.* import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase @@ -48,7 +48,9 @@ internal interface TangemPayDataModule { @Binds @Singleton - fun bindTangemPaySwapDataFactory(factory: DefaultTangemPaySwapDataFactory): TangemPaySwapDataFactory + fun bindTangemPayCryptoCurrencyFactory( + factory: DefaultTangemPayCryptoCurrencyFactory, + ): TangemPayCryptoCurrencyFactory @Binds @Singleton diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt index 21077cd428..8af56ff827 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayCardDetailsRepository.kt @@ -55,6 +55,7 @@ internal class DefaultTangemPayCardDetailsRepository @Inject constructor( fiatBalance = result.fiat.availableBalance, currencyCode = result.fiat.currency, cryptoBalance = result.crypto.balance, + availableForWithdrawal = result.availableForWithdrawal.amount, chainId = result.crypto.chainId, depositAddress = result.crypto.depositAddress, contractAddress = result.crypto.tokenContractAddress, diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPayCryptoCurrencyFactory.kt b/domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPayCryptoCurrencyFactory.kt new file mode 100644 index 0000000000..5f3223e514 --- /dev/null +++ b/domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPayCryptoCurrencyFactory.kt @@ -0,0 +1,11 @@ +package com.tangem.domain.pay + +import arrow.core.Either +import com.tangem.core.error.UniversalError +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.wallet.UserWallet + +interface TangemPayCryptoCurrencyFactory { + + fun create(userWallet: UserWallet, chainId: Int): Either +} \ No newline at end of file diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayCardBalance.kt b/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayCardBalance.kt index 90d3375e9c..911aead866 100644 --- a/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayCardBalance.kt +++ b/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayCardBalance.kt @@ -6,6 +6,7 @@ data class TangemPayCardBalance( val fiatBalance: BigDecimal, val currencyCode: String, val cryptoBalance: BigDecimal, + val availableForWithdrawal: BigDecimal, val chainId: Int, val depositAddress: String?, val contractAddress: String, diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPaySwapDataFactory.kt b/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayTopUpData.kt similarity index 51% rename from domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPaySwapDataFactory.kt rename to domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayTopUpData.kt index c23f9becab..3d40efda8e 100644 --- a/domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPaySwapDataFactory.kt +++ b/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayTopUpData.kt @@ -1,24 +1,10 @@ -package com.tangem.domain.pay +package com.tangem.domain.pay.model -import arrow.core.Either -import com.tangem.core.error.UniversalError import com.tangem.domain.models.ReceiveAddressModel import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import java.math.BigDecimal -interface TangemPaySwapDataFactory { - - fun create( - userWallet: UserWallet, - depositAddress: String, - chainId: Int, - cryptoBalance: BigDecimal, - fiatBalance: BigDecimal, - ): Either -} - data class TangemPayTopUpData( val walletId: UserWalletId, val currency: CryptoCurrency, diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayAddFundsComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayAddFundsComponent.kt index db43708e08..7058acc0a1 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayAddFundsComponent.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayAddFundsComponent.kt @@ -5,7 +5,7 @@ import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.decompose.ComposableBottomSheetComponent import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.pay.TangemPayTopUpData +import com.tangem.domain.pay.model.TangemPayTopUpData import com.tangem.features.tangempay.model.TangemPayAddFundsModel import com.tangem.features.tangempay.ui.TangemPayAddFundsContent import java.math.BigDecimal diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayAddFundsModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayAddFundsModel.kt index 4f2ae1c371..b1a7a7133a 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayAddFundsModel.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayAddFundsModel.kt @@ -4,7 +4,10 @@ import androidx.compose.runtime.Stable import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer -import com.tangem.domain.pay.TangemPaySwapDataFactory +import com.tangem.domain.models.ReceiveAddressModel +import com.tangem.domain.models.ReceiveAddressModel.NameService +import com.tangem.domain.pay.TangemPayCryptoCurrencyFactory +import com.tangem.domain.pay.model.TangemPayTopUpData import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.tangempay.components.TangemPayAddFundsComponent import com.tangem.features.tangempay.entity.TangemPayAddFundsUM @@ -17,7 +20,7 @@ import javax.inject.Inject internal class TangemPayAddFundsModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, - private val tangemPaySwapDataFactory: TangemPaySwapDataFactory, + private val tangemPayCryptoCurrencyFactory: TangemPayCryptoCurrencyFactory, private val getUserWalletUseCase: GetUserWalletUseCase, ) : Model() { @@ -26,17 +29,25 @@ internal class TangemPayAddFundsModel @Inject constructor( val uiState: TangemPayAddFundsUM = getInitialState() private fun getInitialState(): TangemPayAddFundsUM { - val userWallet = requireNotNull( - getUserWalletUseCase(params.walletId).getOrNull(), - ) { "User wallet not found for id: ${params.walletId}" } - val data = tangemPaySwapDataFactory.create( - userWallet = userWallet, - depositAddress = params.depositAddress, - chainId = params.chainId, - cryptoBalance = params.cryptoBalance, - fiatBalance = params.fiatBalance, - ).getOrNull() - + val userWallet = getUserWalletUseCase(params.walletId).getOrNull() + val currency = userWallet?.let { + tangemPayCryptoCurrencyFactory.create(userWallet = userWallet, chainId = params.chainId).getOrNull() + } + val data = currency?.let { + TangemPayTopUpData( + currency = currency, + walletId = params.walletId, + cryptoBalance = params.cryptoBalance, + fiatBalance = params.fiatBalance, + depositAddress = params.depositAddress, + receiveAddress = listOf( + ReceiveAddressModel( + nameService = NameService.Default, + value = params.depositAddress, + ), + ), + ) + } return TangemPayAddFundsUMConverter(listener = params.listener).convert(data) } diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt index bfe48f97c9..3a08e43adf 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt @@ -18,8 +18,8 @@ import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.message.SnackbarMessage import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.models.TokenReceiveConfig -import com.tangem.domain.pay.TangemPaySwapDataFactory -import com.tangem.domain.pay.TangemPayTopUpData +import com.tangem.domain.pay.TangemPayCryptoCurrencyFactory +import com.tangem.domain.pay.model.TangemPayTopUpData import com.tangem.domain.pay.model.TangemPayCardBalance import com.tangem.domain.pay.repository.CustomerOrderRepository import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository @@ -70,7 +70,7 @@ internal class TangemPayDetailsModel @Inject constructor( private val uiMessageSender: UiMessageSender, private val cardDetailsEventListener: CardDetailsEventListener, private val txHistoryUpdateListener: TangemPayTxHistoryUpdateListener, - private val tangemPaySwapDataFactory: TangemPaySwapDataFactory, + private val tangemPayCryptoCurrencyFactory: TangemPayCryptoCurrencyFactory, private val orderRepository: CustomerOrderRepository, private val getUserWalletUseCase: GetUserWalletUseCase, ) : Model(), TangemPayTxHistoryUiActions, TangemPayDetailIntents, AddFundsListener { @@ -236,27 +236,22 @@ internal class TangemPayDetailsModel @Inject constructor( if (hasActiveWithdrawal) { showBottomSheetError(TangemPayDetailsErrorType.WithdrawInProgress) } else { - val userWallet = requireNotNull( - getUserWalletUseCase(params.userWalletId).getOrNull(), - ) { "User wallet not found: ${params.userWalletId}" } - val data = tangemPaySwapDataFactory.create( - userWallet = userWallet, - depositAddress = depositAddress, - chainId = params.config.chainId, - cryptoBalance = currentBalance.cryptoBalance, - fiatBalance = currentBalance.fiatBalance, - ).getOrNull() - if (data != null) { + val userWallet = getUserWalletUseCase(params.userWalletId).getOrNull() + val currency = userWallet?.let { + tangemPayCryptoCurrencyFactory.create(userWallet = userWallet, chainId = params.config.chainId) + .getOrNull() + } + if (currency != null) { router.push( AppRoute.Swap( - currencyFrom = data.currency, - userWalletId = data.walletId, + currencyFrom = currency, + userWalletId = params.userWalletId, isInitialReverseOrder = false, screenSource = AnalyticsParam.ScreensSources.TangemPay.value, tangemPayInput = AppRoute.Swap.TangemPayInput( - cryptoAmount = data.cryptoBalance, - fiatAmount = data.fiatBalance, - depositAddress = data.depositAddress, + cryptoAmount = currentBalance.availableForWithdrawal, + fiatAmount = currentBalance.availableForWithdrawal, + depositAddress = depositAddress, isWithdrawal = true, ), ), @@ -277,7 +272,13 @@ internal class TangemPayDetailsModel @Inject constructor( Timber.e(e) return@launch } - uiState.update(DetailsBalanceTransformer(balance = result)) + uiState.update( + transformer = DetailsBalanceTransformer( + balance = result, + userWallet = getUserWalletUseCase(params.userWalletId).getOrNull(), + cryptoCurrencyFactory = tangemPayCryptoCurrencyFactory, + ), + ) }.saveIn(fetchBalanceJobHolder) } diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsBalanceTransformer.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsBalanceTransformer.kt index 7817286e55..857920d456 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsBalanceTransformer.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/DetailsBalanceTransformer.kt @@ -2,17 +2,24 @@ package com.tangem.features.tangempay.model.transformers import arrow.core.Either import com.tangem.core.error.UniversalError +import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.format +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.pay.TangemPayCryptoCurrencyFactory import com.tangem.domain.pay.model.TangemPayCardBalance import com.tangem.features.tangempay.entity.TangemPayDetailsBalanceBlockState import com.tangem.features.tangempay.entity.TangemPayDetailsUM import com.tangem.utils.transformer.Transformer import kotlinx.collections.immutable.persistentListOf +import java.math.BigDecimal import java.util.Currency internal class DetailsBalanceTransformer( private val balance: Either, + private val cryptoCurrencyFactory: TangemPayCryptoCurrencyFactory, + private val userWallet: UserWallet?, ) : Transformer { override fun transform(prevState: TangemPayDetailsUM): TangemPayDetailsUM { @@ -21,22 +28,32 @@ internal class DetailsBalanceTransformer( TangemPayDetailsBalanceBlockState.Error(actionButtons = persistentListOf()) } is Either.Right -> { - TangemPayDetailsBalanceBlockState.Content( - isBalanceFlickering = false, - fiatBalance = getBalanceText(balance.value), - // TODO [REDACTED_TASK_KEY]: Add crypto balance when the BFF is ready - cryptoBalance = "", - actionButtons = prevState.balanceBlockState.actionButtons, - ) + val cryptoCurrency = userWallet?.let { + cryptoCurrencyFactory.create(userWallet, balance.value.chainId).getOrNull() + } + if (cryptoCurrency == null) { + TangemPayDetailsBalanceBlockState.Error(actionButtons = persistentListOf()) + } else { + TangemPayDetailsBalanceBlockState.Content( + isBalanceFlickering = false, + fiatBalance = getFiatBalanceText(balance.value), + cryptoBalance = getCryptoBalanceText(balance.value.cryptoBalance, cryptoCurrency), + actionButtons = prevState.balanceBlockState.actionButtons, + ) + } } } return prevState.copy(balanceBlockState = balance) } - private fun getBalanceText(balance: TangemPayCardBalance): String { + private fun getFiatBalanceText(balance: TangemPayCardBalance): String { val currency = Currency.getInstance(balance.currencyCode) return balance.fiatBalance.format { fiat(fiatCurrencyCode = currency.currencyCode, fiatCurrencySymbol = currency.symbol) } } + + private fun getCryptoBalanceText(cryptoBalance: BigDecimal, cryptoCurrency: CryptoCurrency): String { + return cryptoBalance.format { crypto(cryptoCurrency = cryptoCurrency) } + } } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayAddFundsUMConverter.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayAddFundsUMConverter.kt index b770bcc649..4de43025ef 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayAddFundsUMConverter.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayAddFundsUMConverter.kt @@ -1,7 +1,7 @@ package com.tangem.features.tangempay.model.transformers import com.tangem.core.ui.extensions.TextReference -import com.tangem.domain.pay.TangemPayTopUpData +import com.tangem.domain.pay.model.TangemPayTopUpData import com.tangem.features.tangempay.components.AddFundsListener import com.tangem.features.tangempay.details.impl.R import com.tangem.features.tangempay.entity.TangemPayAddFundsItemUM diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt index e59ab905cb..6c0a7fdf77 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt @@ -157,12 +157,11 @@ internal fun TangemPayDetailsBalanceBlock( state = state, isBalanceHidden = isBalanceHidden, ) - // TODO [REDACTED_TASK_KEY]: Uncomment after adding crypto balance when the BFF is ready - // CryptoBalance( - // modifier = Modifier.padding(start = 12.dp, top = 4.dp), - // state = state, - // isBalanceHidden = isBalanceHidden, - // ) + CryptoBalance( + modifier = Modifier.padding(start = 12.dp, top = 4.dp), + state = state, + isBalanceHidden = isBalanceHidden, + ) if (state.actionButtons.isNotEmpty()) { HorizontalActionChips( modifier = Modifier.padding(top = 12.dp), From 3c109eb736fcbdb0ac849899a1e485bf78f9e682 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 9 Dec 2025 15:21:58 +0300 Subject: [PATCH 02/11] Updated on 2026-08-14 --- .../src/main/assets/configs/feature_toggles_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json index 1d456f1591..03e0a8cfd3 100644 --- a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json @@ -49,7 +49,7 @@ }, { "name": "NEW_ONRAMP_MAIN_ENABLED", - "version": "undefined" + "version": "5.31.0" }, { "name": "ACCOUNTS_FEATURE_ENABLED", From e2f9d50499a4c0900fd2d658b398434dc1962846 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 9 Dec 2025 20:50:03 +0500 Subject: [PATCH 03/11] Updated on 2026-08-14 --- .../com/tangem/screens/DetailsPageObject.kt | 2 +- core/res/src/main/res/values/strings.xml | 3 + .../res/drawable/img_visa_label_26_16.xml | 17 ------ .../res/drawable/img_visa_notification.webp | Bin 0 -> 2500 bytes .../feedback/models/FeedbackEmailType.kt | 2 + .../domain/feedback/FeedbackDataBuilder.kt | 4 ++ .../feedback/SendFeedbackEmailUseCase.kt | 1 + .../utils/EmailMessageBodyResolver.kt | 10 ++++ .../utils/EmailMessageTitleResolver.kt | 3 +- .../feedback/utils/EmailSubjectResolver.kt | 5 +- .../features/details/utils/ItemsBuilder.kt | 2 +- .../entity/TangemPayDetailsStateFactory.kt | 13 +++++ .../tangempay/entity/TangemPayDetailsUM.kt | 2 + .../tangempay/model/TangemPayDetailsModel.kt | 16 +++++- .../tangempay/ui/TangemPayDetailsScreen.kt | 52 +++++++++++++++--- .../tangempay/utils/TangemPayDetailIntents.kt | 1 + .../model/intents/TangemPayClickIntents.kt | 2 +- .../wallet/state/model/WalletNotification.kt | 2 +- 18 files changed, 105 insertions(+), 32 deletions(-) delete mode 100644 core/ui/src/main/res/drawable/img_visa_label_26_16.xml create mode 100644 core/ui/src/main/res/drawable/img_visa_notification.webp diff --git a/app/src/androidTest/kotlin/com/tangem/screens/DetailsPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/DetailsPageObject.kt index 62b73d6c4b..863e387a71 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/DetailsPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/DetailsPageObject.kt @@ -44,7 +44,7 @@ class DetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : } val contactSupportButton: KNode = child { hasTestTag(DetailsScreenTestTags.SCREEN_ITEM) - hasText(getResourceString(R.string.details_row_title_contact_to_support)) + hasText(getResourceString(R.string.common_contact_support)) } val toSButton: KNode = child { hasTestTag(DetailsScreenTestTags.SCREEN_ITEM) diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index deea678229..7f0604d2d7 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -244,6 +244,7 @@ Coming soon Confirm Connecting + Contact support Contact Tangem Support Contact Visa Support Continue @@ -1382,6 +1383,8 @@ You receive Choose token not available + We would be happy to receive your feedback + Tangem Pay is now in beta Card frozen Card payment Deposit diff --git a/core/ui/src/main/res/drawable/img_visa_label_26_16.xml b/core/ui/src/main/res/drawable/img_visa_label_26_16.xml deleted file mode 100644 index c5859a2fda..0000000000 --- a/core/ui/src/main/res/drawable/img_visa_label_26_16.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - diff --git a/core/ui/src/main/res/drawable/img_visa_notification.webp b/core/ui/src/main/res/drawable/img_visa_notification.webp new file mode 100644 index 0000000000000000000000000000000000000000..b0b4afb8b65e4b4c7c19b83757fff925a66d1564 GIT binary patch literal 2500 zcmV;#2|M;uNk&Gz2><|BMM6+kP&il$0000G0001w0055w06|PpNIU}o00E$0Yj4~} z!y&1mO`C_32Qp1mkPg(H-9S=E3W*DusX!IX;tiqze#@_jm;hL{=|UV1W6pFpXT%`} zZ$M)c5*A`Fm^Mxmvq_mM9EXij!R(PL#^8iATcqkS2 zkpx61hdYpvgA*bak~2!+Gl`nr+DsyG3o7;4+Dx zU3Fa{;ZI#Fq>JhC{_{Ny+W)#$+BNO}JnYKJd*Qs2LV zY;PaepT7j1ua}7pU+}~{U4IGuIWducZeY61zeJudO!$-|-j82mfAEldX5hK}68ypw zpUEuKEZID%44+m_he3@wpvjxCV^z)?$(0ob-h07z|-0I)3(ptQva47CLr-x^(LjSyQS z_N~!lYaE(m%&n2zgIZ(3|8M2i$n9}#4gB65eQWfwHDYLu@U1nxX$=FVElvQ~76_2q zA_0W9*Z`QeumF%-Vgvw4Ez#d>TViu#TEg4_^8A!;=0Ui-=ebJv#S`uso_FcaJoX+S z%bRo)3&O)K3teUVB-ZfA6qae0Y@S#$JQ-Q&EZLb@`)4ch6kkrGwgSmMvST-yS6!Evz!hm0+#=B2(GHdTo|y zw6N+ZPcpD_n`Ox!1dM`|2r}AUih~6)ElPkMMD@5f^dPS9*MuHKwtZeli5BDzSRZZ- z$ZiAHgnI)Tnr(lqA*ZbYMeR0W;VYPe0ga6haX`%ZUe3qE5JP8R)mBhAAX)|h05Bi` zodGJ40FVGakwBeFrK7*0rdJ9(@Dd4XZs5SJd;$0Yo&f>@_yK4XXZ-89bB=az%Km)q z_3#Hsd8+hx;dQj{X_kK|Ng)aK;PCs zRiFEw#J{^=yT1T`uOI*a|MmcNMrZx@Wi`OPAWYtv;`q(WlkAH`SdGx=qlw;~lgU4U zOQZU_QIzI{#MtmFix*FmP^cCQ8QmdUm; zT0hetp5o-KBA2iSZVgMwRXqyb%BPT6`M~~;WCh6$=5{xXUI#aW_pn=Xjjr_HNFKEm z?Ct;n{@h4M{>niQ00lsu4?VB=k;@OSq$xycwX8} zToUdk3JbMXFnbP04aX9MOI&Av;}00M)MqObpY7mu(oA`Gt53(HTI3a_tA#j7+RM;5 zKFMNlYr4b--A@Ex{=J}wCv;+652pv$kHnc`_D2ja^gQ8Q30pJ&S30b(%Q1Z9xPnjn zpNZqVK>UIw?f#27yO2ls3b1lf8~_8~l@$BCKtsYOlMY8=I({%h=*T`^mKRL3(8^YwpeY_J7q>y&LgT&?=nj?k6WA7oQp51d;=Ha+=cBWk-~If^*kmh@!z+ z4_LwktU8?cNAU*KGD;cN`|r9{ zUp!DPLXy$_BYLm{Gy8B$mCKmS3oKi_r(e0y3}?j+Bi_99PGlcF$L4bTZfjXhKSD`< zz#mVJt1@D<18FmPcxHERs0$EUk9Ik$tILtfqhmNMImsvyg`!#%@i!xJE~c278p#dV z`l;^ek;}^745j(YiuFc%)N4!`RB;SdZwLTmgcO@E6d=DJzZAge)t>%h!nr%;n3Z;! z8}%52l27f$<2}&pMEthFUBqe^p{QhsR>6!s2=W_!r6zMj>%G1k?`HJ+RP2tNXH1wx zlQwzLt>kAJufC+Q_bT!_2z<*`H{%9kV+iV&7G>t+?1-#8xKMkH-@(1)08p~M zTW$tBQ|0^MjEi4W0rXMXHUXgu3vgow%bi-P90KhgMW?@i(u&O382x`D!Ob#q)6sC>Ui_%?J>k|$K!YGJ_(MvG^ne3< z$501hY(brv!0xo1+;ys}d<|8sKi>D_?3MgmYc;YR< this is FeedbackEmailType.DirectUserRequest, is FeedbackEmailType.RateCanBeBetter, diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt index 12bd80d66a..c8a13a4ef7 100644 --- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt +++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt @@ -38,6 +38,7 @@ internal class EmailMessageBodyResolver( is FeedbackEmailType.Visa.Dispute -> addVisaRequestBody(type.walletMetaInfo, type.visaTxDetails) is FeedbackEmailType.Visa.DisputeV2 -> addTangemPayRequestBody(type.walletMetaInfo, type.item) is FeedbackEmailType.Visa.Withdrawal -> addTangemPayWithdrawalRequestBody(type) + is FeedbackEmailType.Visa.FeatureIsBeta -> addTangemPayBetaRequestBody(type.walletMetaInfo) } return build() @@ -52,6 +53,15 @@ internal class EmailMessageBodyResolver( addTangemPayTxInfo(item) } + private fun FeedbackDataBuilder.addTangemPayBetaRequestBody(walletMetaInfo: WalletMetaInfo) { + addPhoneInfoBody() + addDelimiter() + walletMetaInfo.userWalletId?.let { userWalletId -> + addUserWalletId(userWalletId = userWalletId.stringValue) + addDelimiter() + } + } + private suspend fun FeedbackDataBuilder.addTangemPayWithdrawalRequestBody( type: FeedbackEmailType.Visa.Withdrawal, ) { diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt index 7d42928a99..36940c948e 100644 --- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt +++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt @@ -26,6 +26,8 @@ internal class EmailMessageTitleResolver(private val resources: Resources) { is FeedbackEmailType.Visa.DisputeV2, is FeedbackEmailType.Visa.FailedIssueCard, is FeedbackEmailType.Visa.Withdrawal, + is FeedbackEmailType.Visa.FeatureIsBeta, + is FeedbackEmailType.PreActivatedWallet, -> R.string.feedback_preface_support is FeedbackEmailType.RateCanBeBetter -> R.string.feedback_preface_rate_negative is FeedbackEmailType.ScanningProblem -> R.string.feedback_preface_scan_failed @@ -33,7 +35,6 @@ internal class EmailMessageTitleResolver(private val resources: Resources) { is FeedbackEmailType.StakingProblem, is FeedbackEmailType.SwapProblem, -> R.string.feedback_preface_tx_failed - is FeedbackEmailType.PreActivatedWallet -> R.string.feedback_preface_support } return resources.getStringSafe(resId) diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt index 6e01c9989f..4b1e4f9799 100644 --- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt +++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt @@ -15,6 +15,7 @@ import com.tangem.domain.feedback.models.FeedbackEmailType internal class EmailSubjectResolver(private val resources: Resources) { /** Resolve email message body by [type] */ + @Suppress("CyclomaticComplexMethod") fun resolve(type: FeedbackEmailType): String { return when (type) { is FeedbackEmailType.DirectUserRequest -> { @@ -43,8 +44,8 @@ internal class EmailSubjectResolver(private val resources: Resources) { is FeedbackEmailType.Visa.Dispute, is FeedbackEmailType.Visa.DisputeV2, -> "[Visa] [DISPUTE] {auto-filled subject}" - is FeedbackEmailType.Visa.Withdrawal, - -> "[Visa] [WITHDRAWAL] {auto-filled subject}" + is FeedbackEmailType.Visa.Withdrawal -> "[Visa] [WITHDRAWAL] {auto-filled subject}" + is FeedbackEmailType.Visa.FeatureIsBeta -> "[VISA] [FEEDBACK]" } } } \ No newline at end of file diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt index ebabf476c2..617de52a47 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt @@ -87,7 +87,7 @@ internal class ItemsBuilder @Inject constructor(private val router: Router) { DetailsItemUM.Basic.Item( id = "support_email", block = BlockUM( - text = resourceReference(R.string.details_row_title_contact_to_support), + text = resourceReference(R.string.common_contact_support), iconRes = R.drawable.ic_comment_24, onClick = onSupportEmailClick, ), diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt index 0036f7c5ba..9853165dad 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt @@ -1,8 +1,10 @@ package com.tangem.features.tangempay.entity +import androidx.compose.ui.unit.dp import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig import com.tangem.core.ui.components.dropdownmenu.TangemDropdownMenuItem +import com.tangem.core.ui.components.notifications.NotificationConfig import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.themedColor import com.tangem.core.ui.res.TangemTheme @@ -21,6 +23,7 @@ internal class TangemPayDetailsStateFactory( private val converter: TangemPayCardFrozenStateConverter, ) { + @Suppress("LongMethod") fun getInitialState(): TangemPayDetailsUM { val cardFrozenStateItem = when (cardFrozenState) { is TangemPayCardFrozenState.Pending -> null @@ -88,6 +91,16 @@ internal class TangemPayDetailsStateFactory( isBalanceHidden = false, addFundsEnabled = true, cardFrozenState = converter.convert(cardFrozenState), + betaNotificationConfig = NotificationConfig( + title = resourceReference(R.string.tangem_pay_beta_notification_title), + subtitle = resourceReference(R.string.tangem_pay_beta_notification_subtitle), + iconResId = R.drawable.img_visa_notification, + buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig( + text = resourceReference(R.string.common_contact_support), + onClick = intents::onContactSupportClicked, + ), + iconSize = 36.dp, + ), ) } } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt index 6faa4a89ea..a8b31086f1 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt @@ -2,6 +2,7 @@ package com.tangem.features.tangempay.entity import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig +import com.tangem.core.ui.components.notifications.NotificationConfig import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.visa.model.TangemPayCardFrozenState import kotlinx.collections.immutable.ImmutableList @@ -14,6 +15,7 @@ internal data class TangemPayDetailsUM( val isBalanceHidden: Boolean, val addFundsEnabled: Boolean, val cardFrozenState: CardFrozenState, + val betaNotificationConfig: NotificationConfig, ) internal data class TangemPayCardDetailsUM( diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt index 3a08e43adf..78c4c843c6 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt @@ -17,10 +17,13 @@ import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfi import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.message.SnackbarMessage import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase +import com.tangem.domain.feedback.SendFeedbackEmailUseCase +import com.tangem.domain.feedback.models.FeedbackEmailType +import com.tangem.domain.feedback.models.WalletMetaInfo import com.tangem.domain.models.TokenReceiveConfig import com.tangem.domain.pay.TangemPayCryptoCurrencyFactory -import com.tangem.domain.pay.model.TangemPayTopUpData import com.tangem.domain.pay.model.TangemPayCardBalance +import com.tangem.domain.pay.model.TangemPayTopUpData import com.tangem.domain.pay.repository.CustomerOrderRepository import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository import com.tangem.domain.tangempay.TangemPayAnalyticsEvents @@ -73,6 +76,7 @@ internal class TangemPayDetailsModel @Inject constructor( private val tangemPayCryptoCurrencyFactory: TangemPayCryptoCurrencyFactory, private val orderRepository: CustomerOrderRepository, private val getUserWalletUseCase: GetUserWalletUseCase, + private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, ) : Model(), TangemPayTxHistoryUiActions, TangemPayDetailIntents, AddFundsListener { private val params: TangemPayDetailsContainerComponent.Params = paramsContainer.require() @@ -306,6 +310,16 @@ internal class TangemPayDetailsModel @Inject constructor( }.saveIn(addToWalletBannerJobHolder) } + override fun onContactSupportClicked() { + modelScope.launch { + sendFeedbackEmailUseCase.invoke( + type = FeedbackEmailType.Visa.FeatureIsBeta( + walletMetaInfo = WalletMetaInfo(userWalletId = params.userWalletId), + ), + ) + } + } + override fun onRefreshSwipe(refreshState: ShowRefreshState) { modelScope.launch { uiState.update(TangemPayDetailsRefreshTransformer(isRefreshing = refreshState.value)) diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt index 6c0a7fdf77..6addbcf3d6 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt @@ -31,11 +31,10 @@ import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfi import com.tangem.core.ui.components.containers.pullToRefresh.TangemPullToRefreshContainer import com.tangem.core.ui.components.dropdownmenu.TangemDropdownItem import com.tangem.core.ui.components.dropdownmenu.TangemDropdownMenu +import com.tangem.core.ui.components.notifications.Notification +import com.tangem.core.ui.components.notifications.NotificationConfig import com.tangem.core.ui.components.text.applyBladeBrush -import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.extensions.orMaskWithStars -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.extensions.* import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.test.TokenDetailsTopBarTestTags @@ -81,7 +80,9 @@ internal fun TangemPayDetailsScreen( ) { item(TangemPayCardDetailsUM::class.java) { cardDetailsBlockComponent.CardDetailsBlockContent( - modifier = Modifier.padding(horizontal = 16.dp).padding(top = 8.dp), + modifier = Modifier + .padding(horizontal = 16.dp) + .padding(top = 8.dp), state = cardDetailsState, ) } @@ -116,7 +117,7 @@ internal fun TangemPayDetailsScreen( key = TangemPayDetailsBalanceBlockState::class.java, content = { TangemPayDetailsBalanceBlock( - modifier = modifier + modifier = Modifier .padding(horizontal = TangemTheme.dimens.spacing16) .padding(top = 12.dp) .fillMaxWidth(), @@ -125,15 +126,32 @@ internal fun TangemPayDetailsScreen( ) }, ) + item( + key = "TANGEM_PAY_IS_IN_BETA", + content = { + TangemPayBetaBlock( + modifier = modifier + .padding(horizontal = TangemTheme.dimens.spacing16) + .padding(top = 12.dp) + .fillMaxWidth(), + config = state.betaNotificationConfig, + ) + }, + ) with(txHistoryComponent) { txHistoryContent(listState = listState, state = txHistoryState) } } } } } +@Composable +private fun TangemPayBetaBlock(config: NotificationConfig, modifier: Modifier = Modifier) { + Notification(modifier = modifier, config = config) +} + // region Balance block @Composable -internal fun TangemPayDetailsBalanceBlock( +private fun TangemPayDetailsBalanceBlock( state: TangemPayDetailsBalanceBlockState, isBalanceHidden: Boolean, modifier: Modifier = Modifier, @@ -335,6 +353,16 @@ private class TangemPayDetailsUMProvider : CollectionPreviewParameterProvider Date: Wed, 10 Dec 2025 15:46:19 +0500 Subject: [PATCH 04/11] Updated on 2026-08-14 --- .../common/ui/navigationButtons/NavigationButtonsBlock.kt | 6 ++++-- .../com/tangem/common/ui/navigationButtons/NavigationUM.kt | 1 + .../features/send/v2/send/confirm/model/SendConfirmModel.kt | 1 + .../send/v2/send/success/model/SendConfirmSuccessModel.kt | 1 + .../send/v2/sendnft/confirm/model/NFTSendConfirmModel.kt | 3 ++- .../send/v2/sendnft/success/model/NFTSendSuccessModel.kt | 1 + .../send/v2/subcomponents/amount/model/SendAmountModel.kt | 1 + .../subcomponents/destination/model/SendDestinationModel.kt | 2 ++ .../features/swap/v2/impl/amount/model/SwapAmountModel.kt | 1 + .../sendviaswap/confirm/model/SendWithSwapConfirmModel.kt | 1 + .../sendviaswap/success/model/SendWithSwapSuccessModel.kt | 2 ++ .../sendviaswap/success/ui/SendWithSwapSuccessContent.kt | 2 ++ 12 files changed, 19 insertions(+), 3 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsBlock.kt b/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsBlock.kt index 47233d7291..1941c34ff9 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsBlock.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsBlock.kt @@ -35,8 +35,8 @@ import com.tangem.core.ui.extensions.isNullOrEmpty import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview -import com.tangem.core.ui.utils.singleEvent import com.tangem.core.ui.test.SendScreenTestTags +import com.tangem.core.ui.utils.singleEvent @Composable fun NavigationButtonsBlock( @@ -78,7 +78,9 @@ fun NavigationButtonsBlockV2( horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12), ) { PreviousButton(navigationUM?.prevButton) - NavigationPrimaryButton(navigationUM?.primaryButton, modifier = Modifier.weight(1f)) + key(navigationUM?.source) { + NavigationPrimaryButton(navigationUM?.primaryButton, modifier = Modifier.weight(1f)) + } } } } diff --git a/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationUM.kt b/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationUM.kt index dcde9ac935..dc1953b1d9 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationUM.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationUM.kt @@ -7,6 +7,7 @@ import com.tangem.core.ui.extensions.TextReference @Immutable sealed class NavigationUM { data class Content( + val source: String, val title: TextReference, val subtitle: TextReference?, @DrawableRes val backIconRes: Int, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt index 0fb799cf17..5c00ee1e19 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt @@ -523,6 +523,7 @@ internal class SendConfirmModel @Inject constructor( params.callback.onResult( state.copy( navigationUM = NavigationUM.Content( + source = CommonSendRoute.Confirm.javaClass.simpleName, title = resourceReference(id = R.string.common_send), subtitle = null, backIconRes = when (confirmUM) { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/success/model/SendConfirmSuccessModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/success/model/SendConfirmSuccessModel.kt index 0d6a56bba6..29d2b390d8 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/success/model/SendConfirmSuccessModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/success/model/SendConfirmSuccessModel.kt @@ -52,6 +52,7 @@ internal class SendConfirmSuccessModel @Inject constructor( params.callback.onResult( state.copy( navigationUM = NavigationUM.Content( + source = CommonSendRoute.ConfirmSuccess.javaClass.simpleName, title = stringReference(""), subtitle = null, backIconRes = R.drawable.ic_close_24, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/NFTSendConfirmModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/NFTSendConfirmModel.kt index aab81e8c77..1c7c92bc7e 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/NFTSendConfirmModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/model/NFTSendConfirmModel.kt @@ -371,11 +371,12 @@ internal class NFTSendConfirmModel @Inject constructor( flow = uiState, flow2 = params.currentRoute, transform = { state, route -> state to route }, - ).onEach { (state, _) -> + ).onEach { (state, route) -> val confirmUM = state.confirmUM params.callback.onResult( state.copy( navigationUM = NavigationUM.Content( + source = CommonSendRoute.Confirm.javaClass.simpleName, title = resourceReference(R.string.nft_send), subtitle = null, backIconRes = when (confirmUM) { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/success/model/NFTSendSuccessModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/success/model/NFTSendSuccessModel.kt index 7fc3951005..92c860fb82 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/success/model/NFTSendSuccessModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/success/model/NFTSendSuccessModel.kt @@ -50,6 +50,7 @@ internal class NFTSendSuccessModel @Inject constructor( params.callback.onResult( state.copy( navigationUM = NavigationUM.Content( + source = CommonSendRoute.ConfirmSuccess.javaClass.simpleName, title = stringReference(""), subtitle = null, backIconRes = R.drawable.ic_close_24, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt index 7926083e2e..9be514d748 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt @@ -378,6 +378,7 @@ internal class SendAmountModel @Inject constructor( setSendWithSwapAvailability() params.callback.onNavigationResult( NavigationUM.Content( + source = CommonSendRoute.Amount::class.java.simpleName, title = resourceReference(R.string.send_amount_label), subtitle = null, backIconRes = if (route.isEditMode) { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt index becc704e91..5870afd0fb 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt @@ -35,6 +35,7 @@ import com.tangem.features.send.v2.api.entity.PredefinedValues import com.tangem.features.send.v2.api.subcomponents.destination.SendDestinationComponentParams import com.tangem.features.send.v2.api.subcomponents.destination.SendDestinationComponentParams.DestinationBlockParams import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationUM +import com.tangem.features.send.v2.common.CommonSendRoute import com.tangem.features.send.v2.impl.R import com.tangem.features.send.v2.subcomponents.destination.analytics.EnterAddressSource import com.tangem.features.send.v2.subcomponents.destination.analytics.SendDestinationAnalyticEvents @@ -359,6 +360,7 @@ internal class SendDestinationModel @Inject constructor( ).onEach { (state, route) -> params.callback.onNavigationResult( NavigationUM.Content( + source = CommonSendRoute.Destination::class.java.simpleName, title = params.title, subtitle = null, backIconRes = if (route.isEditMode) { diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt index 70fe7d5312..da46d20b3f 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt @@ -720,6 +720,7 @@ internal class SwapAmountModel @Inject constructor( ).filter { (_, route) -> route is SendWithSwapRoute.Amount }.onEach { (state, route) -> params.callback.onNavigationResult( NavigationUM.Content( + source = SendWithSwapRoute.Amount::class.java.simpleName, title = resourceReference(R.string.common_amount), subtitle = null, backIconRes = if (route.isEditMode) { diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt index 8d04b3d804..c0d119b50f 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt @@ -428,6 +428,7 @@ internal class SendWithSwapConfirmModel @Inject constructor( route = SendWithSwapRoute.Confirm, sendWithSwapUM = state.copy( navigationUM = NavigationUM.Content( + source = SendWithSwapRoute.Confirm.javaClass.simpleName, title = resourceReference(id = R.string.send_with_swap_confirm_title), subtitle = null, backIconRes = R.drawable.ic_back_24, diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/model/SendWithSwapSuccessModel.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/model/SendWithSwapSuccessModel.kt index 33909f7563..6b743b5db5 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/model/SendWithSwapSuccessModel.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/model/SendWithSwapSuccessModel.kt @@ -12,6 +12,7 @@ import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.features.swap.v2.impl.R import com.tangem.features.swap.v2.impl.common.entity.ConfirmUM +import com.tangem.features.swap.v2.impl.sendviaswap.SendWithSwapRoute import com.tangem.features.swap.v2.impl.sendviaswap.entity.SendWithSwapUM import com.tangem.features.swap.v2.impl.sendviaswap.success.SendWithSwapSuccessComponent import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -40,6 +41,7 @@ internal class SendWithSwapSuccessModel @Inject constructor( private fun configConfirmSuccessNavigation() { params.callback.onNavigationResult( NavigationUM.Content( + source = SendWithSwapRoute.Success.javaClass.simpleName, title = TextReference.EMPTY, subtitle = null, backIconRes = R.drawable.ic_close_24, diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt index c948e842c3..0ccf5aada7 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt @@ -55,6 +55,7 @@ import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM import com.tangem.features.swap.v2.impl.amount.ui.preview.SwapAmountContentPreview import com.tangem.features.swap.v2.impl.common.entity.ConfirmUM import com.tangem.features.swap.v2.impl.common.entity.SwapQuoteUM +import com.tangem.features.swap.v2.impl.sendviaswap.SendWithSwapRoute import com.tangem.features.swap.v2.impl.sendviaswap.entity.SendWithSwapUM import kotlinx.collections.immutable.persistentListOf import java.math.BigDecimal @@ -368,6 +369,7 @@ private fun SendWithSwapSuccessContent_Preview() { ), ), navigationUM = NavigationUM.Content( + source = SendWithSwapRoute.Success.javaClass.simpleName, title = TextReference.EMPTY, subtitle = null, backIconRes = R.drawable.ic_close_24, From d28347ee21e60bf905edadf64b9cf026d4e618d9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Dec 2025 13:54:59 +0300 Subject: [PATCH 05/11] Updated on 2026-08-14 --- .../src/main/assets/configs/excluded_blockchains_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/config-toggles/src/main/assets/configs/excluded_blockchains_config.json b/core/config-toggles/src/main/assets/configs/excluded_blockchains_config.json index b3c1dd8f8d..59809c4e40 100644 --- a/core/config-toggles/src/main/assets/configs/excluded_blockchains_config.json +++ b/core/config-toggles/src/main/assets/configs/excluded_blockchains_config.json @@ -29,7 +29,7 @@ }, { "name": "zklink", - "version": "5.31" + "version": "undefined" }, { "name": "plasma", From 1b061d2d2bed9d0d289082e608c1daeaf0206994 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Dec 2025 16:14:08 +0500 Subject: [PATCH 06/11] Updated on 2026-08-14 --- .../tokens/repository/DefaultCurrencyChecksRepository.kt | 3 ++- .../com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt | 4 +++- .../domain/tokens/repository/CurrencyChecksRepository.kt | 2 +- .../subcomponents/notifications/model/NotificationsModel.kt | 1 + .../staking/impl/presentation/model/StakingModel.kt | 1 + .../com/tangem/feature/swap/domain/SwapInteractorImpl.kt | 6 ++++++ 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrencyChecksRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrencyChecksRepository.kt index 8c77f51a78..de056fb431 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrencyChecksRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrencyChecksRepository.kt @@ -155,9 +155,10 @@ internal class DefaultCurrencyChecksRepository( override suspend fun getRentExemptionError( userWalletId: UserWalletId, - currencyStatus: CryptoCurrencyStatus, + currencyStatus: CryptoCurrencyStatus?, balanceAfterTransaction: BigDecimal, ): CryptoCurrencyWarning.Rent? { + if (currencyStatus == null) return null val rentData = walletManagersFacade.getRentInfo(userWalletId, currencyStatus.currency.network) ?: return null return when { balanceAfterTransaction.isZero() -> null diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt index 43c65d397a..e1073f1bd0 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt @@ -14,9 +14,11 @@ class GetCurrencyCheckUseCase( private val dispatchers: CoroutineDispatcherProvider, ) { + @Suppress("LongParameterList") suspend operator fun invoke( userWalletId: UserWalletId, currencyStatus: CryptoCurrencyStatus, + feeCurrencyStatus: CryptoCurrencyStatus?, amount: BigDecimal?, fee: BigDecimal?, feeCurrencyBalanceAfterTransaction: BigDecimal?, @@ -31,7 +33,7 @@ class GetCurrencyCheckUseCase( val existentialDeposit = currencyChecksRepository.getExistentialDeposit(userWalletId, network) val rentWarning = currencyChecksRepository.getRentExemptionError( userWalletId = userWalletId, - currencyStatus = currencyStatus, + currencyStatus = feeCurrencyStatus, balanceAfterTransaction = feeCurrencyBalanceAfterTransaction ?: BigDecimal.ZERO, ) val isAccountFunded = recipientAddress?.let { diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrencyChecksRepository.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrencyChecksRepository.kt index 8351958b10..41266e0b39 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrencyChecksRepository.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrencyChecksRepository.kt @@ -58,7 +58,7 @@ interface CurrencyChecksRepository { */ suspend fun getRentExemptionError( userWalletId: UserWalletId, - currencyStatus: CryptoCurrencyStatus, + currencyStatus: CryptoCurrencyStatus?, balanceAfterTransaction: BigDecimal, ): CryptoCurrencyWarning.Rent? } \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt index 7642f338a8..7efbe2186d 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/notifications/model/NotificationsModel.kt @@ -136,6 +136,7 @@ internal class NotificationsModel @Inject constructor( val currencyCheck = getCurrencyCheckUseCase( userWalletId = userWalletId, currencyStatus = cryptoCurrencyStatus, + feeCurrencyStatus = feeCryptoCurrencyStatus, amount = sendingAmount, fee = feeValue, recipientAddress = destinationAddress, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt index eebecedbcf..9e1aaa62ba 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt @@ -772,6 +772,7 @@ internal class StakingModel @Inject constructor( val currencyStatus = getCurrencyCheckUseCase( userWalletId = userWalletId, currencyStatus = cryptoCurrencyStatus, + feeCurrencyStatus = feeCryptoCurrencyStatus, amount = amount, fee = fee, feeCurrencyBalanceAfterTransaction = balanceAfterTransaction, diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index 8146ac1c63..aa8415a3c9 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -92,6 +92,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( private val amountFormatter: AmountFormatter, private val rampStateManager: RampStateManager, private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, + private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val accountsFeatureToggles: AccountsFeatureToggles, @Assisted private val userWalletId: UserWalletId, ) : SwapInteractor { @@ -631,9 +632,14 @@ internal class SwapInteractorImpl @AssistedInject constructor( } else { amount } + val feePaidCurrencyStatus = getFeePaidCryptoCurrencyStatusSyncUseCase( + userWalletId = userWalletId, + cryptoCurrencyStatus = fromTokenStatus, + ).getOrNull() val currencyCheck = getCurrencyCheckUseCase( userWalletId = userWalletId, currencyStatus = fromTokenStatus, + feeCurrencyStatus = feePaidCurrencyStatus, amount = amountToRequest.value, fee = fee, feeCurrencyBalanceAfterTransaction = balanceAfterTransaction, From 30613125f8a8940fb34e524b13e1dda2debd8db6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Dec 2025 15:15:13 +0400 Subject: [PATCH 07/11] Updated on 2026-08-14 --- .../tangem/features/tangempay/model/TangemPayOnboardingModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayOnboardingModel.kt b/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayOnboardingModel.kt index 246b7a1ce7..2479a42d03 100644 --- a/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayOnboardingModel.kt +++ b/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayOnboardingModel.kt @@ -58,7 +58,7 @@ internal class TangemPayOnboardingModel @Inject constructor( } is TangemPayOnboardingComponent.Params.Deeplink -> { repository.validateDeeplink(params.deeplink) - .onRight { isValid -> if (isValid) showOnboarding() } + .onRight { isValid -> if (isValid) showOnboarding() else back() } .onLeft { back() } } } From 3451c40021f610a2665b4ae4784942f3205853cf Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Dec 2025 12:25:49 +0100 Subject: [PATCH 08/11] Updated on 2026-08-14 --- .../mainv2/entity/factory/OnrampOffersStateFactory.kt | 7 ++++--- .../mainv2/entity/factory/OnrampV2AmountStateFactory.kt | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/factory/OnrampOffersStateFactory.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/factory/OnrampOffersStateFactory.kt index 67f09bf351..60b8cc3570 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/factory/OnrampOffersStateFactory.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/factory/OnrampOffersStateFactory.kt @@ -17,14 +17,15 @@ internal class OnrampOffersStateFactory( fun getOffersState(offers: List): OnrampV2MainComponentUM { val currentState = currentStateProvider.invoke() return when (currentState) { + is OnrampV2MainComponentUM.InitialLoading -> currentState is OnrampV2MainComponentUM.Content -> { + if (currentState.offersBlockState is OnrampOffersBlockUM.Loading && offers.isEmpty()) { + return currentState + } currentState.copy( offersBlockState = mapOnrampOffersBlockToUM(offersBlocks = offers), ) } - is OnrampV2MainComponentUM.InitialLoading -> { - currentState - } } } diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/factory/OnrampV2AmountStateFactory.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/factory/OnrampV2AmountStateFactory.kt index 2af5055bd7..499cb56a88 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/factory/OnrampV2AmountStateFactory.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/factory/OnrampV2AmountStateFactory.kt @@ -64,6 +64,7 @@ internal class OnrampV2AmountStateFactory( currencySymbol = currency.unit, onAmountValueChanged = onrampIntents::onAmountValueChanged, ), + offersBlockState = OnrampOffersBlockUM.Loading, ) } From 2c74ec0fb265716b8862bc0642846b26b7186333 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Dec 2025 16:07:33 +0300 Subject: [PATCH 09/11] Updated on 2026-08-14 --- .../BiometricUserWalletsListManager.kt | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 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 85b958f1d1..6e9ca21efb 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 @@ -18,8 +18,12 @@ import com.tangem.tap.domain.userWalletList.utils.toUserWallets import com.tangem.tap.domain.userWalletList.utils.updateWith import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.* +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import timber.log.Timber +@Suppress("LargeClass") @OptIn(ExperimentalCoroutinesApi::class) internal class BiometricUserWalletsListManager( private val keysRepository: UserWalletsKeysRepository, @@ -29,6 +33,9 @@ internal class BiometricUserWalletsListManager( ) : UserWalletsListManager.Lockable { private val state = MutableStateFlow(State()) + private var hasSavedWallets: Boolean? = null + private val savedWalletMutex = Mutex() + override val isLockable: Boolean = true override val userWallets: Flow> @@ -61,7 +68,21 @@ internal class BiometricUserWalletsListManager( get() = state.value.isLocked override val hasUserWallets: Boolean - get() = keysRepository.hasSavedEncryptionKeys() + get() { + return runBlocking { + // workaround to avoid calling hasSavedEncryptionKeys many times because of performance + savedWalletMutex.withLock { + val hasSavedWalletsLocal = hasSavedWallets + if (hasSavedWalletsLocal == null || !hasSavedWalletsLocal) { + val hasKeys = keysRepository.hasSavedEncryptionKeys() + hasSavedWallets = hasKeys + hasKeys + } else { + true + } + } + } + } override val walletsCount: Int get() = state.value.userWallets.size @@ -194,6 +215,9 @@ internal class BiometricUserWalletsListManager( } override suspend fun clear(): CompletionResult { + savedWalletMutex.withLock { + hasSavedWallets = null + } return sensitiveInformationRepository.clear() .flatMap { publicInformationRepository.clear() } .map { From 3b57f24af04446b73bc553276ea4ac5b3f2a2be6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Dec 2025 18:15:39 +0500 Subject: [PATCH 10/11] Updated on 2026-08-14 --- .../core/ui/components/rows/NetworkTitle.kt | 3 +- .../tokenlist/internal/GroupTitleItem.kt | 2 +- .../impl/ui/MarketsTokenDetailsContent.kt | 53 +++---- .../impl/ui/components/InsightsBlock.kt | 7 +- .../ui/components/PricePerformanceBlock.kt | 6 +- .../ui/preview/MarketsTokenDetailsPreview.kt | 129 ++++++++++++++++++ 6 files changed, 162 insertions(+), 38 deletions(-) create mode 100644 features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/preview/MarketsTokenDetailsPreview.kt diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/rows/NetworkTitle.kt b/core/ui/src/main/java/com/tangem/core/ui/components/rows/NetworkTitle.kt index e7644ee705..25b0a54929 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/rows/NetworkTitle.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/rows/NetworkTitle.kt @@ -61,7 +61,6 @@ fun NetworkTitle( ) { Box( modifier = Modifier - .weight(weight = 1f) .heightIn(min = TangemTheme.dimens.size20), contentAlignment = Alignment.CenterStart, content = title, @@ -99,4 +98,4 @@ private fun NetworkTitlePreview(@PreviewParameter(NetworkTitleIconVisibilityProv } } -private object NetworkTitleIconVisibilityProvider : CollectionPreviewParameterProvider(listOf(true, false)) \ No newline at end of file +private class NetworkTitleIconVisibilityProvider : CollectionPreviewParameterProvider(listOf(true, false)) \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/internal/GroupTitleItem.kt b/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/internal/GroupTitleItem.kt index a3f882b7ba..719f825aed 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/internal/GroupTitleItem.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/tokenlist/internal/GroupTitleItem.kt @@ -124,4 +124,4 @@ private fun NetworkTitleItemPreview(@PreviewParameter(GroupTitleItemProvider::cl } } -private object GroupTitleItemProvider : CollectionPreviewParameterProvider(collection = listOf(true, false)) \ No newline at end of file +private class GroupTitleItemProvider : CollectionPreviewParameterProvider(collection = listOf(true, false)) \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/MarketsTokenDetailsContent.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/MarketsTokenDetailsContent.kt index 311f6709fe..fc3737ddd0 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/MarketsTokenDetailsContent.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/MarketsTokenDetailsContent.kt @@ -20,28 +20,26 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.Dp -import com.tangem.common.ui.charts.state.MarketChartDataProducer import com.tangem.core.ui.components.* import com.tangem.core.ui.components.appbar.TangemTopAppBar import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM -import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig -import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent import com.tangem.core.ui.components.buttons.segmentedbutton.SegmentedButtons import com.tangem.core.ui.components.currency.icon.CoinIcon import com.tangem.core.ui.components.marketprice.PriceChangeInPercent import com.tangem.core.ui.components.marketprice.PriceChangeType import com.tangem.core.ui.event.EventEffect import com.tangem.core.ui.event.StateEvent -import com.tangem.core.ui.event.consumedEvent import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.domain.markets.PriceChangeInterval import com.tangem.features.markets.details.impl.ui.components.* +import com.tangem.features.markets.details.impl.ui.preview.MarketsTokenDetailsPreview import com.tangem.features.markets.details.impl.ui.state.ExchangesBottomSheetContent import com.tangem.features.markets.details.impl.ui.state.InfoBottomSheetContent import com.tangem.features.markets.details.impl.ui.state.MarketsTokenDetailsUM @@ -317,36 +315,16 @@ fun PriceChangeInterval.getText(): TextReference { } } -@Preview -@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +// region Preview @Composable -private fun Preview() { +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +private fun MarketsTokenDetailsContent_Preview( + @PreviewParameter(MarketsTokenDetailsContentPreviewProvider::class) params: MarketsTokenDetailsUM, +) { TangemThemePreview { MarketsTokenDetailsContent( - state = MarketsTokenDetailsUM( - tokenName = "Token Name", - priceText = "$0.00000000324", - dateTimeText = stringReference("Today"), - priceChangePercentText = "52.00%", - iconUrl = "", - priceChangeType = PriceChangeType.UP, - chartState = MarketsTokenDetailsUM.ChartState( - dataProducer = MarketChartDataProducer.build { }, - onLoadRetryClick = {}, - status = MarketsTokenDetailsUM.ChartState.Status.LOADING, - onMarkerPointSelected = { _, _ -> }, - ), - selectedInterval = PriceChangeInterval.H24, - onSelectedIntervalChange = { }, - body = MarketsTokenDetailsUM.Body.Loading, - bottomSheetConfig = TangemBottomSheetConfig( - isShown = false, - onDismissRequest = {}, - content = TangemBottomSheetConfigContent.Empty, - ), - markerSet = false, - triggerPriceChange = consumedEvent(), - ), + state = params, onHeaderSizeChange = {}, onBackClick = {}, backgroundColor = TangemTheme.colors.background.tertiary, @@ -356,4 +334,13 @@ private fun Preview() { addTopBarStatusBarPadding = false, ) } -} \ No newline at end of file +} + +private class MarketsTokenDetailsContentPreviewProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + MarketsTokenDetailsPreview.loadingState, + MarketsTokenDetailsPreview.contentState, + ) +} +// endregion \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/InsightsBlock.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/InsightsBlock.kt index e13502279d..8b5e829a64 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/InsightsBlock.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/InsightsBlock.kt @@ -8,6 +8,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import com.tangem.core.ui.components.RectangleShimmer import com.tangem.core.ui.components.block.information.GridItems import com.tangem.core.ui.components.block.information.InformationBlock @@ -51,12 +52,16 @@ internal fun InsightsBlock(state: InsightsUM, modifier: Modifier = Modifier) { currentInterval = it state.onIntervalChanged(it) }, + modifier = Modifier.width(IntrinsicSize.Min), ) { Box( Modifier .fillMaxSize() .align(Alignment.Center) - .padding(vertical = TangemTheme.dimens.spacing4), + .padding( + horizontal = 14.dp, + vertical = 4.dp, + ), ) { Text( modifier = Modifier.align(Alignment.Center), diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/PricePerformanceBlock.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/PricePerformanceBlock.kt index 4486732b67..efede75d0e 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/PricePerformanceBlock.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/PricePerformanceBlock.kt @@ -57,12 +57,16 @@ internal fun PricePerformanceBlock(state: PricePerformanceUM, modifier: Modifier currentInterval = it state.onIntervalChanged(it) }, + modifier = Modifier.width(IntrinsicSize.Min), ) { Box( Modifier .fillMaxSize() .align(Alignment.Center) - .padding(vertical = TangemTheme.dimens.spacing4), + .padding( + horizontal = 14.dp, + vertical = TangemTheme.dimens.spacing4, + ), ) { Text( modifier = Modifier.align(Alignment.Center), diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/preview/MarketsTokenDetailsPreview.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/preview/MarketsTokenDetailsPreview.kt new file mode 100644 index 0000000000..46ad847bf6 --- /dev/null +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/preview/MarketsTokenDetailsPreview.kt @@ -0,0 +1,129 @@ +package com.tangem.features.markets.details.impl.ui.preview + +import com.tangem.common.ui.charts.state.MarketChartDataProducer +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent +import com.tangem.core.ui.components.marketprice.PriceChangeType +import com.tangem.core.ui.event.consumedEvent +import com.tangem.core.ui.extensions.stringReference +import com.tangem.domain.markets.PriceChangeInterval +import com.tangem.features.markets.details.impl.ui.state.* +import kotlinx.collections.immutable.persistentListOf + +internal object MarketsTokenDetailsPreview { + private val infoPoint = InfoPointUM( + title = stringReference("1"), + value = "2", + change = InfoPointUM.ChangeType.DOWN, + onInfoClick = {}, + ) + + val loadingState = MarketsTokenDetailsUM( + tokenName = "Token Name", + priceText = "$0.00000000324", + dateTimeText = stringReference("Today"), + priceChangePercentText = "52.00%", + iconUrl = "", + priceChangeType = PriceChangeType.UP, + chartState = MarketsTokenDetailsUM.ChartState( + dataProducer = MarketChartDataProducer.build { }, + onLoadRetryClick = {}, + status = MarketsTokenDetailsUM.ChartState.Status.LOADING, + onMarkerPointSelected = { _, _ -> }, + ), + selectedInterval = PriceChangeInterval.H24, + onSelectedIntervalChange = { }, + body = MarketsTokenDetailsUM.Body.Loading, + bottomSheetConfig = TangemBottomSheetConfig( + isShown = false, + onDismissRequest = {}, + content = TangemBottomSheetConfigContent.Empty, + ), + markerSet = false, + triggerPriceChange = consumedEvent(), + ) + + val contentState = MarketsTokenDetailsUM( + tokenName = "Token Name", + priceText = "$0.00000000324", + dateTimeText = stringReference("Today"), + priceChangePercentText = "52.00%", + iconUrl = "", + priceChangeType = PriceChangeType.UP, + chartState = MarketsTokenDetailsUM.ChartState( + dataProducer = MarketChartDataProducer.build { }, + onLoadRetryClick = {}, + status = MarketsTokenDetailsUM.ChartState.Status.LOADING, + onMarkerPointSelected = { _, _ -> }, + ), + selectedInterval = PriceChangeInterval.H24, + onSelectedIntervalChange = { }, + body = MarketsTokenDetailsUM.Body.Content( + description = MarketsTokenDetailsUM.Description( + shortDescription = stringReference("markets_token_details_description_short"), + fullDescription = stringReference("markets_token_details_description_full"), + onReadMoreClick = {}, + ), + infoBlocks = MarketsTokenDetailsUM.InformationBlocks( + insights = InsightsUM( + h24Info = persistentListOf( + infoPoint, + infoPoint, + infoPoint, + ), + weekInfo = persistentListOf( + infoPoint, + infoPoint, + infoPoint, + ), + monthInfo = persistentListOf( + infoPoint, + infoPoint, + infoPoint, + ), + onInfoClick = {}, + onIntervalChanged = {}, + ), + securityScore = SecurityScoreUM( + score = 2.3f, + description = stringReference("markets_token_details_security_score_description"), + onInfoClick = {}, + ), + metrics = MetricsUM( + metrics = persistentListOf( + infoPoint, + infoPoint, + infoPoint, + ), + ), + pricePerformance = PricePerformanceUM( + h24 = PricePerformanceUM.Value( + low = "1", + high = "2", + indicatorFraction = 0.3f, + ), + month = PricePerformanceUM.Value( + low = "1", + high = "2", + indicatorFraction = 0.3f, + ), + all = PricePerformanceUM.Value( + low = "1", + high = "2", + indicatorFraction = 0.3f, + ), + onIntervalChanged = {}, + ), + listedOn = ListedOnUM.Empty, + links = null, + ), + ), + bottomSheetConfig = TangemBottomSheetConfig( + isShown = false, + onDismissRequest = {}, + content = TangemBottomSheetConfigContent.Empty, + ), + markerSet = true, + triggerPriceChange = consumedEvent(), + ) +} \ No newline at end of file From 364bc12ffe6a1e7122ff37bf2fe3b004b9400097 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 10 Dec 2025 13:15:57 +0000 Subject: [PATCH 11/11] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 07be659f64..8c10bcaf9d 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,13 +5,13 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.31-1314" +tangemBlockchainSdk = "develop-1317" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "releases-5.31-569" +tangemCardSdk = "develop-568" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem12" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ -tangemHotSdk = "develop-531" +tangemHotSdk = "develop-532" #tangemHotSdk = "0.0.1" # Keep it! - used for local builds ^