From 96784ebd43cb4e70206e3aacca83db4416e64b86 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 18 Jan 2026 13:56:25 +0300 Subject: [PATCH] Updated on 2026-08-14 --- core/res/src/main/res/values-ja/strings.xml | 2 + core/res/src/main/res/values/strings.xml | 1 + .../send/v2/api/entity/FeeSelectorUM.kt | 1 + .../extended/ui/FeeExtendedSelectorContent.kt | 2 + .../speed/ui/FeeSpeedSelectorContent.kt | 8 +++ .../v2/feeselector/model/FeeSelectorLogic.kt | 52 +++++++++++-------- .../FeeSelectorErrorTransformer.kt | 7 +++ .../FeeSelectorTokenSelectedTransformer.kt | 1 + 8 files changed, 53 insertions(+), 21 deletions(-) diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 6ac1337a55..5197f96905 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -552,6 +552,7 @@ Tangemへのフィードバック 取引を送信できません コインの説明エラー + ガス代不要の取引手数料 エラーが発生しました エラーが発生しました。コード: %s 。 メモが必要 @@ -973,6 +974,7 @@ アクセスコードの復元 同一のカード アクセスコード + 同時に利用できるのは、モバイルウォレットまたはハードウェアウォレットのいずれか一方のみです。Tangemのコールドウォレットを使用するには、ウォレットをアップグレードするか、アプリから削除してください。 すべてのオファー %sで利用可能 プロバイダーが取引を促進します diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 128a5d68c7..a5e90a215a 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -560,6 +560,7 @@ Tangem feedback Can\'t send a transaction Coin description error + Not enough funds Gasless transaction fee An error occurred An error occurred. Code: %s. diff --git a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt index 3706fa2f92..9d92d11e1c 100644 --- a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt +++ b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt @@ -68,6 +68,7 @@ data class FeeExtraInfo( val feeCryptoCurrencyStatus: CryptoCurrencyStatus, val availableFeeCurrencies: ImmutableList? = null, val transactionFeeExtended: TransactionFeeExtended? = null, + val isNotEnoughFunds: Boolean = false, ) sealed class FeeNonce { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/ui/FeeExtendedSelectorContent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/ui/FeeExtendedSelectorContent.kt index eef8cc085a..e084555a7b 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/ui/FeeExtendedSelectorContent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/ui/FeeExtendedSelectorContent.kt @@ -98,6 +98,7 @@ fun FeeExtendedSelectorContent(state: FeeExtendedSelectorUM, modifier: Modifier }, ellipsizeOffset = fee.amount.currencySymbol.length, showSelectorIcon = isChooseSpeedAvailable, + isNotEnoughFunds = state.parent.feeExtraInfo.isNotEnoughFunds, isLoading = state.fee.isLoading(), ) } @@ -168,6 +169,7 @@ private fun Preview() { isFeeConvertibleToFiat = true, isTronToken = false, feeCryptoCurrencyStatus = cryptoCurrencyStatus, + isNotEnoughFunds = true, ), feeNonce = FeeNonce.None, feeFiatRateUM = FeeFiatRateUM( diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/speed/ui/FeeSpeedSelectorContent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/speed/ui/FeeSpeedSelectorContent.kt index 89a8ed3660..ef604613c9 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/speed/ui/FeeSpeedSelectorContent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/speed/ui/FeeSpeedSelectorContent.kt @@ -328,6 +328,7 @@ internal fun RegularFeeItemContent( ellipsizeOffset: Int? = null, showSelectorIcon: Boolean = false, isLoading: Boolean = false, + isNotEnoughFunds: Boolean = false, ) { Column(modifier = modifier) { Row( @@ -353,6 +354,7 @@ internal fun RegularFeeItemContent( postDot = postDot, ellipsizeOffset = ellipsizeOffset, isLoading = isLoading, + isNotEnoughFunds = isNotEnoughFunds, ) if (showSelectorIcon) { @@ -376,6 +378,7 @@ private fun FeeDescription( postDot: TextReference? = null, ellipsizeOffset: Int? = null, isLoading: Boolean = false, + isNotEnoughFunds: Boolean = false, ) { Column(modifier = modifier, verticalArrangement = Arrangement.spacedBy(2.dp)) { Text( @@ -385,6 +388,11 @@ private fun FeeDescription( modifier = Modifier.testTag(SendSelectNetworkFeeBottomSheetTestTags.REGULAR_ITEM_TITLE), ) when { + isNotEnoughFunds -> Text( + text = stringResourceSafe(R.string.gasless_not_enough_funds_to_cover_token_fee), + color = TangemTheme.colors.text.warning, + style = TangemTheme.typography.caption1, + ) isLoading -> TextShimmer( modifier = Modifier.width(122.dp), style = TangemTheme.typography.caption1, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt index 8afabe494a..100d288151 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt @@ -3,6 +3,7 @@ package com.tangem.features.send.v2.feeselector.model import arrow.core.Either import arrow.core.flatMap import arrow.core.getOrElse +import arrow.core.left import arrow.core.raise.either import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.transaction.TransactionFee @@ -228,10 +229,13 @@ internal class FeeSelectorLogic @AssistedInject constructor( return extended(selectedTokenOrNull).fold( ifLeft = { error -> - if (error is GetFeeError.GaslessError) { - params.onLoadFee().map { LoadedFeeResult.Basic(it) } - } else { - Either.Left(error) + when (error) { + is GetFeeError.GaslessError.NotEnoughFunds -> error.left() + is GetFeeError.GaslessError -> { + // Something wrong with gasless fee, fallback to basic fee + params.onLoadFee().map { LoadedFeeResult.Basic(it) } + } + else -> error.left() } }, ifRight = { fee -> @@ -243,32 +247,38 @@ internal class FeeSelectorLogic @AssistedInject constructor( private suspend fun populateExtendedFee( fee: TransactionFeeExtended, ): Either = either { - val selectedToken = if (params.feeCryptoCurrencyStatus.currency.id != fee.feeTokenId) { - getSingleCryptoCurrencyStatusUseCase - .invokeMultiWalletSync( - userWalletId = params.userWalletId, - cryptoCurrencyId = fee.feeTokenId, - ).getOrElse { - raise(GetFeeError.DataError(IllegalStateException("No token found for id: ${fee.feeTokenId}"))) - } - } else { - params.feeCryptoCurrencyStatus + LoadedFeeResult.Extended( + fee = fee, + selectedToken = getSelectedTokenStatus(fee.feeTokenId).bind(), + availableTokens = getAvailableFeeTokens().bind(), + ) + } + + private suspend fun getSelectedTokenStatus(tokenId: CryptoCurrency.ID): Either = + either { + val feeTokenId = tokenId + if (params.feeCryptoCurrencyStatus.currency.id != feeTokenId) { + getSingleCryptoCurrencyStatusUseCase + .invokeMultiWalletSync( + userWalletId = params.userWalletId, + cryptoCurrencyId = feeTokenId, + ).getOrElse { + raise(GetFeeError.DataError(IllegalStateException("No token found for id: $tokenId"))) + } + } else { + params.feeCryptoCurrencyStatus + } } + private suspend fun getAvailableFeeTokens(): Either> = either { val userWallet = getUserWalletUseCase(params.userWalletId).mapLeft { GetFeeError.DataError(IllegalStateException("No wallet found for id: ${params.userWalletId}")) }.bind() - val availableTokens = getAvailableFeeTokensUseCase.invoke( + getAvailableFeeTokensUseCase.invoke( userWallet = userWallet, network = params.cryptoCurrencyStatus.currency.network, ).bind() - - LoadedFeeResult.Extended( - fee = fee, - selectedToken = selectedToken, - availableTokens = availableTokens, - ) } sealed class LoadedFeeResult { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorErrorTransformer.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorErrorTransformer.kt index 80386d5c77..7cac2f632f 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorErrorTransformer.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorErrorTransformer.kt @@ -7,6 +7,13 @@ import com.tangem.utils.transformer.Transformer internal class FeeSelectorErrorTransformer(private val error: GetFeeError) : Transformer { override fun transform(prevState: FeeSelectorUM): FeeSelectorUM { + if (prevState is FeeSelectorUM.Content && error is GetFeeError.GaslessError.NotEnoughFunds) { + return prevState.copy( + isPrimaryButtonEnabled = false, + feeExtraInfo = prevState.feeExtraInfo.copy(isNotEnoughFunds = true), + ) + } + return FeeSelectorUM.Error(error = error) } } \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorTokenSelectedTransformer.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorTokenSelectedTransformer.kt index f11d9c8dd9..c054119f3d 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorTokenSelectedTransformer.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorTokenSelectedTransformer.kt @@ -18,6 +18,7 @@ class FeeSelectorTokenSelectedTransformer( feeItems = persistentListOf(FeeItem.Loading), feeExtraInfo = prevState.feeExtraInfo.copy( feeCryptoCurrencyStatus = selectedToken, + isNotEnoughFunds = false, ), ) } else {