Updated on 2026-08-14
This commit is contained in:
parent
058a6ab4d5
commit
451fdc5e0b
37 changed files with 748 additions and 226 deletions
|
|
@ -6,41 +6,70 @@ import androidx.compose.foundation.layout.*
|
|||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
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.Devices
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatString
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.components.atoms.text.EllipsisText
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.format.bigdecimal.BigDecimalFormatConstants.EMPTY_BALANCE_SIGN
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fee
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
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.send.v2.api.FeeSelectorBlockComponent
|
||||
import com.tangem.features.send.v2.api.params.FeeSelectorParams
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeFiatRateUM
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeItem
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeSelectorUM
|
||||
import com.tangem.features.send.v2.feeselector.entity.PrimaryButtonConfig
|
||||
import com.tangem.features.send.v2.feeselector.model.FeeSelectorModel
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
internal class DefaultFeeSelectorBlockComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted params: Unit,
|
||||
@Assisted params: FeeSelectorParams.FeeSelectorBlockParams,
|
||||
) : FeeSelectorBlockComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: FeeSelectorModel = getOrCreateModel(params = params)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
FeeSelectorBlockContent(modifier = modifier)
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
FeeSelectorBlockContent(modifier = modifier, state = state)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : FeeSelectorBlockComponent.Factory {
|
||||
override fun create(context: AppComponentContext, params: Unit): DefaultFeeSelectorBlockComponent
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: FeeSelectorParams.FeeSelectorBlockParams,
|
||||
): DefaultFeeSelectorBlockComponent
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FeeSelectorBlockContent(modifier: Modifier = Modifier) {
|
||||
private fun FeeSelectorBlockContent(state: FeeSelectorUM, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.background(TangemTheme.colors.background.action)
|
||||
|
|
@ -67,26 +96,90 @@ private fun FeeSelectorBlockContent(modifier: Modifier = Modifier) {
|
|||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Text(
|
||||
text = "~ 0.25 \$",
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.size(width = 18.dp, height = 24.dp),
|
||||
painter = painterResource(id = R.drawable.ic_select_18_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
SpacerWMax()
|
||||
when (state) {
|
||||
is FeeSelectorUM.Content -> FeeContent(state)
|
||||
is FeeSelectorUM.Loading -> FeeLoading()
|
||||
is FeeSelectorUM.Error -> FeeError()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RowScope.FeeError() {
|
||||
Text(
|
||||
text = EMPTY_BALANCE_SIGN,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.body2,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RowScope.FeeLoading() {
|
||||
TextShimmer(
|
||||
radius = TangemTheme.dimens.radius3,
|
||||
style = TangemTheme.typography.body1,
|
||||
modifier = Modifier.width(width = TangemTheme.dimens.size90),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RowScope.FeeContent(state: FeeSelectorUM.Content) {
|
||||
EllipsisText(
|
||||
text = if (state.feeFiatRateUM != null) {
|
||||
getFiatString(
|
||||
value = state.selectedFeeItem.fee.amount.value,
|
||||
rate = state.feeFiatRateUM.rate,
|
||||
appCurrency = state.feeFiatRateUM.appCurrency,
|
||||
approximate = state.isFeeApproximate,
|
||||
)
|
||||
} else {
|
||||
state.selectedFeeItem.fee.amount.value.format {
|
||||
crypto(
|
||||
symbol = state.selectedFeeItem.fee.amount.currencySymbol,
|
||||
decimals = state.selectedFeeItem.fee.amount.decimals,
|
||||
).fee(canBeLower = state.isFeeApproximate)
|
||||
}
|
||||
},
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.End,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(start = TangemTheme.dimens.spacing4),
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.size(width = 18.dp, height = 24.dp),
|
||||
painter = painterResource(id = R.drawable.ic_select_18_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO)
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun FeeSelectorBlockContent_Preview() {
|
||||
TangemThemePreview {
|
||||
FeeSelectorBlockContent(modifier = Modifier.fillMaxWidth())
|
||||
val feeItem = FeeItem.Market(
|
||||
Fee.Common(amount = Amount(value = BigDecimal("0.0002876"), blockchain = Blockchain.Ethereum)),
|
||||
)
|
||||
FeeSelectorBlockContent(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state = FeeSelectorUM.Content(
|
||||
doneButtonConfig = PrimaryButtonConfig(enabled = true, onClick = {}),
|
||||
feeItems = persistentListOf(feeItem),
|
||||
onFeeSelected = {},
|
||||
selectedFeeItem = feeItem,
|
||||
isFeeApproximate = false,
|
||||
feeFiatRateUM = FeeFiatRateUM(
|
||||
rate = BigDecimal("2500"),
|
||||
appCurrency = AppCurrency.Default,
|
||||
),
|
||||
displayNonceInput = false,
|
||||
nonce = null,
|
||||
onNonceChange = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
package com.tangem.features.send.v2.feeselector.entity
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -12,33 +13,44 @@ import java.math.BigInteger
|
|||
@Immutable
|
||||
internal sealed class FeeSelectorUM {
|
||||
|
||||
data object Loading : FeeSelectorUM()
|
||||
abstract val doneButtonConfig: PrimaryButtonConfig
|
||||
|
||||
data class Loading(private val onDone: () -> Unit) : FeeSelectorUM() {
|
||||
override val doneButtonConfig = PrimaryButtonConfig(enabled = false, onClick = onDone)
|
||||
}
|
||||
|
||||
data class Error(val error: GetFeeError, private val onDone: () -> Unit) : FeeSelectorUM() {
|
||||
override val doneButtonConfig = PrimaryButtonConfig(enabled = false, onClick = onDone)
|
||||
}
|
||||
|
||||
data class Content(
|
||||
val isDoneEnabled: Boolean,
|
||||
override val doneButtonConfig: PrimaryButtonConfig,
|
||||
val feeItems: ImmutableList<FeeItem>,
|
||||
val onFeeSelected: (FeeItem) -> Unit,
|
||||
val selectedFeeItem: FeeItem,
|
||||
val isFeeApproximate: Boolean,
|
||||
val feeFiatRateDataHolder: FeeFiatRateDataHolder?,
|
||||
val feeFiatRateUM: FeeFiatRateUM?,
|
||||
val displayNonceInput: Boolean,
|
||||
val nonce: BigInteger?,
|
||||
val onNonceChange: (String) -> Unit,
|
||||
) : FeeSelectorUM()
|
||||
}
|
||||
|
||||
internal data class PrimaryButtonConfig(val enabled: Boolean, val onClick: () -> Unit)
|
||||
|
||||
@Immutable
|
||||
data class FeeFiatRateDataHolder(
|
||||
internal data class FeeFiatRateUM(
|
||||
val rate: BigDecimal,
|
||||
val appCurrency: AppCurrency,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal sealed class FeeItem {
|
||||
abstract val onSelect: () -> Unit
|
||||
abstract val fee: Fee
|
||||
|
||||
data class Suggested(val title: TextReference, val amount: Amount, override val onSelect: () -> Unit) : FeeItem()
|
||||
data class Slow(val amount: Amount, override val onSelect: () -> Unit) : FeeItem()
|
||||
data class Market(val amount: Amount, override val onSelect: () -> Unit) : FeeItem()
|
||||
data class Fast(val amount: Amount, override val onSelect: () -> Unit) : FeeItem()
|
||||
data class Custom(val customValues: ImmutableList<CustomFeeFieldUM>, override val onSelect: () -> Unit) : FeeItem()
|
||||
data class Suggested(val title: TextReference, override val fee: Fee) : FeeItem()
|
||||
data class Slow(override val fee: Fee) : FeeItem()
|
||||
data class Market(override val fee: Fee) : FeeItem()
|
||||
data class Fast(override val fee: Fee) : FeeItem()
|
||||
data class Custom(override val fee: Fee, val customValues: ImmutableList<CustomFeeFieldUM>) : FeeItem()
|
||||
}
|
||||
|
|
@ -1,31 +1,101 @@
|
|||
package com.tangem.features.send.v2.feeselector.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.features.send.v2.api.FeeSelectorComponent
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase
|
||||
import com.tangem.features.send.v2.api.params.FeeSelectorParams
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeItem
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeSelectorUM
|
||||
import com.tangem.features.send.v2.feeselector.model.transformers.FeeItemSelectedTransformer
|
||||
import com.tangem.features.send.v2.feeselector.model.transformers.FeeSelectorErrorTransformer
|
||||
import com.tangem.features.send.v2.feeselector.model.transformers.FeeSelectorLoadedTransformer
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.transformer.update
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class FeeSelectorModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
private val isFeeApproximateUseCase: IsFeeApproximateUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val router: Router,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private val params = paramsContainer.require<FeeSelectorComponent.Params>()
|
||||
private val params = paramsContainer.require<FeeSelectorParams.FeeSelectorBlockParams>()
|
||||
private var appCurrency: AppCurrency = AppCurrency.Default
|
||||
|
||||
val uiState: StateFlow<FeeSelectorUM>
|
||||
field = MutableStateFlow<FeeSelectorUM>(FeeSelectorUM.Loading)
|
||||
field = MutableStateFlow<FeeSelectorUM>(FeeSelectorUM.Loading(onDone = ::onDone))
|
||||
|
||||
init {
|
||||
initAppCurrency()
|
||||
loadFee()
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
router.pop()
|
||||
}
|
||||
|
||||
private fun initAppCurrency() {
|
||||
modelScope.launch {
|
||||
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadFee() {
|
||||
modelScope.launch {
|
||||
params.onLoadFee()
|
||||
.fold(
|
||||
ifLeft = { uiState.update(FeeSelectorErrorTransformer(it)) },
|
||||
ifRight = {
|
||||
uiState.update(
|
||||
FeeSelectorLoadedTransformer(
|
||||
cryptoCurrencyStatus = params.cryptoCurrencyStatus,
|
||||
appCurrency = appCurrency,
|
||||
fees = it,
|
||||
suggestedFeeState = params.suggestedFeeState,
|
||||
isFeeApproximate = isFeeApproximate(it.normal.amount.type),
|
||||
onFeeSelected = ::onFeeItemSelected,
|
||||
onCustomFeeValueChange = ::onCustomFeeValueChange,
|
||||
onNextClick = ::onNextClick,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isFeeApproximate(amountType: AmountType): Boolean {
|
||||
val networkId = params.network.id
|
||||
return isFeeApproximateUseCase(networkId = networkId, amountType = amountType)
|
||||
}
|
||||
|
||||
private fun onFeeItemSelected(feeItem: FeeItem) {
|
||||
uiState.update(FeeItemSelectedTransformer(feeItem))
|
||||
}
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private fun onCustomFeeValueChange(index: Int, value: String) {
|
||||
// TODO: [REDACTED_JIRA]
|
||||
}
|
||||
|
||||
private fun onNextClick() {
|
||||
// TODO: [REDACTED_JIRA]
|
||||
}
|
||||
|
||||
private fun onDone() {
|
||||
// TODO: [REDACTED_JIRA]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package com.tangem.features.send.v2.feeselector.model.transformers
|
||||
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.send.v2.api.params.FeeSelectorParams
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeItem
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class FeeItemConverter(
|
||||
private val suggestedFeeState: FeeSelectorParams.SuggestedFeeState,
|
||||
private val normalFee: Fee,
|
||||
private val onCustomFeeValueChange: (Int, String) -> Unit,
|
||||
private val onNextClick: () -> Unit,
|
||||
private val appCurrency: AppCurrency,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
) : Converter<TransactionFee, ImmutableList<FeeItem>> {
|
||||
|
||||
private val customFeeFieldConverter = FeeSelectorCustomFieldConverter(
|
||||
onCustomFeeValueChange = onCustomFeeValueChange,
|
||||
onNextClick = onNextClick,
|
||||
appCurrency = appCurrency,
|
||||
feeCryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
normalFee = normalFee,
|
||||
)
|
||||
|
||||
override fun convert(value: TransactionFee): ImmutableList<FeeItem> {
|
||||
val fees = mutableListOf<FeeItem>()
|
||||
|
||||
when (suggestedFeeState) {
|
||||
FeeSelectorParams.SuggestedFeeState.None -> Unit
|
||||
is FeeSelectorParams.SuggestedFeeState.Suggestion -> fees.add(
|
||||
FeeItem.Suggested(
|
||||
title = suggestedFeeState.title,
|
||||
fee = suggestedFeeState.fee,
|
||||
),
|
||||
)
|
||||
}
|
||||
when (value) {
|
||||
is TransactionFee.Choosable -> {
|
||||
fees.add(FeeItem.Slow(fee = value.minimum))
|
||||
fees.add(FeeItem.Market(fee = value.normal))
|
||||
fees.add(FeeItem.Fast(fee = value.priority))
|
||||
}
|
||||
is TransactionFee.Single -> {
|
||||
fees.add(FeeItem.Market(fee = value.normal))
|
||||
}
|
||||
}
|
||||
val customFeeFields = customFeeFieldConverter.convert(normalFee)
|
||||
if (customFeeFields.isNotEmpty()) {
|
||||
fees.add(
|
||||
FeeItem.Custom(
|
||||
fee = customFeeFieldConverter.convertBack(customFeeFields),
|
||||
customValues = customFeeFields,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return fees.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.features.send.v2.feeselector.model.transformers
|
||||
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeItem
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeSelectorUM
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class FeeItemSelectedTransformer(private val selectedFeeItem: FeeItem) : Transformer<FeeSelectorUM> {
|
||||
override fun transform(prevState: FeeSelectorUM): FeeSelectorUM {
|
||||
prevState as? FeeSelectorUM.Content ?: return prevState
|
||||
|
||||
return prevState.copy(selectedFeeItem = selectedFeeItem)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
package com.tangem.features.send.v2.feeselector.model.transformers
|
||||
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.bitcoin.BitcoinCustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum.EthereumCustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.kaspa.KaspaCustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeSelectorUM
|
||||
import com.tangem.utils.converter.TwoWayConverter
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal class FeeSelectorCustomFieldConverter(
|
||||
private val onCustomFeeValueChange: (Int, String) -> Unit,
|
||||
private val onNextClick: () -> Unit,
|
||||
private val appCurrency: AppCurrency,
|
||||
private val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val normalFee: Fee,
|
||||
) : TwoWayConverter<Fee, ImmutableList<CustomFeeFieldUM>> {
|
||||
|
||||
private val ethereumCustomFeeConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
EthereumCustomFeeConverter(
|
||||
onCustomFeeValueChange = onCustomFeeValueChange,
|
||||
onNextClick = onNextClick,
|
||||
appCurrency = appCurrency,
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
)
|
||||
}
|
||||
|
||||
private val bitcoinCustomFeeConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
BitcoinCustomFeeConverter(
|
||||
onCustomFeeValueChange = onCustomFeeValueChange,
|
||||
onNextClick = onNextClick,
|
||||
appCurrency = appCurrency,
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
)
|
||||
}
|
||||
|
||||
private val kaspaCustomFeeConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
KaspaCustomFeeConverter(
|
||||
onCustomFeeValueChange = onCustomFeeValueChange,
|
||||
appCurrency = appCurrency,
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
)
|
||||
}
|
||||
|
||||
override fun convert(value: Fee): ImmutableList<CustomFeeFieldUM> {
|
||||
return when (value) {
|
||||
is Fee.Ethereum -> ethereumCustomFeeConverter.convert(value)
|
||||
is Fee.Bitcoin -> bitcoinCustomFeeConverter.convert(value)
|
||||
is Fee.Kaspa -> kaspaCustomFeeConverter.convert(value)
|
||||
else -> persistentListOf()
|
||||
}
|
||||
}
|
||||
|
||||
override fun convertBack(value: ImmutableList<CustomFeeFieldUM>): Fee {
|
||||
return if (value.isEmpty()) {
|
||||
normalFee
|
||||
} else {
|
||||
when (normalFee) {
|
||||
is Fee.Ethereum -> ethereumCustomFeeConverter.convertBack(normalFee = normalFee, value = value)
|
||||
is Fee.Bitcoin -> bitcoinCustomFeeConverter.convertBack(normalFee = normalFee, value = value)
|
||||
is Fee.Kaspa -> kaspaCustomFeeConverter.convertBack(normalFee = normalFee, value = value)
|
||||
else -> {
|
||||
val customFee = value.firstOrNull()
|
||||
Fee.Common(
|
||||
normalFee.amount.copy(
|
||||
value = customFee?.value?.parseToBigDecimal(customFee.decimals),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onValueChange(feeSelectorState: FeeSelectorUM.Content, index: Int, value: String) =
|
||||
when (val fee = feeSelectorState.fees.normal) {
|
||||
is Fee.Ethereum -> ethereumCustomFeeConverter.onValueChange(
|
||||
feeValue = fee,
|
||||
customValues = feeSelectorState.customValues,
|
||||
index = index,
|
||||
value = value,
|
||||
)
|
||||
is Fee.Bitcoin -> bitcoinCustomFeeConverter.onValueChange(
|
||||
customValues = feeSelectorState.customValues,
|
||||
index = index,
|
||||
value = value,
|
||||
txSize = fee.txSize,
|
||||
)
|
||||
is Fee.Kaspa -> kaspaCustomFeeConverter.onValueChange(
|
||||
customValues = feeSelectorState.customValues,
|
||||
index = index,
|
||||
value = value,
|
||||
)
|
||||
else -> feeSelectorState.customValues
|
||||
}
|
||||
|
||||
fun tryAutoFixValue(feeSelectorState: FeeSelectorUM.Content) = when (feeSelectorState.fees) {
|
||||
is TransactionFee.Choosable -> feeSelectorState.fees.minimum
|
||||
is TransactionFee.Single -> feeSelectorState.fees.normal
|
||||
}.let {
|
||||
when (it) {
|
||||
is Fee.Kaspa -> kaspaCustomFeeConverter.tryAutoFixValue(
|
||||
minimumFee = it,
|
||||
customValues = feeSelectorState.customValues,
|
||||
)
|
||||
else -> feeSelectorState.customValues
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.features.send.v2.feeselector.model.transformers
|
||||
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeSelectorUM
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class FeeSelectorErrorTransformer(private val error: GetFeeError) : Transformer<FeeSelectorUM> {
|
||||
|
||||
override fun transform(prevState: FeeSelectorUM): FeeSelectorUM {
|
||||
return FeeSelectorUM.Error(error = error, onDone = prevState.doneButtonConfig.onClick)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.tangem.features.send.v2.feeselector.model.transformers
|
||||
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.send.v2.api.params.FeeSelectorParams
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeFiatRateUM
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeItem
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeSelectorUM
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class FeeSelectorLoadedTransformer(
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val appCurrency: AppCurrency,
|
||||
private val fees: TransactionFee,
|
||||
private val suggestedFeeState: FeeSelectorParams.SuggestedFeeState,
|
||||
private val isFeeApproximate: Boolean,
|
||||
private val onFeeSelected: (FeeItem) -> Unit,
|
||||
private val onCustomFeeValueChange: (Int, String) -> Unit,
|
||||
private val onNextClick: () -> Unit,
|
||||
) : Transformer<FeeSelectorUM> {
|
||||
|
||||
private val feeItemsConverter = FeeItemConverter(
|
||||
suggestedFeeState = suggestedFeeState,
|
||||
normalFee = fees.normal,
|
||||
onCustomFeeValueChange = onCustomFeeValueChange,
|
||||
onNextClick = onNextClick,
|
||||
appCurrency = appCurrency,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
)
|
||||
|
||||
override fun transform(prevState: FeeSelectorUM): FeeSelectorUM {
|
||||
val feeItems: ImmutableList<FeeItem> = feeItemsConverter.convert(fees)
|
||||
val selectedFee = feeItems.find { it is FeeItem.Suggested } ?: feeItems.first { it is FeeItem.Market }
|
||||
return FeeSelectorUM.Content(
|
||||
doneButtonConfig = prevState.doneButtonConfig.copy(enabled = true),
|
||||
feeItems = feeItems,
|
||||
selectedFeeItem = selectedFee,
|
||||
isFeeApproximate = isFeeApproximate,
|
||||
onFeeSelected = onFeeSelected,
|
||||
feeFiatRateUM = cryptoCurrencyStatus.value.fiatRate?.let { rate ->
|
||||
FeeFiatRateUM(
|
||||
rate = rate,
|
||||
appCurrency = appCurrency,
|
||||
)
|
||||
},
|
||||
displayNonceInput = false,
|
||||
nonce = null,
|
||||
onNonceChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatReference
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.components.atoms.text.EllipsisText
|
||||
|
|
@ -47,9 +48,10 @@ import com.tangem.core.ui.format.bigdecimal.format
|
|||
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.send.v2.feeselector.entity.FeeFiatRateDataHolder
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeFiatRateUM
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeItem
|
||||
import com.tangem.features.send.v2.feeselector.entity.FeeSelectorUM
|
||||
import com.tangem.features.send.v2.feeselector.entity.PrimaryButtonConfig
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import com.tangem.utils.StringsSigns
|
||||
|
|
@ -88,8 +90,8 @@ internal fun FeeSelectorModalBottomSheet(state: FeeSelectorUM, onDismiss: () ->
|
|||
.fillMaxWidth()
|
||||
.padding(16.dp),
|
||||
text = stringResourceSafe(R.string.common_done),
|
||||
onClick = onDismiss,
|
||||
enabled = state.isDoneEnabled,
|
||||
onClick = state.doneButtonConfig.onClick,
|
||||
enabled = state.doneButtonConfig.enabled,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -114,7 +116,7 @@ private fun FeeSelectorItems(state: FeeSelectorUM.Content, modifier: Modifier =
|
|||
},
|
||||
label = "Fee selector icon background change",
|
||||
)
|
||||
val onSelect by rememberUpdatedState(item.onSelect)
|
||||
val onSelect by rememberUpdatedState(state.onFeeSelected)
|
||||
val itemModifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors.background.primary)
|
||||
|
|
@ -133,7 +135,7 @@ private fun FeeSelectorItems(state: FeeSelectorUM.Content, modifier: Modifier =
|
|||
Modifier
|
||||
},
|
||||
)
|
||||
.clickableSingle(onClick = onSelect)
|
||||
.clickableSingle(onClick = { onSelect(item) })
|
||||
when (item) {
|
||||
is FeeItem.Suggested -> RegularFeeItemContent(
|
||||
modifier = itemModifier,
|
||||
|
|
@ -142,23 +144,23 @@ private fun FeeSelectorItems(state: FeeSelectorUM.Content, modifier: Modifier =
|
|||
iconBackgroundColor = iconBackgroundColor,
|
||||
iconTint = iconTint,
|
||||
preDot = stringReference(
|
||||
item.amount.value.format {
|
||||
item.fee.amount.value.format {
|
||||
crypto(
|
||||
symbol = item.amount.currencySymbol,
|
||||
decimals = item.amount.decimals,
|
||||
symbol = item.fee.amount.currencySymbol,
|
||||
decimals = item.fee.amount.decimals,
|
||||
).fee(canBeLower = state.isFeeApproximate)
|
||||
},
|
||||
),
|
||||
postDot = if (state.feeFiatRateDataHolder != null) {
|
||||
postDot = if (state.feeFiatRateUM != null) {
|
||||
getFiatReference(
|
||||
value = item.amount.value,
|
||||
rate = state.feeFiatRateDataHolder.rate,
|
||||
appCurrency = state.feeFiatRateDataHolder.appCurrency,
|
||||
value = item.fee.amount.value,
|
||||
rate = state.feeFiatRateUM.rate,
|
||||
appCurrency = state.feeFiatRateUM.appCurrency,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = item.amount.currencySymbol.length,
|
||||
ellipsizeOffset = item.fee.amount.currencySymbol.length,
|
||||
showDivider = !isSelected && !lastItem,
|
||||
)
|
||||
is FeeItem.Slow -> RegularFeeItemContent(
|
||||
|
|
@ -168,23 +170,23 @@ private fun FeeSelectorItems(state: FeeSelectorUM.Content, modifier: Modifier =
|
|||
iconBackgroundColor = iconBackgroundColor,
|
||||
iconTint = iconTint,
|
||||
preDot = stringReference(
|
||||
item.amount.value.format {
|
||||
item.fee.amount.value.format {
|
||||
crypto(
|
||||
symbol = item.amount.currencySymbol,
|
||||
decimals = item.amount.decimals,
|
||||
symbol = item.fee.amount.currencySymbol,
|
||||
decimals = item.fee.amount.decimals,
|
||||
).fee(canBeLower = state.isFeeApproximate)
|
||||
},
|
||||
),
|
||||
postDot = if (state.feeFiatRateDataHolder != null) {
|
||||
postDot = if (state.feeFiatRateUM != null) {
|
||||
getFiatReference(
|
||||
value = item.amount.value,
|
||||
rate = state.feeFiatRateDataHolder.rate,
|
||||
appCurrency = state.feeFiatRateDataHolder.appCurrency,
|
||||
value = item.fee.amount.value,
|
||||
rate = state.feeFiatRateUM.rate,
|
||||
appCurrency = state.feeFiatRateUM.appCurrency,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = item.amount.currencySymbol.length,
|
||||
ellipsizeOffset = item.fee.amount.currencySymbol.length,
|
||||
showDivider = !isSelected && !lastItem,
|
||||
)
|
||||
is FeeItem.Market -> RegularFeeItemContent(
|
||||
|
|
@ -194,23 +196,23 @@ private fun FeeSelectorItems(state: FeeSelectorUM.Content, modifier: Modifier =
|
|||
iconBackgroundColor = iconBackgroundColor,
|
||||
iconTint = iconTint,
|
||||
preDot = stringReference(
|
||||
item.amount.value.format {
|
||||
item.fee.amount.value.format {
|
||||
crypto(
|
||||
symbol = item.amount.currencySymbol,
|
||||
decimals = item.amount.decimals,
|
||||
symbol = item.fee.amount.currencySymbol,
|
||||
decimals = item.fee.amount.decimals,
|
||||
).fee(canBeLower = state.isFeeApproximate)
|
||||
},
|
||||
),
|
||||
postDot = if (state.feeFiatRateDataHolder != null) {
|
||||
postDot = if (state.feeFiatRateUM != null) {
|
||||
getFiatReference(
|
||||
value = item.amount.value,
|
||||
rate = state.feeFiatRateDataHolder.rate,
|
||||
appCurrency = state.feeFiatRateDataHolder.appCurrency,
|
||||
value = item.fee.amount.value,
|
||||
rate = state.feeFiatRateUM.rate,
|
||||
appCurrency = state.feeFiatRateUM.appCurrency,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = item.amount.currencySymbol.length,
|
||||
ellipsizeOffset = item.fee.amount.currencySymbol.length,
|
||||
showDivider = !isSelected && !lastItem,
|
||||
)
|
||||
is FeeItem.Fast -> RegularFeeItemContent(
|
||||
|
|
@ -220,23 +222,23 @@ private fun FeeSelectorItems(state: FeeSelectorUM.Content, modifier: Modifier =
|
|||
iconBackgroundColor = iconBackgroundColor,
|
||||
iconTint = iconTint,
|
||||
preDot = stringReference(
|
||||
item.amount.value.format {
|
||||
item.fee.amount.value.format {
|
||||
crypto(
|
||||
symbol = item.amount.currencySymbol,
|
||||
decimals = item.amount.decimals,
|
||||
symbol = item.fee.amount.currencySymbol,
|
||||
decimals = item.fee.amount.decimals,
|
||||
).fee(canBeLower = state.isFeeApproximate)
|
||||
},
|
||||
),
|
||||
postDot = if (state.feeFiatRateDataHolder != null) {
|
||||
postDot = if (state.feeFiatRateUM != null) {
|
||||
getFiatReference(
|
||||
value = item.amount.value,
|
||||
rate = state.feeFiatRateDataHolder.rate,
|
||||
appCurrency = state.feeFiatRateDataHolder.appCurrency,
|
||||
value = item.fee.amount.value,
|
||||
rate = state.feeFiatRateUM.rate,
|
||||
appCurrency = state.feeFiatRateUM.appCurrency,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = item.amount.currencySymbol.length,
|
||||
ellipsizeOffset = item.fee.amount.currencySymbol.length,
|
||||
showDivider = !isSelected && !lastItem,
|
||||
)
|
||||
is FeeItem.Custom -> CustomFeeBlock(
|
||||
|
|
@ -471,34 +473,24 @@ private fun FeeSelectorBS_Preview(
|
|||
private class FeeSelectorUMContentProvider : CollectionPreviewParameterProvider<FeeSelectorUM.Content>(
|
||||
collection = listOf(
|
||||
FeeSelectorUM.Content(
|
||||
isDoneEnabled = false,
|
||||
doneButtonConfig = PrimaryButtonConfig(enabled = true, onClick = {}),
|
||||
feeItems = persistentListOf(
|
||||
FeeItem.Suggested(
|
||||
title = stringReference("Suggested by Tangem"),
|
||||
amount = Amount(value = BigDecimal("0.1"), blockchain = Blockchain.Ethereum),
|
||||
onSelect = onSelectStub,
|
||||
fee = Fee.Common(Amount(value = BigDecimal("0.1"), blockchain = Blockchain.Ethereum)),
|
||||
),
|
||||
FeeItem.Slow(
|
||||
amount = Amount(value = BigDecimal("0.01"), blockchain = Blockchain.Ethereum),
|
||||
onSelect = onSelectStub,
|
||||
),
|
||||
FeeItem.Market(
|
||||
amount = Amount(value = BigDecimal("0.02"), blockchain = Blockchain.Ethereum),
|
||||
onSelect = onSelectStub,
|
||||
),
|
||||
FeeItem.Fast(
|
||||
amount = Amount(value = BigDecimal("0.3"), blockchain = Blockchain.Ethereum),
|
||||
onSelect = onSelectStub,
|
||||
),
|
||||
FeeItem.Custom(customValues = customFeeFields, onSelect = onSelectStub),
|
||||
FeeItem.Slow(fee = Fee.Common(Amount(value = BigDecimal("0.01"), blockchain = Blockchain.Ethereum))),
|
||||
FeeItem.Market(fee = Fee.Common(Amount(value = BigDecimal("0.02"), blockchain = Blockchain.Ethereum))),
|
||||
FeeItem.Fast(fee = Fee.Common(Amount(value = BigDecimal("0.03"), blockchain = Blockchain.Ethereum))),
|
||||
customFeeItem,
|
||||
),
|
||||
onFeeSelected = {},
|
||||
// selectedFeeItem = FeeItem.Market(
|
||||
// amount = Amount(value = BigDecimal("0.02"), blockchain = Blockchain.Ethereum),
|
||||
// onSelect = onSelectStub
|
||||
// ),
|
||||
selectedFeeItem = FeeItem.Custom(customValues = customFeeFields, onSelect = onSelectStub),
|
||||
selectedFeeItem = customFeeItem,
|
||||
isFeeApproximate = true,
|
||||
feeFiatRateDataHolder = FeeFiatRateDataHolder(
|
||||
feeFiatRateUM = FeeFiatRateUM(
|
||||
rate = BigDecimal.TEN,
|
||||
appCurrency = AppCurrency.Default,
|
||||
),
|
||||
|
|
@ -509,43 +501,44 @@ private class FeeSelectorUMContentProvider : CollectionPreviewParameterProvider<
|
|||
),
|
||||
)
|
||||
|
||||
private val onSelectStub: () -> Unit = {}
|
||||
|
||||
private val customFeeFields = persistentListOf(
|
||||
CustomFeeFieldUM(
|
||||
value = "0.119806",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions(),
|
||||
keyboardActions = KeyboardActions(),
|
||||
symbol = "ETH",
|
||||
decimals = 8,
|
||||
title = resourceReference(R.string.send_max_fee),
|
||||
footer = resourceReference(R.string.send_custom_amount_fee_footer),
|
||||
label = stringReference("~ 0,03 \$"),
|
||||
isReadonly = false,
|
||||
),
|
||||
CustomFeeFieldUM(
|
||||
value = "40000",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions(),
|
||||
keyboardActions = KeyboardActions(),
|
||||
symbol = "GWEI",
|
||||
decimals = 8,
|
||||
title = resourceReference(R.string.send_gas_price),
|
||||
footer = resourceReference(R.string.send_gas_price_footer),
|
||||
label = null,
|
||||
isReadonly = false,
|
||||
),
|
||||
CustomFeeFieldUM(
|
||||
value = "31400",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions(),
|
||||
keyboardActions = KeyboardActions(),
|
||||
symbol = null,
|
||||
decimals = 8,
|
||||
title = resourceReference(R.string.send_gas_limit),
|
||||
footer = resourceReference(R.string.send_gas_limit_footer),
|
||||
label = null,
|
||||
isReadonly = false,
|
||||
private val customFeeItem = FeeItem.Custom(
|
||||
fee = Fee.Common(Amount(value = BigDecimal("0.05"), blockchain = Blockchain.Ethereum)),
|
||||
customValues = persistentListOf(
|
||||
CustomFeeFieldUM(
|
||||
value = "0.119806",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions(),
|
||||
keyboardActions = KeyboardActions(),
|
||||
symbol = "ETH",
|
||||
decimals = 8,
|
||||
title = resourceReference(R.string.send_max_fee),
|
||||
footer = resourceReference(R.string.send_custom_amount_fee_footer),
|
||||
label = stringReference("~ 0,03 \$"),
|
||||
isReadonly = false,
|
||||
),
|
||||
CustomFeeFieldUM(
|
||||
value = "40000",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions(),
|
||||
keyboardActions = KeyboardActions(),
|
||||
symbol = "GWEI",
|
||||
decimals = 8,
|
||||
title = resourceReference(R.string.send_gas_price),
|
||||
footer = resourceReference(R.string.send_gas_price_footer),
|
||||
label = null,
|
||||
isReadonly = false,
|
||||
),
|
||||
CustomFeeFieldUM(
|
||||
value = "31400",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions(),
|
||||
keyboardActions = KeyboardActions(),
|
||||
symbol = null,
|
||||
decimals = 8,
|
||||
title = resourceReference(R.string.send_gas_limit),
|
||||
footer = resourceReference(R.string.send_gas_limit_footer),
|
||||
label = null,
|
||||
isReadonly = false,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -24,7 +24,8 @@ internal class SendFeeCustomFieldConverter(
|
|||
|
||||
private val ethereumCustomFeeConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
EthereumCustomFeeConverter(
|
||||
clickIntents = clickIntents,
|
||||
onCustomFeeValueChange = clickIntents::onCustomFeeValueChange,
|
||||
onNextClick = clickIntents::onNextClick,
|
||||
appCurrency = appCurrency,
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
)
|
||||
|
|
@ -32,7 +33,8 @@ internal class SendFeeCustomFieldConverter(
|
|||
|
||||
private val bitcoinCustomFeeConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
BitcoinCustomFeeConverter(
|
||||
clickIntents = clickIntents,
|
||||
onCustomFeeValueChange = clickIntents::onCustomFeeValueChange,
|
||||
onNextClick = clickIntents::onNextClick,
|
||||
appCurrency = appCurrency,
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
)
|
||||
|
|
@ -40,7 +42,7 @@ internal class SendFeeCustomFieldConverter(
|
|||
|
||||
private val kaspaCustomFeeConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
KaspaCustomFeeConverter(
|
||||
clickIntents = clickIntents,
|
||||
onCustomFeeValueChange = clickIntents::onCustomFeeValueChange,
|
||||
appCurrency = appCurrency,
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import com.tangem.core.ui.utils.parseToBigDecimal
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.checkExceedBalance
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.CustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
|
|
@ -24,7 +23,8 @@ import java.math.BigDecimal
|
|||
import java.math.RoundingMode
|
||||
|
||||
internal class BitcoinCustomFeeConverter(
|
||||
private val clickIntents: SendFeeClickIntents,
|
||||
private val onCustomFeeValueChange: (Int, String) -> Unit,
|
||||
private val onNextClick: () -> Unit,
|
||||
private val appCurrency: AppCurrency,
|
||||
private val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
) : CustomFeeConverter<Fee.Bitcoin> {
|
||||
|
|
@ -40,7 +40,7 @@ internal class BitcoinCustomFeeConverter(
|
|||
value = feeValue?.parseBigDecimal(value.amount.decimals).orEmpty(),
|
||||
decimals = value.amount.decimals,
|
||||
symbol = value.amount.currencySymbol,
|
||||
onValueChange = { clickIntents.onCustomFeeValueChange(FEE_AMOUNT_INDEX, it) },
|
||||
onValueChange = { onCustomFeeValueChange(FEE_AMOUNT_INDEX, it) },
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = ImeAction.Companion.Next,
|
||||
keyboardType = KeyboardType.Companion.Number,
|
||||
|
|
@ -65,7 +65,7 @@ internal class BitcoinCustomFeeConverter(
|
|||
symbol = "",
|
||||
title = resourceReference(R.string.send_satoshi_per_byte_title),
|
||||
footer = resourceReference(R.string.send_satoshi_per_byte_text),
|
||||
onValueChange = { clickIntents.onCustomFeeValueChange(FEE_SATOSHI_INDEX, it) },
|
||||
onValueChange = { onCustomFeeValueChange(FEE_SATOSHI_INDEX, it) },
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = if (checkExceedBalance(
|
||||
feeBalance = currencyStatus.amount,
|
||||
|
|
@ -78,9 +78,7 @@ internal class BitcoinCustomFeeConverter(
|
|||
},
|
||||
keyboardType = KeyboardType.Companion.Number,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { clickIntents.onNextClick() },
|
||||
),
|
||||
keyboardActions = KeyboardActions(onDone = { onNextClick() }),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ import com.tangem.core.ui.utils.parseBigDecimal
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.checkExceedBalance
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class EthereumCustomFeeConverter(
|
||||
private val clickIntents: SendFeeClickIntents,
|
||||
private val onCustomFeeValueChange: (Int, String) -> Unit,
|
||||
private val onNextClick: () -> Unit,
|
||||
private val appCurrency: AppCurrency,
|
||||
feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
) : BaseEthereumCustomFeeConverter<Fee.Ethereum> {
|
||||
|
|
@ -26,13 +26,13 @@ internal class EthereumCustomFeeConverter(
|
|||
private val currencyStatus = feeCryptoCurrencyStatus.value
|
||||
|
||||
private val legacyFeeConverter = EthereumLegacyCustomFeeConverter(
|
||||
clickIntents = clickIntents,
|
||||
onCustomFeeValueChange = onCustomFeeValueChange,
|
||||
appCurrency = appCurrency,
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
)
|
||||
|
||||
private val eipFeeConverter = EthereumEIPCustomFeeConverter(
|
||||
clickIntents = clickIntents,
|
||||
onCustomFeeValueChange = onCustomFeeValueChange,
|
||||
appCurrency = appCurrency,
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
)
|
||||
|
|
@ -84,7 +84,7 @@ internal class EthereumCustomFeeConverter(
|
|||
value = feeValue?.parseBigDecimal(value.amount.decimals).orEmpty(),
|
||||
decimals = value.amount.decimals,
|
||||
symbol = value.amount.currencySymbol,
|
||||
onValueChange = { clickIntents.onCustomFeeValueChange(FEE_AMOUNT, it) },
|
||||
onValueChange = { onCustomFeeValueChange(FEE_AMOUNT, it) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next, keyboardType = KeyboardType.Number),
|
||||
title = resourceReference(R.string.send_max_fee),
|
||||
footer = resourceReference(R.string.send_custom_amount_fee_footer),
|
||||
|
|
@ -106,13 +106,13 @@ internal class EthereumCustomFeeConverter(
|
|||
symbol = "",
|
||||
title = resourceReference(R.string.send_gas_limit),
|
||||
footer = resourceReference(R.string.send_gas_limit_footer),
|
||||
onValueChange = { clickIntents.onCustomFeeValueChange(getGasLimitIndex(value), it) },
|
||||
onValueChange = { onCustomFeeValueChange(getGasLimitIndex(value), it) },
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = if (isExceedBalance) ImeAction.None else ImeAction.Done,
|
||||
keyboardType = KeyboardType.Number,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { clickIntents.onNextClick() },
|
||||
onDone = { onNextClick() },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import com.tangem.core.ui.utils.parseToBigDecimal
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.checkExceedBalance
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum.EthereumCustomFeeConverter.Companion.ETHEREUM_GAS_UNIT
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum.EthereumCustomFeeConverter.Companion.FEE_AMOUNT
|
||||
|
|
@ -26,7 +25,7 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
import java.math.RoundingMode
|
||||
|
||||
internal class EthereumEIPCustomFeeConverter(
|
||||
private val clickIntents: SendFeeClickIntents,
|
||||
private val onCustomFeeValueChange: (Int, String) -> Unit,
|
||||
private val appCurrency: AppCurrency,
|
||||
private val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
) : BaseEthereumCustomFeeConverter<Fee.Ethereum.EIP1559> {
|
||||
|
|
@ -41,7 +40,7 @@ internal class EthereumEIPCustomFeeConverter(
|
|||
symbol = ETHEREUM_GAS_UNIT,
|
||||
title = resourceReference(R.string.send_custom_evm_max_fee),
|
||||
footer = resourceReference(R.string.send_custom_evm_max_fee_footer),
|
||||
onValueChange = { clickIntents.onCustomFeeValueChange(MAX_FEE, it) },
|
||||
onValueChange = { onCustomFeeValueChange(MAX_FEE, it) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next, keyboardType = KeyboardType.Number),
|
||||
keyboardActions = KeyboardActions(),
|
||||
),
|
||||
|
|
@ -51,7 +50,7 @@ internal class EthereumEIPCustomFeeConverter(
|
|||
symbol = ETHEREUM_GAS_UNIT,
|
||||
title = resourceReference(R.string.send_custom_evm_priority_fee),
|
||||
footer = resourceReference(R.string.send_custom_evm_priority_fee_footer),
|
||||
onValueChange = { clickIntents.onCustomFeeValueChange(PRIORITY_FEE, it) },
|
||||
onValueChange = { onCustomFeeValueChange(PRIORITY_FEE, it) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next, keyboardType = KeyboardType.Number),
|
||||
keyboardActions = KeyboardActions(),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import com.tangem.core.ui.utils.parseToBigDecimal
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.checkExceedBalance
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum.EthereumCustomFeeConverter.Companion.ETHEREUM_GAS_UNIT
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum.EthereumCustomFeeConverter.Companion.FEE_AMOUNT
|
||||
|
|
@ -26,7 +25,7 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
import java.math.RoundingMode
|
||||
|
||||
internal class EthereumLegacyCustomFeeConverter(
|
||||
private val clickIntents: SendFeeClickIntents,
|
||||
private val onCustomFeeValueChange: (Int, String) -> Unit,
|
||||
private val appCurrency: AppCurrency,
|
||||
feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
) : BaseEthereumCustomFeeConverter<Fee.Ethereum.Legacy> {
|
||||
|
|
@ -41,7 +40,7 @@ internal class EthereumLegacyCustomFeeConverter(
|
|||
symbol = ETHEREUM_GAS_UNIT,
|
||||
title = resourceReference(R.string.send_gas_price),
|
||||
footer = resourceReference(R.string.send_gas_price_footer),
|
||||
onValueChange = { clickIntents.onCustomFeeValueChange(GAS_PRICE, it) },
|
||||
onValueChange = { onCustomFeeValueChange(GAS_PRICE, it) },
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = ImeAction.Next,
|
||||
keyboardType = KeyboardType.Number,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import com.tangem.core.ui.utils.parseToBigDecimal
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.CustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -21,7 +20,7 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
import java.math.RoundingMode
|
||||
|
||||
internal class KaspaCustomFeeConverter(
|
||||
private val clickIntents: SendFeeClickIntents,
|
||||
private val onCustomFeeValueChange: (Int, String) -> Unit,
|
||||
private val appCurrency: AppCurrency,
|
||||
feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
) : CustomFeeConverter<Fee.Kaspa> {
|
||||
|
|
@ -35,7 +34,7 @@ internal class KaspaCustomFeeConverter(
|
|||
value = feeValue?.parseBigDecimal(value.amount.decimals).orEmpty(),
|
||||
decimals = value.amount.decimals,
|
||||
symbol = value.amount.currencySymbol,
|
||||
onValueChange = { clickIntents.onCustomFeeValueChange(FEE_AMOUNT_INDEX, it) },
|
||||
onValueChange = { onCustomFeeValueChange(FEE_AMOUNT_INDEX, it) },
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = ImeAction.Companion.Next,
|
||||
keyboardType = KeyboardType.Companion.Number,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue