Updated on 2026-08-14
This commit is contained in:
parent
8889ad4c31
commit
d2518865d1
39 changed files with 414 additions and 57 deletions
|
|
@ -1,10 +1,13 @@
|
|||
package com.tangem.features.send.impl.presentation.state
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.features.send.impl.R
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal sealed class SendNotification(val config: NotificationConfig) {
|
||||
|
||||
|
|
@ -186,4 +189,46 @@ internal sealed class SendNotification(val config: NotificationConfig) {
|
|||
),
|
||||
)
|
||||
}
|
||||
|
||||
sealed interface Koinos {
|
||||
data class InsufficientRecoverableMana(
|
||||
val mana: BigDecimal,
|
||||
val maxMana: BigDecimal,
|
||||
) : Error(
|
||||
title = resourceReference(R.string.koinos_insufficient_mana_to_send_koin_title),
|
||||
subtitle = resourceReference(
|
||||
R.string.koinos_insufficient_mana_to_send_koin_description,
|
||||
formatArgs = wrappedList(
|
||||
BigDecimalFormatter.formatCryptoAmountShorted(mana, "", Blockchain.Koinos.decimals()),
|
||||
BigDecimalFormatter.formatCryptoAmountShorted(maxMana, "", Blockchain.Koinos.decimals()),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
data object InsufficientBalance : Error(
|
||||
title = resourceReference(R.string.koinos_insufficient_balance_to_send_koin_title),
|
||||
subtitle = resourceReference(R.string.koinos_insufficient_balance_to_send_koin_description),
|
||||
)
|
||||
|
||||
data class ManaExceedsBalance(
|
||||
val availableKoinForTransfer: BigDecimal,
|
||||
val onReduceClick: () -> Unit,
|
||||
) : Error(
|
||||
title = resourceReference(R.string.koinos_mana_exceeds_koin_balance_title),
|
||||
subtitle = resourceReference(
|
||||
R.string.koinos_mana_exceeds_koin_balance_description,
|
||||
formatArgs = wrappedList(
|
||||
BigDecimalFormatter.formatCryptoAmount(
|
||||
availableKoinForTransfer,
|
||||
Blockchain.Koinos.currency,
|
||||
Blockchain.Koinos.decimals(),
|
||||
),
|
||||
),
|
||||
),
|
||||
buttonState = NotificationConfig.ButtonsState.PrimaryButtonConfig(
|
||||
text = resourceReference(R.string.send_notification_reduce_to, wrappedList(availableKoinForTransfer)),
|
||||
onClick = onReduceClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -60,6 +60,7 @@ internal class SendStateFactory(
|
|||
SendFeeStateConverter(
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
feeCryptoCurrencyStatusProvider = feeCryptoCurrencyStatusProvider,
|
||||
cryptoCurrencyStatusProvider = cryptoCurrencyStatusProvider,
|
||||
)
|
||||
}
|
||||
private val confirmStateConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ internal sealed class SendStates {
|
|||
val feeSelectorState: FeeSelectorState,
|
||||
val fee: Fee?,
|
||||
val rate: BigDecimal?,
|
||||
val isFeeConvertibleToFiat: Boolean,
|
||||
val appCurrency: AppCurrency,
|
||||
val isFeeApproximate: Boolean,
|
||||
val isCustomSelected: Boolean,
|
||||
|
|
|
|||
|
|
@ -101,7 +101,11 @@ internal class SendNotificationFactory(
|
|||
addTooLowNotification(feeState)
|
||||
|
||||
// blockchain specific
|
||||
addCardanoNotifications(sendingAmount, feeState.fee, state)
|
||||
addValidateTransactionNotifications(
|
||||
sendingAmount = sendingAmount,
|
||||
fee = feeState.fee,
|
||||
state = state,
|
||||
)
|
||||
}.toImmutableList()
|
||||
}
|
||||
|
||||
|
|
@ -420,13 +424,12 @@ internal class SendNotificationFactory(
|
|||
return Blockchain.fromNetworkId(this.currency.network.backendId) == Blockchain.Arbitrum
|
||||
}
|
||||
|
||||
private suspend fun MutableList<SendNotification>.addCardanoNotifications(
|
||||
private suspend fun MutableList<SendNotification>.addValidateTransactionNotifications(
|
||||
sendingAmount: BigDecimal,
|
||||
fee: Fee?,
|
||||
state: SendUiState,
|
||||
) {
|
||||
val sendingCurrency = cryptoCurrencyStatusProvider().currency
|
||||
if (!BlockchainUtils.isCardano(sendingCurrency.network.id.value)) return
|
||||
|
||||
validateTransactionUseCase(
|
||||
amount = sendingAmount.convertToAmount(sendingCurrency),
|
||||
|
|
@ -437,10 +440,14 @@ internal class SendNotificationFactory(
|
|||
network = sendingCurrency.network,
|
||||
).fold(
|
||||
ifLeft = {
|
||||
addCardanoTransactionValidationError(
|
||||
error = it as? BlockchainSdkError.Cardano ?: return@fold,
|
||||
sendingCurrency = sendingCurrency,
|
||||
)
|
||||
when (it) {
|
||||
is BlockchainSdkError.Cardano -> addCardanoTransactionValidationError(
|
||||
error = it,
|
||||
sendingCurrency = sendingCurrency,
|
||||
)
|
||||
is BlockchainSdkError.Koinos -> addKoinosTransactionValidationError(error = it)
|
||||
else -> return
|
||||
}
|
||||
},
|
||||
ifRight = {
|
||||
(fee as? Fee.CardanoToken)?.let {
|
||||
|
|
@ -488,6 +495,36 @@ internal class SendNotificationFactory(
|
|||
}
|
||||
}
|
||||
|
||||
private fun MutableList<SendNotification>.addKoinosTransactionValidationError(error: BlockchainSdkError.Koinos) {
|
||||
when (error) {
|
||||
is BlockchainSdkError.Koinos.InsufficientBalance -> {
|
||||
add(SendNotification.Koinos.InsufficientBalance)
|
||||
}
|
||||
is BlockchainSdkError.Koinos.InsufficientMana -> {
|
||||
add(
|
||||
SendNotification.Koinos.InsufficientRecoverableMana(
|
||||
mana = error.manaBalance ?: BigDecimal.ZERO,
|
||||
maxMana = error.maxMana ?: BigDecimal.ZERO,
|
||||
),
|
||||
)
|
||||
}
|
||||
is BlockchainSdkError.Koinos.ManaFeeExceedsBalance -> {
|
||||
add(
|
||||
SendNotification.Koinos.ManaExceedsBalance(
|
||||
availableKoinForTransfer = error.availableKoinForTransfer,
|
||||
onReduceClick = {
|
||||
clickIntents.onAmountReduceClick(
|
||||
reduceAmountTo = error.availableKoinForTransfer,
|
||||
clazz = SendNotification.Koinos.InsufficientRecoverableMana::class.java,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun MutableList<SendNotification>.addDustWarningNotification(
|
||||
feeValue: BigDecimal,
|
||||
sendingAmount: BigDecimal,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
internal class SendFeeStateConverter(
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val feeCryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus?>,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||
) : Converter<Unit, SendStates.FeeState> {
|
||||
|
||||
override fun convert(value: Unit): SendStates.FeeState {
|
||||
|
|
@ -21,6 +22,7 @@ internal class SendFeeStateConverter(
|
|||
appCurrency = appCurrencyProvider(),
|
||||
isFeeApproximate = false,
|
||||
isCustomSelected = false,
|
||||
isFeeConvertibleToFiat = cryptoCurrencyStatusProvider().currency.network.hasFiatFeeRate,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -82,6 +82,7 @@ internal object FeeStatePreviewData {
|
|||
isFeeApproximate = false,
|
||||
notifications = persistentListOf(),
|
||||
isCustomSelected = false,
|
||||
isFeeConvertibleToFiat = true,
|
||||
)
|
||||
|
||||
val feeChoosableState = feeState.copy(
|
||||
|
|
|
|||
|
|
@ -29,16 +29,15 @@ 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.TangemButtonsDefaults
|
||||
import com.tangem.core.ui.components.keyboardAsState
|
||||
import com.tangem.core.ui.extensions.resolveAnnotatedReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.shareText
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.tokens.model.Amount
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiCurrentScreen
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiState
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiStateType
|
||||
import com.tangem.features.send.impl.presentation.utils.getFiatString
|
||||
import com.tangem.features.send.impl.presentation.utils.getCryptoReference
|
||||
|
||||
@Composable
|
||||
internal fun SendNavigationButtons(
|
||||
|
|
@ -175,7 +174,11 @@ private fun SendingText(
|
|||
val sendingFiat = if (uiState.isSubtracted) {
|
||||
fiatAmount?.value
|
||||
} else {
|
||||
feeFiat?.let { fiatAmount?.value?.plus(it) }
|
||||
if (feeState?.isFeeConvertibleToFiat == true) {
|
||||
feeFiat?.let { fiatAmount?.value?.plus(it) }
|
||||
} else {
|
||||
fiatAmount?.value
|
||||
}
|
||||
}
|
||||
|
||||
if (feeFiat != null && sendingFiat != null) {
|
||||
|
|
@ -184,14 +187,23 @@ private fun SendingText(
|
|||
fiatCurrencySymbol = feeState.appCurrency.symbol,
|
||||
fiatCurrencyCode = feeState.appCurrency.code,
|
||||
)
|
||||
val feeValue = getFiatString(
|
||||
value = feeState.fee?.amount?.value,
|
||||
rate = feeState.rate,
|
||||
appCurrency = feeState.appCurrency,
|
||||
)
|
||||
val feeValue = if (feeState.isFeeConvertibleToFiat) {
|
||||
getFiatString(
|
||||
value = feeState.fee?.amount?.value,
|
||||
rate = feeState.rate,
|
||||
appCurrency = feeState.appCurrency,
|
||||
)
|
||||
} else {
|
||||
getCryptoReference(feeState.fee?.amount, feeState.isFeeApproximate)?.resolveReference().orEmpty()
|
||||
}
|
||||
|
||||
val textResource = remember(uiState) {
|
||||
resourceReference(
|
||||
id = R.string.send_summary_transaction_description,
|
||||
id = if (feeState.isFeeConvertibleToFiat) {
|
||||
R.string.send_summary_transaction_description
|
||||
} else {
|
||||
R.string.send_summary_transaction_description_no_fiat_fee
|
||||
},
|
||||
formatArgs = wrappedList(sendingValue, feeValue),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,11 @@ internal fun SendSpeedSelectorItem(
|
|||
onSelect = onSelect,
|
||||
modifier = modifier,
|
||||
preDot = getCryptoReference(amount, state.isFeeApproximate),
|
||||
postDot = getFiatReference(amount?.value, state.rate, state.appCurrency),
|
||||
postDot = if (state.isFeeConvertibleToFiat) {
|
||||
getFiatReference(amount?.value, state.rate, state.appCurrency)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = amount?.currencySymbol?.length,
|
||||
isSelected = content?.selectedFee == feeType,
|
||||
showDivider = showDivider,
|
||||
|
|
|
|||
|
|
@ -62,7 +62,11 @@ internal fun FeeBlock(feeState: SendStates.FeeState, isClickDisabled: Boolean, o
|
|||
titleRes = title,
|
||||
iconRes = icon,
|
||||
preDot = getCryptoReference(feeAmount, feeState.isFeeApproximate),
|
||||
postDot = getFiatReference(feeAmount?.value, feeState.rate, feeState.appCurrency),
|
||||
postDot = if (feeState.isFeeConvertibleToFiat) {
|
||||
getFiatReference(feeAmount?.value, feeState.rate, feeState.appCurrency)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = feeAmount?.currencySymbol?.length,
|
||||
isSelected = true,
|
||||
showDivider = false,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue