diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index 9f34ca0ea3..a8cf062a6b 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit 9f34ca0ea3969b5ba6b82e1aea2fef0a44463fc8 +Subproject commit a8cf062a6bb58332458c0f5b43026e062378e5c7 diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index c357e3c31f..282551cd56 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -134,7 +134,7 @@ お使いの携帯電話で生体認証が無効になっているため、アプリにウォレットを保存できません。ウォレットを保存するには、携帯電話の設定で生体認証機能を有効にしてください。 プロモーションコードの処理中にエラーが発生しました。しばらくしてからもう一度お試しください。 アクティベーションエラー - プロモコードが正常に有効化されました。リワードは14日以内にあなたのアカウントに付与されます。 + プロモーションコードが正常に有効化されました。報酬は14日以内にビットコインアカウントに入金されます。 プロモーションコードが有効になりました このプロモーションコードは既に使用されているため、再度使うことはできません。 コードが利用できません @@ -180,6 +180,7 @@ 追加 ポートフォリオに追加 トークンを追加 + 追加済み アドレス すべて 許可する @@ -1365,7 +1366,7 @@ 新しい機能や限定オファーへの早期アクセス。 機能およびニュースのアップデート プッシュ通知を使用しますか? - プッシュ通知を有効にすると、資金が到着するとすぐに通知されます。 + プッシュ通知を有効にすると、ウォレットに着金したときにアラートを受信できます。 取引を見逃さない 新しいウォレットを追加 バックアップせずにこのウォレットを削除すると、資金に永久にアクセスできなくなります。 @@ -1444,6 +1445,7 @@ dAppsに接続する WalletConnect 接続には数秒かかる場合があります + Tangemウォレットを作成する %sから Tangemウォレットを購入ーこれは、あなたの秘密鍵をオフラインで安全に保管する物理デバイスです。 ハードウェアウォレット @@ -1759,7 +1761,8 @@ 供給APR APY あなたの資産を眠らせない — 残高を運用して利息を得ましょう。 - 保有資産から報酬を得る + 利息は自動的に発生します + Aaveレンディング 入金の処理中 年間%1$s%%の収益 自動 diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index acc3f54800..c55cacce85 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -80,7 +80,7 @@ Вы отключили биометрическую аутентификацию на вашем телефоне и не сможете сохранять кошельки в приложении. Для сохранения кошельков, пожалуйста, включите функцию биометрической аутентификации в настройках телефона. При обработке промокода произошла ошибка. Пожалуйста, попробуйте позже. Ошибка активации - Ваш промокод был успешно активирован. Награда будет зачислена на ваш счёт в течение 14 дней. + Ваш промокод был успешно активирован. Награда будет зачислена на ваш Bitcoin адрес в течение 14 дней. Промокод активирован Этот промокод уже был использован и не может быть активирован повторно. Код недоступен diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index ce3e6d97ca..3e4c4ec8a8 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -135,7 +135,7 @@ You have disabled biometric authentication on your phone and will not be able to save wallets in the app. To save wallets, please enable the biometric authentication function in your phone settings. An error occurred while processing your promo code. Please try again later. Activation error - Your promo code was successfully activated. A reward will be credited to your account within 14 days. + Your promo code was successfully activated. The reward will be credited to your Bitcoin account within 14 days. Promo Code Activated This promo code has already been used and cannot be activated again. Code unavailable @@ -1797,7 +1797,10 @@ All future %s top-ups will be supplied to Aave automatically, with the transaction fee deducted. If network fees rise above maximum fee, the transaction won’t go through until they decrease. You can change this limit later. Maximum fee + The transaction fee must stay below 4% of your deposit. Tangem will transfer funds to Aave only once your balance is large enough to meet this condition. + Minimal amount Fee policy + Tangem also takes a 3% service fee on the yield earned. Network fee is too high right now. Waiting until it falls below your limit. Historical returns Write description here. In one, two or three lines will be awesome. [PLACEHOLDER] diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt index 6de247399b..20bb9fce3b 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt @@ -85,6 +85,7 @@ fun Notification( subtitle = config.subtitle, subtitleColor = subtitleColor, showArrowIcon = isEnabled && config.shouldShowArrowIcon, + hasCloseButton = config.onCloseClick != null, ) } } @@ -148,6 +149,7 @@ private fun MainContent( titleColor: Color, subtitleColor: Color, showArrowIcon: Boolean, + hasCloseButton: Boolean, ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( @@ -161,10 +163,24 @@ private fun MainContent( SpacerW(width = TangemTheme.dimens.spacing10) - TextsBlock(title = title, titleColor = titleColor, subtitle = subtitle, subtitleColor = subtitleColor) + TextsBlock( + title = title, + titleColor = titleColor, + subtitle = subtitle, + subtitleColor = subtitleColor, + modifier = Modifier + .weight(1f, fill = false) + .then( + if (hasCloseButton && !showArrowIcon) { + Modifier.padding(end = TangemTheme.dimens.size32) + } else { + Modifier + }, + ), + ) if (showArrowIcon) { - SpacerWMax() + SpacerW(width = TangemTheme.dimens.spacing8) Icon( painter = painterResource(id = R.drawable.ic_chevron_right_24), diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt index 3fc333d86f..cc2fe1bca6 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt @@ -41,6 +41,11 @@ internal class DefaultCustomTokensRepository( private val networkFactory: NetworkFactory, ) : CustomTokensRepository { + private val excludedBlockchainsForCustom = setOf( + Blockchain.Quai, + Blockchain.QuaiTestnet, + ) + private val cryptoCurrencyFactory = CryptoCurrencyFactory(excludedBlockchains) private val userTokensResponseFactory = UserTokensResponseFactory() private val tokenAddressConverter = TokenAddressesConverter() @@ -268,6 +273,7 @@ internal class DefaultCustomTokensRepository( val scanResponse = userWallet.scanResponse Blockchain.entries + .filter { it !in excludedBlockchainsForCustom } .mapNotNull { blockchain -> val canHandleBlockchain = scanResponse.card.canHandleBlockchain( blockchain, diff --git a/domain/card/src/main/kotlin/com/tangem/domain/card/common/extensions/CardSdk.kt b/domain/card/src/main/kotlin/com/tangem/domain/card/common/extensions/CardSdk.kt index 4606c72970..4be35ce782 100644 --- a/domain/card/src/main/kotlin/com/tangem/domain/card/common/extensions/CardSdk.kt +++ b/domain/card/src/main/kotlin/com/tangem/domain/card/common/extensions/CardSdk.kt @@ -45,19 +45,33 @@ fun CardDTO.supportedBlockchains( excludedBlockchains: ExcludedBlockchains, ): List { val supportedBlockchains = if (firmwareVersion < FirmwareVersion.MultiWalletAvailable) { - Blockchain.fromCurve(EllipticCurve.Secp256k1).toMutableList() + Blockchain.fromCurve(EllipticCurve.Secp256k1) } else if (!cardTypesResolver.isWallet2() && !cardTypesResolver.isTangemWallet()) { // need for old multiwallet that supports only secp256k1 - wallets.flatMap { Blockchain.fromCurve(it.curve) }.distinct().toMutableList() + wallets.flatMap { Blockchain.fromCurve(it.curve) }.distinct() } else { // multiwallet supports all blockchains, move this logic to config - Blockchain.entries.toMutableList() + Blockchain.entries } return supportedBlockchains .filter { isTestCard == it.isTestnet() } + .filterNot(::isBlockchainUnsupported) .filter { it !in excludedBlockchains } } +/** + * Filters out blockchains that are not supported by the specific card firmware. + * @return `false` if blockchain is not supported, `true` otherwise. + */ +private fun CardDTO.isBlockchainUnsupported(blockchain: Blockchain): Boolean { + return when (blockchain) { + Blockchain.Quai, Blockchain.QuaiTestnet -> { + firmwareVersion <= FirmwareVersion.HDWalletAvailable + } + else -> false + } +} + fun CardDTO.supportedTokens( cardTypesResolver: CardTypesResolver, excludedBlockchains: ExcludedBlockchains, diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/InitializeQrScanningStateTransformer.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/InitializeQrScanningStateTransformer.kt index bc9659cc28..06faacb811 100644 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/InitializeQrScanningStateTransformer.kt +++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/InitializeQrScanningStateTransformer.kt @@ -2,7 +2,6 @@ package com.tangem.feature.qrscanning.presentation.transformers import com.tangem.core.ui.clipboard.ClipboardManager import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.qrscanning.models.QrResultSource import com.tangem.domain.qrscanning.models.SourceType @@ -22,7 +21,7 @@ internal class InitializeQrScanningStateTransformer( override fun transform(prevState: QrScanningState): QrScanningState { val message = when (source) { SourceType.SEND -> network?.let { resourceReference(R.string.send_qrcode_scan_info, wrappedList(it)) } - SourceType.WALLET_CONNECT -> stringReference("Open Web3 app and chose WalletConnect option") + SourceType.WALLET_CONNECT -> resourceReference(R.string.wc_qr_scan_hint) } return QrScanningState( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingClickIntents.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingClickIntents.kt index 28507abd9f..97e447a0f5 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingClickIntents.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingClickIntents.kt @@ -69,4 +69,8 @@ internal interface StakingClickIntents : AmountScreenClickIntents { fun showPrimaryClickAlert() fun onOpenLearnMoreAboutApproveClick() + + fun onActivateTonAccountNotificationClick() + + fun onActivateTonAccountClick() } \ No newline at end of file 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 b4c31ec116..f32aabd0e3 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 @@ -2,6 +2,7 @@ package com.tangem.features.staking.impl.presentation.model import androidx.compose.runtime.Stable import arrow.core.getOrElse +import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.common.routing.AppRouter import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer @@ -48,8 +49,11 @@ import com.tangem.domain.staking.utils.getValidatorsCount import com.tangem.domain.tokens.* import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.transaction.usecase.CreateApprovalTransactionUseCase +import com.tangem.domain.transaction.usecase.CreateTransferTransactionUseCase import com.tangem.domain.transaction.usecase.GetAllowanceUseCase +import com.tangem.domain.transaction.usecase.GetFeeUseCase import com.tangem.domain.transaction.usecase.SendTransactionUseCase +import com.tangem.domain.utils.convertToSdkAmount import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.staking.api.StakingComponent import com.tangem.features.staking.impl.analytics.StakingParamsInterceptor @@ -69,10 +73,15 @@ import com.tangem.features.staking.impl.presentation.state.transformers.approval import com.tangem.features.staking.impl.presentation.state.transformers.confirmation.SetUpdatedAllowanceTransformer import com.tangem.features.staking.impl.presentation.state.transformers.notifications.AddStakingNotificationsTransformer import com.tangem.features.staking.impl.presentation.state.transformers.notifications.DismissStakingNotificationsStateTransformer +import com.tangem.features.staking.impl.presentation.state.transformers.ton.CompleteInitializeBottomSheetTransformer +import com.tangem.features.staking.impl.presentation.state.transformers.ton.SetFeeToTonInitializeBottomSheetTransformer +import com.tangem.features.staking.impl.presentation.state.transformers.ton.ShowTonInitializeBottomSheetTransformer +import com.tangem.features.staking.impl.presentation.state.transformers.ton.SetFeeErrorToTonInitializeBottomSheetTransformer import com.tangem.features.staking.impl.presentation.state.transformers.validator.ValidatorSelectChangeTransformer import com.tangem.features.staking.impl.presentation.state.utils.checkAndCalculateSubtractedAmount import com.tangem.features.staking.impl.presentation.state.utils.isSingleAction import com.tangem.features.staking.impl.presentation.state.utils.withStubUnstakeAction +import com.tangem.lib.crypto.BlockchainUtils.isTon import com.tangem.utils.Provider import com.tangem.utils.TangemBlogUrlBuilder.RESOURCE_TO_LEARN_ABOUT_APPROVING_IN_SWAP import com.tangem.utils.coroutines.* @@ -122,6 +131,9 @@ internal class StakingModel @Inject constructor( private val getActionsUseCase: GetActionsUseCase, private val getYieldUseCase: GetYieldUseCase, private val checkAccountInitializedUseCase: CheckAccountInitializedUseCase, + private val createTransferTransactionUseCase: CreateTransferTransactionUseCase, + private val getFeeUseCase: GetFeeUseCase, + private val getNetworkAddressesUseCase: GetNetworkAddressesUseCase, private val getActionRequirementAmountUseCase: GetActionRequirementAmountUseCase, private val paramsInterceptorHolder: ParamsInterceptorHolder, private val shareManager: ShareManager, @@ -150,11 +162,14 @@ internal class StakingModel @Inject constructor( } } + private var isAccountInitialized: Boolean = true private var cryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull() private var stakingActions: List = emptyList() private var feeCryptoCurrencyStatus: CryptoCurrencyStatus? = null private var minimumTransactionAmount: EnterAmountBoundary? = null + private var tonAccountInitializeTransaction: TransactionData.Uncompiled? = null + private val userWallet by lazy { requireNotNull( getUserWalletUseCase(userWalletId).getOrNull(), @@ -250,26 +265,12 @@ internal class StakingModel @Inject constructor( val isInitialInfoStep = value.currentStep == StakingStep.InitialInfo val noBalanceState = balanceState == null val noYieldBalanceData = cryptoCurrencyStatus.value.yieldBalance !is YieldBalance.Data - val isAccountInitialized = checkAccountInitializedUseCase.invoke( - userWalletId = userWalletId, - network = cryptoCurrencyStatus.currency.network, - ).getOrElse { - Timber.e(it) - false - } when { isInitialInfoStep && noBalanceState && yield.allValidatorsFull && noYieldBalanceData -> { stakingEventFactory.createStakingValidatorsUnavailableAlert() return@launch } - isInitialInfoStep && noBalanceState && !isAccountInitialized -> { - analyticsEventHandler.send(StakingAnalyticsEvent.UnitializedAddress( - token = cryptoCurrencyStatus.currency.symbol, - )) - stakingEventFactory.createInitializeAccountAlert() - return@launch - } isInitialInfoStep && noBalanceState -> { val list = buildList { SetConfirmationStateInitTransformer( @@ -763,6 +764,7 @@ internal class StakingModel @Inject constructor( AddStakingNotificationsTransformer( cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus }, appCurrencyProvider = Provider { appCurrency }, + isAccountInitializedProvider = Provider { isAccountInitialized }, feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, currencyWarning = currencyWarning, currencyCheck = currencyStatus, @@ -934,6 +936,85 @@ internal class StakingModel @Inject constructor( urlOpener.openUrl(RESOURCE_TO_LEARN_ABOUT_APPROVING_IN_SWAP) } + override fun onActivateTonAccountNotificationClick() { + modelScope.launch { + stateController.update( + ShowTonInitializeBottomSheetTransformer( + onDismiss = { stateController.update(DismissBottomSheetStateTransformer) }, + ), + ) + + val tonAmount = BigDecimal(1) + val destination = getNetworkAddressesUseCase.invokeSync( + userWalletId = userWalletId, + network = cryptoCurrencyStatus.currency.network, + ).getOrNull(0)?.address ?: return@launch + + val transaction = createTransferTransactionUseCase( + amount = tonAmount.convertToSdkAmount(cryptoCurrencyStatus), + destination = destination, + userWalletId = userWalletId, + network = cryptoCurrencyStatus.currency.network, + memo = null, + ) + tonAccountInitializeTransaction = transaction.getOrElse { + stateController.update( + SetFeeErrorToTonInitializeBottomSheetTransformer(), + ) + return@launch + } + + val transactionFee = getFeeUseCase( + userWallet = userWallet, + network = cryptoCurrencyStatus.currency.network, + transactionData = tonAccountInitializeTransaction!!, + ) + + transactionFee.fold( + ifLeft = { + stateController.update( + SetFeeErrorToTonInitializeBottomSheetTransformer(), + ) + }, + ifRight = { + stateController.update( + SetFeeToTonInitializeBottomSheetTransformer( + appCurrencyProvider = Provider { appCurrency }, + feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, + fee = it.normal, + isFeeApproximate = false, + ), + ) + }, + ) + } + } + + override fun onActivateTonAccountClick() { + modelScope.launch { + tonAccountInitializeTransaction?.let { transaction -> + sendTransactionUseCase.invoke( + txData = transaction, + userWallet = userWallet, + network = cryptoCurrencyStatus.currency.network, + ).fold( + ifLeft = { + stateController.update(DismissBottomSheetStateTransformer) + }, + ifRight = { + stateController.update(CompleteInitializeBottomSheetTransformer( + cryptoCurrencyStatus = cryptoCurrencyStatus, + minimumTransactionAmount = minimumTransactionAmount, + )) + + balanceUpdater.partialUpdateWithDelay() + stateController.update(DismissBottomSheetStateTransformer) + }, + ) + } + } + } + private suspend fun setupApprovalNeeded() { val approval = StakingIntegrationID.create(currencyId = cryptoCurrencyStatus.currency.id)?.approval ?: StakingApproval.Empty @@ -961,7 +1042,9 @@ internal class StakingModel @Inject constructor( ) .conflate() .distinctUntilChanged() - .filter { value.currentStep == StakingStep.InitialInfo } + .filter { + value.currentStep == StakingStep.InitialInfo || isCaseWithUnitializedTonAccount() + } .onEach { maybeStatus -> maybeStatus.fold( ifRight = { status -> @@ -989,6 +1072,19 @@ internal class StakingModel @Inject constructor( } cryptoCurrencyStatus = status + val isAccountInitializedNew = checkAccountInitializedUseCase.invoke( + userWalletId = userWalletId, + network = cryptoCurrencyStatus.currency.network, + ).getOrElse { + Timber.e(it) + false + } + if (isAccountInitializedNew && !isAccountInitialized) { + isAccountInitialized = true + updateNotifications() + } + isAccountInitialized = isAccountInitializedNew + setupApprovalNeeded() setupIsAnyTokenStaked() checkIfSubtractAvailable() @@ -1150,6 +1246,12 @@ internal class StakingModel @Inject constructor( .getOrElse { false } } + private fun isCaseWithUnitializedTonAccount(): Boolean { + return value.currentStep == StakingStep.Confirmation && + isTon(cryptoCurrencyStatus.currency.network.rawId) && + !isAccountInitialized + } + private companion object { const val WHAT_IS_STAKING_ARTICLE_URL = "https://tangem.com/en/blog/post/how-to-stake-cryptocurrency/" const val ALLOWANCE_UPDATE_DELAY = 10_000L diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingNotification.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingNotification.kt index abbe28cfb5..b5485b47ba 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingNotification.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingNotification.kt @@ -60,6 +60,15 @@ internal object StakingNotification { title = resourceReference(R.string.staking_notification_low_staked_balance_title), subtitle = resourceReference(R.string.staking_notification_low_staked_balance_text), ) + + data class InitializeTonAccount(private val onInitializeClick: () -> Unit) : Info( + title = resourceReference(R.string.staking_notification_ton_account_initialization_title), + subtitle = resourceReference(R.string.staking_notification_ton_account_initialization_message), + buttonsState = NotificationConfig.ButtonsState.PrimaryButtonConfig( + text = resourceReference(R.string.common_activate), + onClick = onInitializeClick, + ), + ) } sealed class Info( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/bottomsheet/TonInitializeAccountBottomSheetConfig.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/bottomsheet/TonInitializeAccountBottomSheetConfig.kt new file mode 100644 index 0000000000..f941d083ec --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/bottomsheet/TonInitializeAccountBottomSheetConfig.kt @@ -0,0 +1,15 @@ +package com.tangem.features.staking.impl.presentation.state.bottomsheet + +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent +import com.tangem.core.ui.extensions.TextReference +import com.tangem.features.staking.impl.presentation.state.FeeState + +internal data class TonInitializeAccountBottomSheetConfig( + val title: TextReference, + val message: TextReference, + val footer: TextReference, + val onButtonClick: () -> Unit, + val isButtonEnabled: Boolean, + val isButtonLoading: Boolean, + val feeState: FeeState, +) : TangemBottomSheetConfigContent \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt index d2c18a8581..af6931c29f 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt @@ -62,13 +62,6 @@ internal sealed class StakingAlertUM : AlertUM { override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok) } - data object InitializeAccount : StakingAlertUM() { - override val onConfirmClick: (() -> Unit)? = null - override val title: TextReference = resourceReference(id = R.string.staking_error_no_validators_title) - override val message: TextReference = resourceReference(id = R.string.staking_notification_ton_activate_account) - override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok) - } - data class RewardsMinimumRequirementsError( val cryptoCurrencyName: String, val cryptoAmountValue: String, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt index bb1b446118..465bd1c024 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt @@ -47,11 +47,6 @@ internal class StakingEventFactory( stateController.updateEvent(alert) } - fun createInitializeAccountAlert() { - val alert = StakingEvent.ShowAlert(alert = StakingAlertUM.InitializeAccount) - stateController.updateEvent(alert) - } - fun createStakingRewardsMinimumRequirementsErrorAlert(cryptoCurrencyName: String, cryptoAmountValue: String) { stateController.updateEvent( StakingEvent.ShowAlert( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt index 3defda6f74..977585131e 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt @@ -76,6 +76,11 @@ internal class StakingBalanceUpdater @AssistedInject constructor( } } + suspend fun partialUpdateWithDelay() { + delay(BALANCE_UPDATE_DELAY) + partialUpdate() + } + private suspend fun fetchCurrencyStatus(delayMillis: Long = 0L) { delay(delayMillis) fetchCurrencyStatusUseCase( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt index d1ed5d5c98..d7fac733a7 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt @@ -78,4 +78,8 @@ internal object StakingClickIntentsStub : StakingClickIntents { override fun showPrimaryClickAlert() {} override fun onOpenLearnMoreAboutApproveClick() {} + + override fun onActivateTonAccountNotificationClick() {} + + override fun onActivateTonAccountClick() {} } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt index 0dbf76f8ad..1681808734 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt @@ -40,6 +40,7 @@ import java.math.BigDecimal internal class AddStakingNotificationsTransformer( private val cryptoCurrencyStatusProvider: Provider, private val appCurrencyProvider: Provider, + private val isAccountInitializedProvider: Provider, private val feeCryptoCurrencyStatus: CryptoCurrencyStatus?, private val currencyWarning: CryptoCurrencyWarning?, private val feeError: GetFeeError?, @@ -90,34 +91,40 @@ internal class AddStakingNotificationsTransformer( BigDecimal.ZERO } - val notifications = buildList { - // errors - addErrorNotifications( - prevState = prevState, - feeError = feeError, - sendingAmount = sendingAmount, - onReload = prevState.clickIntents::getFee, - feeValue = feeValue, - ) - addStakingErrorNotifications(stakingError = stakingError, onReload = prevState.clickIntents::getFee) - // warnings - addWarningNotifications( - prevState = prevState, - amountState = amountState, - feeState = feeState, - sendingAmount = sendingAmount, - isFeeCoverage = isFeeCoverage && isEnterAction && !sendingAmount.equals(minimumRequirement), - ) + val notifications = if (isAccountInitializedProvider.invoke()) { + buildList { + // errors + addErrorNotifications( + prevState = prevState, + feeError = feeError, + sendingAmount = sendingAmount, + onReload = prevState.clickIntents::getFee, + feeValue = feeValue, + ) + addStakingErrorNotifications(stakingError = stakingError, onReload = prevState.clickIntents::getFee) + // warnings + addWarningNotifications( + prevState = prevState, + amountState = amountState, + feeState = feeState, + sendingAmount = sendingAmount, + isFeeCoverage = isFeeCoverage && isEnterAction && !sendingAmount.equals(minimumRequirement), + ) - stakingInfoNotificationsFactory.addInfoNotifications( - notifications = this, - prevState = prevState, - sendingAmount = sendingAmount, - actionAmount = amountValue, - feeValue = feeValue, - tonBalanceExtraFeeThreshold = TON_BALANCE_EXTRA_FEE_THRESHOLD, - ) - }.toImmutableList() + stakingInfoNotificationsFactory.addInfoNotifications( + notifications = this, + prevState = prevState, + sendingAmount = sendingAmount, + actionAmount = amountValue, + feeValue = feeValue, + tonBalanceExtraFeeThreshold = TON_BALANCE_EXTRA_FEE_THRESHOLD, + ) + }.toImmutableList() + } else { + buildList { + addTonInitializeAccountNotification(prevState) + }.toImmutableList() + } val isActualSources = with(cryptoCurrencyStatus.value) { sources.yieldBalanceSource.isActual() && sources.networkSource.isActual() @@ -130,7 +137,8 @@ internal class AddStakingNotificationsTransformer( it is StakingNotification.Error || it is NotificationUM.Error || it is NotificationUM.Warning.NetworkFeeUnreachable || - it is StakingNotification.Warning.TransactionInProgress + it is StakingNotification.Warning.TransactionInProgress || + it is StakingNotification.Warning.InitializeTonAccount } && isActualSources, ), ) @@ -219,7 +227,6 @@ internal class AddStakingNotificationsTransformer( ) { val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() val appCurrency = appCurrencyProvider() - cryptoCurrencyStatus.currency addRentExemptionNotification( rentWarning = currencyCheck.rentWarning, @@ -282,6 +289,19 @@ internal class AddStakingNotificationsTransformer( } } + private fun MutableList.addTonInitializeAccountNotification(prevState: StakingUiState) { + val isAccountInitialized = isAccountInitializedProvider.invoke() + val cryptoCurrencyNetworkIdValue = cryptoCurrencyStatusProvider().currency.network.rawId + + if (isTon(cryptoCurrencyNetworkIdValue) && !isAccountInitialized) { + add( + StakingNotification.Warning.InitializeTonAccount( + onInitializeClick = prevState.clickIntents::onActivateTonAccountNotificationClick, + ), + ) + } + } + private companion object { val TON_BALANCE_EXTRA_FEE_THRESHOLD = BigDecimal(0.2) } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/CompleteInitializeBottomSheetTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/CompleteInitializeBottomSheetTransformer.kt new file mode 100644 index 0000000000..7a9bc02057 --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/CompleteInitializeBottomSheetTransformer.kt @@ -0,0 +1,53 @@ +package com.tangem.features.staking.impl.presentation.state.transformers.ton + +import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer +import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer.ReduceByData +import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.features.staking.impl.presentation.state.FeeState +import com.tangem.features.staking.impl.presentation.state.StakingStates +import com.tangem.features.staking.impl.presentation.state.StakingUiState +import com.tangem.features.staking.impl.presentation.state.bottomsheet.TonInitializeAccountBottomSheetConfig +import com.tangem.utils.transformer.Transformer +import java.math.BigDecimal + +internal class CompleteInitializeBottomSheetTransformer( + private val cryptoCurrencyStatus: CryptoCurrencyStatus, + private val minimumTransactionAmount: EnterAmountBoundary?, +) : Transformer { + + override fun transform(prevState: StakingUiState): StakingUiState { + val prevBottomSheetConfig = prevState.bottomSheetConfig ?: return prevState + val prevBottomSheetConfigContent = + prevBottomSheetConfig.content as? TonInitializeAccountBottomSheetConfig ?: return prevState + + val feeAmount = (prevBottomSheetConfigContent.feeState as? FeeState.Content) + ?.fee?.amount?.value?.multiply(BigDecimal(FEE_MULTIPLIER)) ?: return prevState + + val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data ?: return prevState + + return prevState.copy( + amountState = AmountReduceByTransformer( + cryptoCurrencyStatus = cryptoCurrencyStatus, + minimumTransactionAmount = minimumTransactionAmount, + value = ReduceByData( + feeAmount, + feeAmount, + ), + ).transform(prevState.amountState), + confirmationState = confirmationState.copy( + reduceAmountBy = feeAmount, + ), + bottomSheetConfig = prevBottomSheetConfig.copy( + content = prevBottomSheetConfigContent.copy( + isButtonLoading = true, + isButtonEnabled = false, + ), + ), + ) + } + + private companion object { + const val FEE_MULTIPLIER = 1.1 + } +} \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/SetFeeErrorToTonInitializeBottomSheetTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/SetFeeErrorToTonInitializeBottomSheetTransformer.kt new file mode 100644 index 0000000000..644e344be8 --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/SetFeeErrorToTonInitializeBottomSheetTransformer.kt @@ -0,0 +1,25 @@ +package com.tangem.features.staking.impl.presentation.state.transformers.ton + +import com.tangem.features.staking.impl.presentation.state.FeeState +import com.tangem.features.staking.impl.presentation.state.StakingUiState +import com.tangem.features.staking.impl.presentation.state.bottomsheet.TonInitializeAccountBottomSheetConfig +import com.tangem.utils.transformer.Transformer + +internal class SetFeeErrorToTonInitializeBottomSheetTransformer : Transformer { + + override fun transform(prevState: StakingUiState): StakingUiState { + val prevBottomSheetConfig = prevState.bottomSheetConfig ?: return prevState + val prevBottomSheetConfigContent = + prevBottomSheetConfig.content as? TonInitializeAccountBottomSheetConfig ?: return prevState + + return prevState.copy( + bottomSheetConfig = prevBottomSheetConfig.copy( + content = prevBottomSheetConfigContent.copy( + isButtonEnabled = false, + feeState = FeeState.Error, + isButtonLoading = false, + ), + ), + ) + } +} \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/SetFeeToTonInitializeBottomSheetTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/SetFeeToTonInitializeBottomSheetTransformer.kt new file mode 100644 index 0000000000..659bc1e3ab --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/SetFeeToTonInitializeBottomSheetTransformer.kt @@ -0,0 +1,41 @@ +package com.tangem.features.staking.impl.presentation.state.transformers.ton + +import com.tangem.blockchain.common.transaction.Fee +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.features.staking.impl.presentation.state.FeeState +import com.tangem.features.staking.impl.presentation.state.StakingUiState +import com.tangem.features.staking.impl.presentation.state.bottomsheet.TonInitializeAccountBottomSheetConfig +import com.tangem.utils.Provider +import com.tangem.utils.transformer.Transformer + +internal class SetFeeToTonInitializeBottomSheetTransformer( + private val appCurrencyProvider: Provider, + private val feeCryptoCurrencyStatus: CryptoCurrencyStatus?, + private val fee: Fee, + private val isFeeApproximate: Boolean, +) : Transformer { + + override fun transform(prevState: StakingUiState): StakingUiState { + val prevBottomSheetConfig = prevState.bottomSheetConfig ?: return prevState + val prevBottomSheetConfigContent = + prevBottomSheetConfig.content as? TonInitializeAccountBottomSheetConfig ?: return prevState + + val isFeeConvertibleToFiat = feeCryptoCurrencyStatus?.currency?.network?.hasFiatFeeRate == true + return prevState.copy( + bottomSheetConfig = prevBottomSheetConfig.copy( + content = prevBottomSheetConfigContent.copy( + isButtonEnabled = true, + isButtonLoading = false, + feeState = FeeState.Content( + fee = fee, + rate = feeCryptoCurrencyStatus?.value?.fiatRate, + isFeeConvertibleToFiat = isFeeConvertibleToFiat, + appCurrency = appCurrencyProvider(), + isFeeApproximate = isFeeApproximate, + ), + ), + ), + ) + } +} \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/ShowTonInitializeBottomSheetTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/ShowTonInitializeBottomSheetTransformer.kt new file mode 100644 index 0000000000..27e17d0ca7 --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/ton/ShowTonInitializeBottomSheetTransformer.kt @@ -0,0 +1,32 @@ +package com.tangem.features.staking.impl.presentation.state.transformers.ton + +import com.tangem.common.ui.R +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.features.staking.impl.presentation.state.FeeState +import com.tangem.features.staking.impl.presentation.state.StakingUiState +import com.tangem.features.staking.impl.presentation.state.bottomsheet.TonInitializeAccountBottomSheetConfig +import com.tangem.utils.transformer.Transformer + +internal class ShowTonInitializeBottomSheetTransformer( + private val onDismiss: () -> Unit, +) : Transformer { + + override fun transform(prevState: StakingUiState): StakingUiState { + return prevState.copy( + bottomSheetConfig = TangemBottomSheetConfig( + isShown = true, + onDismissRequest = onDismiss, + content = TonInitializeAccountBottomSheetConfig( + title = resourceReference(R.string.staking_account_initialization_title), + message = resourceReference(R.string.staking_account_initialization_message), + footer = resourceReference(R.string.staking_account_initialization_footer), + onButtonClick = prevState.clickIntents::onActivateTonAccountClick, + isButtonEnabled = false, + feeState = FeeState.Loading, + isButtonLoading = false, + ), + ), + ) + } +} \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt index 3e5d834e16..0196216ea0 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt @@ -28,8 +28,10 @@ import com.tangem.features.staking.impl.presentation.state.StakingStep import com.tangem.features.staking.impl.presentation.state.StakingUiState import com.tangem.features.staking.impl.presentation.state.bottomsheet.StakingActionSelectionBottomSheetConfig import com.tangem.features.staking.impl.presentation.state.bottomsheet.StakingInfoBottomSheetConfig +import com.tangem.features.staking.impl.presentation.state.bottomsheet.TonInitializeAccountBottomSheetConfig import com.tangem.features.staking.impl.presentation.ui.bottomsheet.StakingActionSelectorBottomSheet import com.tangem.features.staking.impl.presentation.ui.bottomsheet.StakingInfoBottomSheet +import com.tangem.features.staking.impl.presentation.ui.bottomsheet.TonInitializeAccountBottomSheet import kotlinx.coroutines.delay import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map @@ -83,6 +85,7 @@ fun StakingBottomSheet(bottomSheetConfig: TangemBottomSheetConfig?) { is StakingInfoBottomSheetConfig -> StakingInfoBottomSheet(bottomSheetConfig) is GiveTxPermissionBottomSheetConfig -> GiveTxPermissionBottomSheet(bottomSheetConfig) is StakingActionSelectionBottomSheetConfig -> StakingActionSelectorBottomSheet(bottomSheetConfig) + is TonInitializeAccountBottomSheetConfig -> TonInitializeAccountBottomSheet(bottomSheetConfig) } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/bottomsheet/TonInitializeAccountBottomSheet.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/bottomsheet/TonInitializeAccountBottomSheet.kt new file mode 100644 index 0000000000..21be5002e8 --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/bottomsheet/TonInitializeAccountBottomSheet.kt @@ -0,0 +1,158 @@ +package com.tangem.features.staking.impl.presentation.ui.bottomsheet + +import android.content.res.Configuration +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.tangem.blockchain.common.Amount +import com.tangem.blockchain.common.AmountType +import com.tangem.blockchain.common.transaction.Fee +import com.tangem.common.ui.R +import com.tangem.core.ui.components.SpacerH +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet +import com.tangem.core.ui.components.buttons.common.TangemButton +import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition +import com.tangem.core.ui.components.buttons.common.TangemButtonSize +import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults +import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.features.staking.impl.presentation.state.FeeState +import com.tangem.features.staking.impl.presentation.state.bottomsheet.TonInitializeAccountBottomSheetConfig +import com.tangem.features.staking.impl.presentation.ui.block.StakingFeeBlock +import java.math.BigDecimal + +@Composable +internal fun TonInitializeAccountBottomSheet(config: TangemBottomSheetConfig) { + TangemBottomSheet( + config = config, + containerColor = TangemTheme.colors.background.tertiary, + ) { content -> + Column( + modifier = Modifier + .padding( + start = TangemTheme.dimens.spacing16, + end = TangemTheme.dimens.spacing16, + bottom = TangemTheme.dimens.spacing16, + ) + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + SpacerH(height = 16.dp) + Image( + painter = painterResource(id = R.drawable.img_ton_22), + modifier = Modifier.size(56.dp), + contentDescription = null, + ) + + SpacerH(height = 24.dp) + + Text( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + text = content.title.resolveReference(), + style = TangemTheme.typography.h3, + color = TangemTheme.colors.text.primary1, + textAlign = TextAlign.Center, + ) + + SpacerH(height = 16.dp) + + Text( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + text = content.message.resolveReference(), + style = TangemTheme.typography.body2, + color = TangemTheme.colors.text.secondary, + textAlign = TextAlign.Center, + ) + + SpacerH(height = 24.dp) + + StakingFeeBlock(content.feeState) + + SpacerH(height = 12.dp) + + Text( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + text = content.footer.resolveReference(), + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.tertiary, + textAlign = TextAlign.Center, + ) + + SpacerH(height = 20.dp) + + TangemButton( + text = stringResourceSafe(R.string.common_activate), + icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_tangem_24), + onClick = content.onButtonClick, + colors = TangemButtonsDefaults.primaryButtonColors, + showProgress = content.feeState is FeeState.Loading || content.isButtonLoading, + enabled = content.isButtonEnabled, + size = TangemButtonSize.WideAction, + textStyle = TangemTheme.typography.subtitle1, + modifier = Modifier.fillMaxWidth(), + ) + + SpacerH(height = 8.dp) + } + } +} + +// region Preview +@Composable +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +private fun Preview_TonInitializeAccountBottomSheetContent() { + TangemThemePreview { + TonInitializeAccountBottomSheet( + config = TangemBottomSheetConfig( + isShown = true, + onDismissRequest = {}, + content = TonInitializeAccountBottomSheetConfig( + title = resourceReference(R.string.staking_account_initialization_title), + message = resourceReference(R.string.staking_account_initialization_message), + footer = resourceReference(R.string.staking_account_initialization_footer), + onButtonClick = {}, + isButtonEnabled = true, + isButtonLoading = false, + feeState = FeeState.Content( + fee = Fee.Common( + amount = Amount( + currencySymbol = "MATIC", + value = BigDecimal(0.159806), + decimals = 18, + type = AmountType.Coin, + ), + ), + rate = BigDecimal.ONE, + appCurrency = AppCurrency.Default, + isFeeApproximate = false, + isFeeConvertibleToFiat = true, + ), + ), + + ), + ) + } +} +// endregion Preview \ No newline at end of file diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt index cb90d135f8..9710aa7b07 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt @@ -241,8 +241,8 @@ internal class SwapNotificationsFactory( ) { add( SwapNotificationUM.Info.PermissionNeeded( - providerName = fromToken.symbol, - fromTokenSymbol = providerName, + providerName = providerName, + fromTokenSymbol = fromToken.symbol, onApproveClick = actions.openPermissionBottomSheet, ), ) diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/SwapNotificationUM.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/SwapNotificationUM.kt index 317e905564..d140ef1ff0 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/SwapNotificationUM.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/SwapNotificationUM.kt @@ -208,7 +208,7 @@ internal object SwapNotificationUM { ), iconResId = R.drawable.ic_locked_24, buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig( - text = TextReference.Res(R.string.common_approve), + text = TextReference.Res(R.string.give_permission_title), onClick = onApproveClick, ), ) diff --git a/gradle.properties b/gradle.properties index 0e6c69b832..6ac9926e82 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,16 +2,15 @@ # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs = -Xmx6144m -XX:MaxMetaspaceSize=768m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -org.gradle.parallel = true -org.gradle.daemon = true -android.useAndroidX = true -org.gradle.unsafe.configuration-cache = true -android.nonTransitiveRClass = false +org.gradle.jvmargs=-Xmx8g -XX:MaxMetaspaceSize=1g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +org.gradle.parallel=true +org.gradle.workers.max=8 +org.gradle.daemon=true +org.gradle.caching=true +org.gradle.configuration-cache=true + +android.useAndroidX=true +android.nonTransitiveRClass=false + +kotlin.incremental=true \ No newline at end of file