Updated on 2026-08-14
This commit is contained in:
parent
f426a1f922
commit
909ff3be7c
17 changed files with 104 additions and 21 deletions
|
|
@ -564,6 +564,7 @@
|
|||
<string name="send_total_subtitle_fiat_format">≈ %1$s (вкл. комиссию: %2$s)</string>
|
||||
<string name="send_total_subtitle_format">%s будет отправлено</string>
|
||||
<string name="send_transaction_success">Транзакция успешно подписана и отправлена в блокчейн. Баланс будет обновлен через некоторое время</string>
|
||||
<string name="send_tron_account_activation_error">%1$s — это монета в сети Tron. Чтобы рассчитать комиссию и совершить транзакцию, вам необходимо внести немного Tron (TRX) на свой адрес.</string>
|
||||
<string name="send_validation_invalid_address">Неверный адрес</string>
|
||||
<string name="sent_transaction_sent_title">Транзакция отправлена</string>
|
||||
<string name="settings_card_settings_footer">Подготовьтесь к сканированию карты, которую вы хотите настроить.</string>
|
||||
|
|
|
|||
|
|
@ -627,6 +627,7 @@
|
|||
<string name="send_total_subtitle_fiat_format">≈ %1$s (inc. fee: %2$s)</string>
|
||||
<string name="send_total_subtitle_format">%s will be sent</string>
|
||||
<string name="send_transaction_success">Transaction has been successfully signed and sent to the blockchain node. Wallet balance will be updated in a while</string>
|
||||
<string name="send_tron_account_activation_error">%1$s is an asset in the Tron network. To calculate the fee and make a transaction you need to deposit some Tron(TRX) in your account.</string>
|
||||
<string name="send_validation_invalid_address">Invalid address</string>
|
||||
<string name="send_wallet_balance_format">%1$s (%2$s)</string>
|
||||
<string name="sent_transaction_sent_title">Transaction sent</string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.domain.transaction.error
|
||||
|
||||
import com.tangem.blockchain.common.BlockchainSdkError
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
|
||||
fun Result.Failure.mapToFeeError(): GetFeeError {
|
||||
return when (this.error) {
|
||||
is BlockchainSdkError.Tron.AccountActivationError -> {
|
||||
GetFeeError.BlockchainErrors.TronActivationError
|
||||
}
|
||||
else -> GetFeeError.DataError(this.error)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,5 +2,9 @@ package com.tangem.domain.transaction.error
|
|||
|
||||
sealed class GetFeeError {
|
||||
data class DataError(val cause: Throwable?) : GetFeeError()
|
||||
object UnknownError : GetFeeError()
|
||||
data object UnknownError : GetFeeError()
|
||||
|
||||
sealed class BlockchainErrors : GetFeeError() {
|
||||
data object TronActivationError : BlockchainErrors()
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import com.tangem.domain.demo.DemoConfig
|
|||
import com.tangem.domain.demo.DemoTransactionSender
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.domain.transaction.error.mapToFeeError
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -47,7 +48,7 @@ class EstimateFeeUseCase(
|
|||
|
||||
val maybeFee = when (result) {
|
||||
is Result.Success -> result.data.right()
|
||||
is Result.Failure -> GetFeeError.DataError(result.error).left()
|
||||
is Result.Failure -> result.mapToFeeError().left()
|
||||
null -> GetFeeError.UnknownError.left()
|
||||
}
|
||||
emit(maybeFee)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.domain.demo.DemoConfig
|
|||
import com.tangem.domain.demo.DemoTransactionSender
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.domain.transaction.error.mapToFeeError
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -47,7 +48,7 @@ class GetFeeUseCase(
|
|||
|
||||
val maybeFee = when (result) {
|
||||
is Result.Success -> result.data
|
||||
is Result.Failure -> raise(GetFeeError.DataError(result.error))
|
||||
is Result.Failure -> raise(result.mapToFeeError())
|
||||
}
|
||||
maybeFee
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.features.send.impl.presentation.errors
|
||||
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState
|
||||
|
||||
internal class FeeErrorStateMapper {
|
||||
|
||||
fun getFeeError(loadFeeError: GetFeeError?, tokenName: String): FeeSelectorState.Error {
|
||||
return when (loadFeeError) {
|
||||
GetFeeError.BlockchainErrors.TronActivationError -> FeeSelectorState.Error.TronAccountActivationError(
|
||||
tokenName,
|
||||
)
|
||||
is GetFeeError.DataError,
|
||||
GetFeeError.UnknownError,
|
||||
null,
|
||||
-> FeeSelectorState.Error.NetworkError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -157,6 +157,14 @@ internal sealed class SendNotification(val config: NotificationConfig) {
|
|||
),
|
||||
)
|
||||
|
||||
data class TronAccountNotActivated(val tokenName: String) : Warning(
|
||||
title = resourceReference(R.string.send_fee_unreachable_error_title),
|
||||
subtitle = resourceReference(
|
||||
R.string.send_tron_account_activation_error,
|
||||
wrappedList(tokenName),
|
||||
),
|
||||
)
|
||||
|
||||
data class FeeCoverageNotification(val cryptoAmount: String, val fiatAmount: String) : Warning(
|
||||
title = resourceReference(R.string.send_network_fee_warning_title),
|
||||
subtitle = resourceReference(
|
||||
|
|
|
|||
|
|
@ -126,8 +126,18 @@ internal class SendNotificationFactory(
|
|||
}
|
||||
|
||||
private fun MutableList<SendNotification>.addFeeUnreachableNotification(feeSelectorState: FeeSelectorState) {
|
||||
if (feeSelectorState is FeeSelectorState.Error) {
|
||||
add(SendNotification.Warning.NetworkFeeUnreachable(clickIntents::feeReload))
|
||||
when (feeSelectorState) {
|
||||
is FeeSelectorState.Error.TronAccountActivationError -> add(
|
||||
SendNotification.Warning.TronAccountNotActivated(
|
||||
feeSelectorState.tokenName,
|
||||
),
|
||||
)
|
||||
is FeeSelectorState.Error.NetworkError -> add(
|
||||
SendNotification.Warning.NetworkFeeUnreachable(clickIntents::feeReload),
|
||||
)
|
||||
else -> {
|
||||
/* do nothing */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package com.tangem.features.send.impl.presentation.state.fee
|
||||
|
||||
import com.tangem.features.send.impl.presentation.state.*
|
||||
import com.tangem.features.send.impl.presentation.state.SendNotification
|
||||
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.state.StateRouter
|
||||
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
|
||||
import com.tangem.utils.Provider
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -21,13 +24,25 @@ internal class FeeNotificationFactory(
|
|||
val state = currentStateProvider()
|
||||
val feeState = state.getFeeState(stateRouterProvider().isEditState) ?: return@map persistentListOf()
|
||||
buildList {
|
||||
addFeeUnreachableNotification(feeState.feeSelectorState)
|
||||
addFeeUnreachableNotification(
|
||||
feeState.feeSelectorState,
|
||||
)
|
||||
}.toImmutableList()
|
||||
}
|
||||
|
||||
private fun MutableList<SendNotification>.addFeeUnreachableNotification(feeSelectorState: FeeSelectorState) {
|
||||
if (feeSelectorState is FeeSelectorState.Error) {
|
||||
add(SendNotification.Warning.NetworkFeeUnreachable(clickIntents::feeReload))
|
||||
when (feeSelectorState) {
|
||||
is FeeSelectorState.Error.TronAccountActivationError -> add(
|
||||
SendNotification.Warning.TronAccountNotActivated(
|
||||
feeSelectorState.tokenName,
|
||||
),
|
||||
)
|
||||
is FeeSelectorState.Error.NetworkError -> add(
|
||||
SendNotification.Warning.NetworkFeeUnreachable(clickIntents::feeReload),
|
||||
)
|
||||
else -> {
|
||||
/* do nothing */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,10 @@ internal sealed class FeeSelectorState {
|
|||
|
||||
data object Loading : FeeSelectorState()
|
||||
|
||||
data object Error : FeeSelectorState()
|
||||
sealed class Error : FeeSelectorState() {
|
||||
data object NetworkError : Error()
|
||||
data class TronAccountActivationError(val tokenName: String) : Error()
|
||||
}
|
||||
}
|
||||
|
||||
enum class FeeType {
|
||||
|
|
|
|||
|
|
@ -99,13 +99,13 @@ internal class FeeStateFactory(
|
|||
)
|
||||
}
|
||||
|
||||
fun onFeeOnErrorState(): SendUiState {
|
||||
fun onFeeOnErrorState(feeError: FeeSelectorState.Error): SendUiState {
|
||||
val state = currentStateProvider()
|
||||
val isEditState = stateRouterProvider().isEditState
|
||||
return state.copyWrapped(
|
||||
isEditState = isEditState,
|
||||
feeState = state.getFeeState(isEditState)?.copy(
|
||||
feeSelectorState = FeeSelectorState.Error,
|
||||
feeSelectorState = feeError,
|
||||
),
|
||||
sendState = state.sendState?.copy(
|
||||
isPrimaryButtonEnabled = false,
|
||||
|
|
|
|||
|
|
@ -102,6 +102,6 @@ internal object FeeStatePreviewData {
|
|||
)
|
||||
|
||||
val errorFeeState = feeState.copy(
|
||||
feeSelectorState = FeeSelectorState.Error,
|
||||
feeSelectorState = FeeSelectorState.Error.NetworkError,
|
||||
)
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ private fun FeeError(feeSelectorState: FeeSelectorState) {
|
|||
Row {
|
||||
SpacerWMax()
|
||||
AnimatedVisibility(
|
||||
visible = feeSelectorState == FeeSelectorState.Error,
|
||||
visible = feeSelectorState is FeeSelectorState.Error,
|
||||
label = "Fee Error State Change",
|
||||
modifier = Modifier.align(Alignment.CenterVertically),
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ private fun BoxScope.FeeError(feeSelectorState: FeeSelectorState) {
|
|||
label = "Fee Error State Change",
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
) {
|
||||
if (it == FeeSelectorState.Error) {
|
||||
if (it is FeeSelectorState.Error) {
|
||||
Text(
|
||||
text = BigDecimalFormatter.EMPTY_BALANCE_SIGN,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import com.tangem.features.send.impl.presentation.analytics.SendAnalyticEvents
|
|||
import com.tangem.features.send.impl.presentation.analytics.SendScreenSource
|
||||
import com.tangem.features.send.impl.presentation.analytics.utils.SendScreenAnalyticSender
|
||||
import com.tangem.features.send.impl.presentation.domain.AvailableWallet
|
||||
import com.tangem.features.send.impl.presentation.errors.FeeErrorStateMapper
|
||||
import com.tangem.features.send.impl.presentation.state.*
|
||||
import com.tangem.features.send.impl.presentation.state.amount.AmountStateFactory
|
||||
import com.tangem.features.send.impl.presentation.state.confirm.SendNotificationFactory
|
||||
|
|
@ -120,6 +121,8 @@ internal class SendViewModel @Inject constructor(
|
|||
var stateRouter: StateRouter by Delegates.notNull()
|
||||
private set
|
||||
|
||||
private val feeErrorHandler = FeeErrorStateMapper()
|
||||
|
||||
private val stateFactory = SendStateFactory(
|
||||
clickIntents = this,
|
||||
stateRouterProvider = Provider { stateRouter },
|
||||
|
|
@ -711,20 +714,24 @@ internal class SendViewModel @Inject constructor(
|
|||
uiState.value = feeStateFactory.onFeeOnLoadedState(it)
|
||||
sendIdleTimer = SystemClock.elapsedRealtime()
|
||||
},
|
||||
ifLeft = {
|
||||
onFeeLoadFailed(isShowStatus)
|
||||
ifLeft = { loadFeeError ->
|
||||
onFeeLoadFailed(isShowStatus, loadFeeError)
|
||||
},
|
||||
)
|
||||
if (result == null) {
|
||||
onFeeLoadFailed(isShowStatus)
|
||||
onFeeLoadFailed(isShowStatus, null)
|
||||
}
|
||||
updateNotifications()
|
||||
updateFeeNotifications()
|
||||
}.saveIn(feeJobHolder)
|
||||
}
|
||||
|
||||
private fun onFeeLoadFailed(isShowStatus: Boolean) {
|
||||
if (isShowStatus) uiState.value = feeStateFactory.onFeeOnErrorState()
|
||||
private fun onFeeLoadFailed(isShowStatus: Boolean, loadFeeError: GetFeeError?) {
|
||||
if (isShowStatus) {
|
||||
uiState.value = feeStateFactory.onFeeOnErrorState(
|
||||
feeErrorHandler.getFeeError(loadFeeError, cryptoCurrency.name),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun checkIfSubtractAvailable() {
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ markdown = "0.7.2"
|
|||
# endregion Other libraries
|
||||
|
||||
# region Tangem
|
||||
tangemBlockchainSdk = "develop-700"
|
||||
tangemBlockchainSdk = "develop-702"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "develop-375"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue