Updated on 2026-08-14
This commit is contained in:
parent
a8dd36e98c
commit
9e399946d7
17 changed files with 304 additions and 198 deletions
|
|
@ -1,23 +1,36 @@
|
|||
package com.tangem.tap.common
|
||||
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.extensions.scaleToFiat
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class CurrencyConverter(var rateValue: BigDecimal) {
|
||||
class CurrencyConverter(
|
||||
private val rateValue: BigDecimal,
|
||||
private val decimals: Int
|
||||
) {
|
||||
private val roundingMode = RoundingMode.DOWN
|
||||
|
||||
fun toFiat(crypto: BigDecimal, decimals: Int = 2): BigDecimal {
|
||||
return rateValue.multiply(crypto).setScale(decimals, RoundingMode.DOWN)
|
||||
fun toFiat(crypto: BigDecimal, fiatDecimals: Int = 2): BigDecimal {
|
||||
return toFiatUnscaled(crypto).setScale(fiatDecimals, roundingMode)
|
||||
}
|
||||
|
||||
fun toCrypto(fiat: BigDecimal, decimals: Int): BigDecimal {
|
||||
if (fiat.isZero() || rateValue.isZero()) return fiat
|
||||
fun toFiatUnscaled(crypto: BigDecimal): BigDecimal {
|
||||
return rateValue.multiply(crypto).setScale(decimals, roundingMode)
|
||||
}
|
||||
|
||||
val scaledRateValue = rateValue.setScale(decimals, RoundingMode.DOWN)
|
||||
val scaledFiat = fiat.setScale(decimals, RoundingMode.DOWN)
|
||||
fun toFiatWithPrecision(crypto: BigDecimal): BigDecimal {
|
||||
return toFiatUnscaled(crypto).scaleToFiat(true)
|
||||
}
|
||||
|
||||
fun toCrypto(fiat: BigDecimal): BigDecimal {
|
||||
if (fiat.isZero()) return fiat
|
||||
|
||||
val scaledRateValue = rateValue.setScale(decimals, roundingMode)
|
||||
val scaledFiat = fiat.setScale(decimals, roundingMode)
|
||||
return scaledFiat.divide(scaledRateValue, RoundingMode.UP)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import com.google.zxing.BarcodeFormat
|
|||
import com.google.zxing.EncodeHintType
|
||||
import com.google.zxing.qrcode.QRCodeWriter
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.redux.global.FiatCurrencyName
|
||||
import com.tangem.tap.network.coinmarketcap.FiatCurrency
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -58,8 +59,28 @@ fun BigDecimal.toFiatString(rateValue: BigDecimal, fiatCurrencyName: FiatCurrenc
|
|||
return "≈ ${fiatCurrencyName} $fiatValue"
|
||||
}
|
||||
|
||||
fun FiatCurrency.toFormattedString(): String = "${this.name} (${this.symbol}) - ${this.sign}"
|
||||
|
||||
fun BigDecimal.stripZeroPlainString(): String = this.stripTrailingZeros().toPlainString()
|
||||
|
||||
// 0.00 -> 0.00
|
||||
// 0.00002345 -> 0.00002
|
||||
// 1.00002345 -> 1.00
|
||||
// 1.45002345 -> 1.45
|
||||
fun BigDecimal.scaleToFiat(applyPrecision: Boolean = false): BigDecimal {
|
||||
if (this.isZero()) return this
|
||||
|
||||
val scaledFiat = this.setScale(2, RoundingMode.DOWN)
|
||||
return if (scaledFiat.isZero() && applyPrecision) this.setPrecision(1)
|
||||
else scaledFiat
|
||||
|
||||
}
|
||||
|
||||
fun BigDecimal.setPrecision(precision: Int, roundingMode: RoundingMode = RoundingMode.DOWN): BigDecimal {
|
||||
if (precision == precision() || scale() <= precision) return this
|
||||
return this.setScale(scale() - precision() + precision, roundingMode)
|
||||
}
|
||||
|
||||
fun BigDecimal.isPositive(): Boolean = this.compareTo(BigDecimal.ZERO) == 1
|
||||
fun BigDecimal.isNegative(): Boolean = this.compareTo(BigDecimal.ZERO) == -1
|
||||
fun BigDecimal.isGreaterThan(value: BigDecimal): Boolean = this.compareTo(value) == 1
|
||||
|
|
@ -73,6 +94,4 @@ fun BigDecimal.isGreaterThanOrEqual(value: BigDecimal): Boolean {
|
|||
fun BigDecimal.isLessThanOrEqual(value: BigDecimal): Boolean {
|
||||
val compareResult = this.compareTo(value)
|
||||
return compareResult == -1 || compareResult == 0
|
||||
}
|
||||
|
||||
fun FiatCurrency.toFormattedString(): String = "${this.name} (${this.symbol}) - ${this.sign}"
|
||||
}
|
||||
|
|
@ -3,7 +3,9 @@ package com.tangem.tap.common.redux
|
|||
import android.widget.Toast
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tangem.tap.domain.MultiMessageError
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.assembleErrorIds
|
||||
import com.tangem.tap.notificationsHandler
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.Middleware
|
||||
|
|
@ -39,19 +41,30 @@ class NotificationsHandler(coordinatorLayout: CoordinatorLayout) {
|
|||
Toast.makeText(it.context, it.context.getString(message), Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
fun showNotification(errorList: List<Int>, builder: (List<String>) -> String) {
|
||||
val context = baseLayout.get()?.context ?: return
|
||||
|
||||
val message = builder(errorList.map { context.getString(it) })
|
||||
showNotification(message)
|
||||
}
|
||||
}
|
||||
|
||||
val notificationsMiddleware: Middleware<AppState> = { dispatch, state ->
|
||||
{ next ->
|
||||
{ action ->
|
||||
if (action is NotificationAction) {
|
||||
notificationsHandler?.showNotification(action.messageResource)
|
||||
}
|
||||
if (action is ToastNotificationAction) {
|
||||
notificationsHandler?.showToastNotification(action.messageResource)
|
||||
}
|
||||
if (action is ErrorAction) {
|
||||
notificationsHandler?.showNotification(action.error.localizedMessage)
|
||||
when (action) {
|
||||
is NotificationAction -> notificationsHandler?.showNotification(action.messageResource)
|
||||
is ToastNotificationAction -> notificationsHandler?.showToastNotification(action.messageResource)
|
||||
is ErrorAction -> {
|
||||
when (action.error) {
|
||||
is MultiMessageError -> {
|
||||
val multiError = action.error as MultiMessageError
|
||||
notificationsHandler?.showNotification(multiError.assembleErrorIds(), multiError.builder)
|
||||
}
|
||||
else -> notificationsHandler?.showNotification(action.error.localizedMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
next(action)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,39 @@ package com.tangem.tap.domain
|
|||
import androidx.annotation.StringRes
|
||||
import com.tangem.wallet.R
|
||||
|
||||
sealed class TapError(@StringRes val localizedMessage: Int): Throwable() {
|
||||
object PayIdAlreadyCreated: TapError(R.string.error_payid_already_created)
|
||||
object PayIdCreatingError: TapError(R.string.error_creating_payid)
|
||||
object PayIdEmptyField: TapError(R.string.wallet_create_payid_empty)
|
||||
object UnknownBlockchain: TapError(R.string.wallet_unknown_blockchain)
|
||||
object NoInternetConnection: TapError(R.string.notification_no_internet)
|
||||
object InsufficientBalance: TapError(R.string.error_insufficient_balance)
|
||||
object BlockchainInternalError: TapError(R.string.error_blockchain_internal)
|
||||
object UnknownError: TapError(R.string.error_unknown)
|
||||
interface TapErrors
|
||||
interface MultiMessageError : TapErrors {
|
||||
val errorList: List<TapError>
|
||||
val builder: (List<String>) -> String
|
||||
}
|
||||
|
||||
sealed class TapError(@StringRes val localizedMessage: Int) : Throwable(), TapErrors {
|
||||
object UnknownError : TapError(R.string.error_unknown)
|
||||
object PayIdAlreadyCreated : TapError(R.string.error_payid_already_created)
|
||||
object PayIdCreatingError : TapError(R.string.error_creating_payid)
|
||||
object PayIdEmptyField : TapError(R.string.wallet_create_payid_empty)
|
||||
object UnknownBlockchain : TapError(R.string.wallet_unknown_blockchain)
|
||||
object NoInternetConnection : TapError(R.string.notification_no_internet)
|
||||
object InsufficientBalance : TapError(R.string.error_insufficient_balance)
|
||||
object BlockchainInternalError : TapError(R.string.error_blockchain_internal)
|
||||
object AmountExceedsBalance : TapError(R.string.amount_exceeds_balance)
|
||||
object FeeExceedsBalance : TapError(R.string.fee_exceeds_balance)
|
||||
object TotalExceedsBalance : TapError(R.string.total_exceeds_balance)
|
||||
object InvalidAmountValue : TapError(R.string.invalid_amount_value)
|
||||
object InvalidFeeValue : TapError(R.string.invalid_fee_value)
|
||||
object DustAmount : TapError(R.string.dust_amount)
|
||||
object DustChang : TapError(R.string.dust_change)
|
||||
data class ValidateTransactionErrors(
|
||||
override val errorList: List<TapError>,
|
||||
override val builder: (List<String>) -> String
|
||||
) : TapError(-1), MultiMessageError
|
||||
}
|
||||
|
||||
fun TapErrors.assembleErrorIds(): MutableList<Int> {
|
||||
val idList = mutableListOf<Int>()
|
||||
when (this) {
|
||||
is MultiMessageError -> this.errorList.forEach { idList.addAll(it.assembleErrorIds()) }
|
||||
is TapError -> idList.add(this.localizedMessage)
|
||||
}
|
||||
return idList
|
||||
}
|
||||
|
|
@ -64,14 +64,9 @@ sealed class AmountActionUi : SendScreenActionUi {
|
|||
}
|
||||
|
||||
sealed class AmountAction : SendScreenAction {
|
||||
enum class Error {
|
||||
FEE_GREATER_THAN_AMOUNT,
|
||||
AMOUNT_WITH_FEE_GREATER_THAN_BALANCE
|
||||
}
|
||||
|
||||
sealed class AmountVerification : AmountAction() {
|
||||
data class SetAmount(val amount: BigDecimal) : AmountVerification()
|
||||
data class SetError(val amount: BigDecimal, val error: Error) : AmountVerification()
|
||||
data class SetError(val amount: BigDecimal, val error: TapError) : AmountVerification()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
package com.tangem.tap.features.send.redux.middlewares
|
||||
|
||||
import com.tangem.tap.common.CurrencyConverter
|
||||
import com.tangem.tap.common.extensions.isGreaterThan
|
||||
import com.tangem.tap.common.extensions.isGreaterThanOrEqual
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.TransactionError
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.features.send.redux.AmountAction
|
||||
import com.tangem.tap.features.send.redux.ReceiptAction
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
import com.tangem.tap.features.send.redux.states.MainCurrencyType
|
||||
import com.tangem.tap.store
|
||||
import org.rekotlin.Action
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -19,81 +19,47 @@ class AmountMiddleware {
|
|||
|
||||
fun handle(rawData: String?, appState: AppState?, dispatch: (Action) -> Unit) {
|
||||
val sendState = appState?.sendState ?: return
|
||||
val walletManager = sendState.walletManager ?: return
|
||||
|
||||
val rawData = rawData ?: store.state.sendState.amountState.viewAmountValue
|
||||
val data = if (rawData == ".") "0.0" else rawData
|
||||
val proposedAmountValue = when {
|
||||
val inputValue = when {
|
||||
data.isEmpty() || data == "0" -> BigDecimal.ZERO
|
||||
else -> BigDecimal(data)
|
||||
}
|
||||
|
||||
val balanceCrypto = sendState.amount?.value ?: BigDecimal.ZERO
|
||||
val amountChecker = when (sendState.amountState.mainCurrency.value) {
|
||||
MainCurrencyType.FIAT -> FiatAmountChecker(balanceCrypto, sendState.currencyConverter)
|
||||
MainCurrencyType.CRYPTO -> CryptoAmountChecker(balanceCrypto)
|
||||
}
|
||||
if (inputValue.isZero() && sendState.amountState.amountToSendCrypto.isZero()) return
|
||||
|
||||
val checkResult = amountChecker.check(
|
||||
proposedAmountValue,
|
||||
sendState.feeState.getCurrentFee(),
|
||||
sendState.feeState.feeIsIncluded
|
||||
)
|
||||
if (checkResult.error == null) {
|
||||
dispatch(AmountAction.AmountVerification.SetAmount(checkResult.amount))
|
||||
val inputCrypto = sendState.convertInputValueToCrypto(inputValue)
|
||||
val fee = sendState.feeState.getCurrentFee()
|
||||
|
||||
val needToExtractFee = sendState.amountState.isCoinAmount() && sendState.feeState.feeIsIncluded
|
||||
val totalToSend = if (needToExtractFee) inputCrypto.minus(fee) else inputCrypto
|
||||
|
||||
val feeAmount = Amount(fee, walletManager.wallet.blockchain)
|
||||
val totalAmount = Amount(totalToSend, walletManager.wallet.blockchain)
|
||||
|
||||
val transactionErrors = walletManager.validateTransaction(totalAmount, feeAmount)
|
||||
if (transactionErrors.isEmpty()) {
|
||||
dispatch(AmountAction.AmountVerification.SetAmount(inputValue))
|
||||
} else {
|
||||
dispatch(AmountAction.AmountVerification.SetError(checkResult.amount, checkResult.error))
|
||||
val tapErrors = transactionErrors.map {
|
||||
when (it) {
|
||||
TransactionError.AmountExceedsBalance -> TapError.AmountExceedsBalance
|
||||
TransactionError.FeeExceedsBalance -> TapError.FeeExceedsBalance
|
||||
TransactionError.TotalExceedsBalance -> TapError.TotalExceedsBalance
|
||||
TransactionError.InvalidAmountValue -> TapError.InvalidAmountValue
|
||||
TransactionError.InvalidFeeValue -> TapError.InvalidFeeValue
|
||||
TransactionError.DustAmount -> TapError.DustAmount
|
||||
TransactionError.DustChange -> TapError.DustChang
|
||||
else -> TapError.UnknownError
|
||||
}
|
||||
}
|
||||
val error = TapError.ValidateTransactionErrors(tapErrors) { it.joinToString("\r\n") }
|
||||
dispatch(AmountAction.AmountVerification.SetError(inputValue, error))
|
||||
}
|
||||
dispatch(ReceiptAction.RefreshReceipt)
|
||||
dispatch(SendAction.ChangeSendButtonState(sendState.getButtonState()))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface AmountChecker {
|
||||
data class Result(val amount: BigDecimal, val error: AmountAction.Error? = null)
|
||||
|
||||
fun check(value: BigDecimal, feeCrypto: BigDecimal, feeIsIncluded: Boolean): Result
|
||||
}
|
||||
|
||||
abstract class BaseAmountChecker(
|
||||
protected val balanceCrypto: BigDecimal
|
||||
) : AmountChecker {
|
||||
|
||||
override fun check(value: BigDecimal, feeCrypto: BigDecimal, feeIsIncluded: Boolean): AmountChecker.Result {
|
||||
val convertedFee = convert(feeCrypto)
|
||||
val convertedBalance = convert(balanceCrypto)
|
||||
if (feeIsIncluded) {
|
||||
return if (value.isGreaterThan(convertedFee)) {
|
||||
if (convertedBalance.isGreaterThanOrEqual(value)) {
|
||||
AmountChecker.Result(value)
|
||||
} else {
|
||||
AmountChecker.Result(value, AmountAction.Error.FEE_GREATER_THAN_AMOUNT)
|
||||
}
|
||||
} else {
|
||||
AmountChecker.Result(value, AmountAction.Error.AMOUNT_WITH_FEE_GREATER_THAN_BALANCE)
|
||||
}
|
||||
} else {
|
||||
val amountWithFee = value.plus(convertedFee)
|
||||
return if (convertedBalance.isGreaterThanOrEqual(amountWithFee)) {
|
||||
AmountChecker.Result(value)
|
||||
} else {
|
||||
AmountChecker.Result(value, AmountAction.Error.AMOUNT_WITH_FEE_GREATER_THAN_BALANCE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun convert(value: BigDecimal): BigDecimal
|
||||
}
|
||||
|
||||
class CryptoAmountChecker(
|
||||
balanceCrypto: BigDecimal
|
||||
) : BaseAmountChecker(balanceCrypto) {
|
||||
override fun convert(value: BigDecimal): BigDecimal = value
|
||||
}
|
||||
|
||||
class FiatAmountChecker(
|
||||
balanceCrypto: BigDecimal,
|
||||
private val converter: CurrencyConverter
|
||||
) : BaseAmountChecker(balanceCrypto) {
|
||||
override fun convert(value: BigDecimal): BigDecimal = converter.toFiat(value)
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.tap.features.send.redux.reducers
|
||||
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.CurrencyConverter
|
||||
import com.tangem.tap.common.extensions.isNegative
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.features.send.redux.AmountAction
|
||||
|
|
@ -11,8 +10,6 @@ import com.tangem.tap.features.send.redux.SendScreenAction
|
|||
import com.tangem.tap.features.send.redux.states.AmountState
|
||||
import com.tangem.tap.features.send.redux.states.MainCurrencyType
|
||||
import com.tangem.tap.features.send.redux.states.SendState
|
||||
import com.tangem.tap.features.send.redux.states.Value
|
||||
import com.tangem.tap.store
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -26,7 +23,6 @@ class AmountReducer : SendInternalReducer {
|
|||
}
|
||||
|
||||
private fun handleUiAction(action: AmountActionUi, sendState: SendState, state: AmountState): SendState {
|
||||
val converter = sendState.currencyConverter
|
||||
val result = when (action) {
|
||||
is ToggleMainCurrency -> {
|
||||
val type = if (state.mainCurrency.value == MainCurrencyType.FIAT) MainCurrencyType.CRYPTO
|
||||
|
|
@ -38,21 +34,21 @@ class AmountReducer : SendInternalReducer {
|
|||
when (action.mainCurrency) {
|
||||
MainCurrencyType.FIAT -> {
|
||||
val fiatToSend = if (state.amountToSendCrypto.isZero()) BigDecimal.ZERO
|
||||
else converter.toFiat(state.amountToSendCrypto)
|
||||
else sendState.convertToFiat(state.amountToSendCrypto)
|
||||
val rescaledBalance = sendState.convertToFiat(state.balanceCrypto, true)
|
||||
state.copy(
|
||||
viewAmountValue = fiatToSend.stripZeroPlainString(),
|
||||
viewBalanceValue = converter.toFiat(state.balanceCrypto).stripZeroPlainString(),
|
||||
mainCurrency = Value(MainCurrencyType.FIAT, store.state.globalState.appCurrency),
|
||||
viewBalanceValue = rescaledBalance.stripZeroPlainString(),
|
||||
mainCurrency = state.createMainCurrencyValue(action.mainCurrency),
|
||||
maxLengthOfAmount = sendState.getDecimals(action.mainCurrency),
|
||||
cursorAtTheSamePosition = false
|
||||
)
|
||||
}
|
||||
MainCurrencyType.CRYPTO -> {
|
||||
val mainCurrency = Value(MainCurrencyType.CRYPTO, sendState.amount?.currencySymbol ?: "null")
|
||||
state.copy(
|
||||
viewAmountValue = state.amountToSendCrypto.stripZeroPlainString(),
|
||||
viewBalanceValue = state.balanceCrypto.stripZeroPlainString(),
|
||||
mainCurrency = mainCurrency,
|
||||
mainCurrency = state.createMainCurrencyValue(action.mainCurrency),
|
||||
maxLengthOfAmount = sendState.getDecimals(action.mainCurrency),
|
||||
cursorAtTheSamePosition = false
|
||||
)
|
||||
|
|
@ -69,7 +65,7 @@ class AmountReducer : SendInternalReducer {
|
|||
}
|
||||
|
||||
val etFieldValue = if (state.mainCurrency.value == MainCurrencyType.CRYPTO) maxAmount
|
||||
else converter.toFiat(maxAmount)
|
||||
else sendState.convertToFiat(maxAmount)
|
||||
state.copy(
|
||||
viewAmountValue = etFieldValue.stripZeroPlainString(),
|
||||
amountToSendCrypto = maxAmount,
|
||||
|
|
@ -83,25 +79,21 @@ class AmountReducer : SendInternalReducer {
|
|||
}
|
||||
|
||||
private fun handleAction(action: AmountAction, sendState: SendState, state: AmountState): SendState {
|
||||
val decimals = sendState.amount?.decimals ?: return sendState
|
||||
|
||||
val result = when (action) {
|
||||
is AmountAction.AmountVerification.SetAmount -> {
|
||||
setAmount(sendState.currencyConverter, decimals, action.amount, state)
|
||||
setAmount(sendState, action.amount, state)
|
||||
}
|
||||
is AmountAction.AmountVerification.SetError -> {
|
||||
setAmount(sendState.currencyConverter, decimals, action.amount, state).copy(error = action.error)
|
||||
setAmount(sendState, action.amount, state).copy(error = action.error)
|
||||
}
|
||||
}
|
||||
|
||||
return updateLastState(sendState.copy(amountState = result), result)
|
||||
|
||||
}
|
||||
|
||||
private fun setAmount(converter: CurrencyConverter, decimals: Int, amount: BigDecimal, state: AmountState): AmountState {
|
||||
private fun setAmount(sendState: SendState, amount: BigDecimal, state: AmountState): AmountState {
|
||||
return when (state.mainCurrency.value) {
|
||||
MainCurrencyType.FIAT -> {
|
||||
val amountCrypto = converter.toCrypto(amount, decimals).stripTrailingZeros()
|
||||
val amountCrypto = sendState.convertToCrypto(amount)
|
||||
state.copy(
|
||||
viewAmountValue = amount.stripZeroPlainString(),
|
||||
amountToSendCrypto = amountCrypto,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.features.send.redux.reducers
|
|||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.tap.common.CurrencyConverter
|
||||
import com.tangem.tap.common.extensions.scaleToFiat
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.features.send.redux.ReceiptAction.RefreshReceipt
|
||||
import com.tangem.tap.features.send.redux.SendScreenAction
|
||||
|
|
@ -24,20 +25,21 @@ class ReceiptReducer : SendInternalReducer {
|
|||
private fun handleRefresh(action: RefreshReceipt, sendState: SendState, state: ReceiptState): SendState {
|
||||
val wallet = sendState.walletManager?.wallet ?: return sendState
|
||||
|
||||
val converter = sendState.currencyConverter
|
||||
val coinConverter = sendState.coinConverter
|
||||
val tokenConverter = sendState.tokenConverter
|
||||
val amountState = sendState.amountState
|
||||
val feeState = sendState.feeState
|
||||
|
||||
val layoutType = determineLayoutType(amountState.mainCurrency.value, amountState.typeOfAmount)
|
||||
val layoutType = determineLayoutType(amountState.mainCurrency.value, sendState.amountState.typeOfAmount)
|
||||
val symbols = determineSymbols(wallet)
|
||||
val showBlank = !sendState.isReadyToSend()
|
||||
val result = state.copy(
|
||||
visibleTypeOfReceipt = layoutType,
|
||||
mainCurrencyType = sendState.amountState.mainCurrency,
|
||||
fiat = createFiatType(converter, amountState, feeState, symbols, showBlank),
|
||||
crypto = createCryptoType(converter, amountState, feeState, symbols, showBlank),
|
||||
tokenFiat = createTokenFiatType(converter, amountState, feeState, symbols, showBlank),
|
||||
tokenCrypto = createTokenCryptoType(converter, amountState, feeState, symbols, showBlank)
|
||||
fiat = createFiatType(coinConverter, amountState, feeState, symbols, showBlank),
|
||||
crypto = createCryptoType(coinConverter, amountState, feeState, symbols, showBlank),
|
||||
tokenFiat = createTokenFiatType(coinConverter, tokenConverter, amountState, feeState, symbols, showBlank),
|
||||
tokenCrypto = createTokenCryptoType(coinConverter, tokenConverter, amountState, feeState, symbols, showBlank)
|
||||
)
|
||||
return updateLastState(sendState.copy(receiptState = result), result)
|
||||
}
|
||||
|
|
@ -50,15 +52,15 @@ class ReceiptReducer : SendInternalReducer {
|
|||
showBlank: Boolean
|
||||
): ReceiptFiat {
|
||||
val feeCrypto = feeState.getCurrentFee()
|
||||
val feeFiat = converter.toFiat(feeCrypto)
|
||||
val feeFiat = converter.toFiatWithPrecision(feeCrypto)
|
||||
|
||||
if (showBlank) {
|
||||
return ReceiptFiat("0", feeFiat.stripZeroPlainString(), feeFiat.stripZeroPlainString(), "0", symbols)
|
||||
return ReceiptFiat("0", feeFiat.stripZeroPlainString(), "0", "0", symbols)
|
||||
}
|
||||
|
||||
return if (feeState.feeIsIncluded) {
|
||||
val amountFiat = converter.toFiat(amountState.amountToSendCrypto.minus(feeCrypto))
|
||||
val totalFiat = converter.toFiat(amountState.amountToSendCrypto)
|
||||
val amountFiat = converter.toFiatWithPrecision(amountState.amountToSendCrypto.minus(feeCrypto))
|
||||
val totalFiat = converter.toFiatWithPrecision(amountState.amountToSendCrypto)
|
||||
ReceiptFiat(
|
||||
amountFiat = amountFiat.stripZeroPlainString(),
|
||||
feeFiat = feeFiat.stripZeroPlainString(),
|
||||
|
|
@ -68,8 +70,8 @@ class ReceiptReducer : SendInternalReducer {
|
|||
)
|
||||
} else {
|
||||
val totalAmountCrypto = amountState.amountToSendCrypto.plus(feeCrypto)
|
||||
val amountFiat = converter.toFiat(amountState.amountToSendCrypto)
|
||||
val totalFiat = converter.toFiat(totalAmountCrypto)
|
||||
val amountFiat = converter.toFiatWithPrecision(amountState.amountToSendCrypto)
|
||||
val totalFiat = converter.toFiatWithPrecision(totalAmountCrypto)
|
||||
ReceiptFiat(
|
||||
amountFiat = amountFiat.stripZeroPlainString(),
|
||||
feeFiat = feeFiat.stripZeroPlainString(),
|
||||
|
|
@ -88,9 +90,9 @@ class ReceiptReducer : SendInternalReducer {
|
|||
showBlank: Boolean
|
||||
): ReceiptCrypto {
|
||||
val feeCrypto = feeState.getCurrentFee()
|
||||
|
||||
val feeFiat = converter.toFiatWithPrecision(feeCrypto)
|
||||
if (showBlank) {
|
||||
return ReceiptCrypto("0", feeCrypto.stripZeroPlainString(), "0", converter.toFiat(feeCrypto).stripZeroPlainString(), "0", symbols)
|
||||
return ReceiptCrypto("0", feeCrypto.stripZeroPlainString(), "0", "0", "0", symbols)
|
||||
}
|
||||
|
||||
if (feeState.feeIsIncluded) {
|
||||
|
|
@ -98,8 +100,8 @@ class ReceiptReducer : SendInternalReducer {
|
|||
amountCrypto = amountState.amountToSendCrypto.minus(feeCrypto).stripZeroPlainString(),
|
||||
feeCrypto = feeCrypto.stripZeroPlainString(),
|
||||
totalCrypto = amountState.amountToSendCrypto.stripZeroPlainString(),
|
||||
feeFiat = converter.toFiat(feeCrypto).stripZeroPlainString(),
|
||||
willSentFiat = converter.toFiat(amountState.amountToSendCrypto).stripZeroPlainString(),
|
||||
feeFiat = feeFiat.stripZeroPlainString(),
|
||||
willSentFiat = converter.toFiatWithPrecision(amountState.amountToSendCrypto).stripZeroPlainString(),
|
||||
symbols = symbols
|
||||
)
|
||||
} else {
|
||||
|
|
@ -108,7 +110,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
amountCrypto = amountState.amountToSendCrypto.stripZeroPlainString(),
|
||||
feeCrypto = feeCrypto.stripZeroPlainString(),
|
||||
totalCrypto = totalCrypto.stripZeroPlainString(),
|
||||
feeFiat = converter.toFiat(feeCrypto).stripZeroPlainString(),
|
||||
feeFiat = feeFiat.stripZeroPlainString(),
|
||||
willSentFiat = converter.toFiat(totalCrypto).stripZeroPlainString(),
|
||||
symbols = symbols
|
||||
)
|
||||
|
|
@ -116,47 +118,55 @@ class ReceiptReducer : SendInternalReducer {
|
|||
}
|
||||
|
||||
private fun createTokenFiatType(
|
||||
converter: CurrencyConverter,
|
||||
coinConverter: CurrencyConverter,
|
||||
tokenConverter: CurrencyConverter,
|
||||
amountState: AmountState,
|
||||
feeState: FeeState,
|
||||
symbols: ReceiptSymbols,
|
||||
showBlank: Boolean
|
||||
): ReceiptTokenFiat {
|
||||
val feeCrypto = feeState.getCurrentFee()
|
||||
val amountFiat = converter.toFiat(amountState.amountToSendCrypto)
|
||||
val feeFiat = converter.toFiat(feeCrypto)
|
||||
|
||||
val feeCoin = feeState.getCurrentFee()
|
||||
val feeFiat = coinConverter.toFiatWithPrecision(feeCoin)
|
||||
if (showBlank) {
|
||||
return ReceiptTokenFiat("0", feeFiat.stripZeroPlainString(), "0", "0", "0", symbols)
|
||||
}
|
||||
|
||||
val tokensToSend = amountState.amountToSendCrypto
|
||||
val amountFiat = tokenConverter.toFiatUnscaled(tokensToSend)
|
||||
val totalFiat = amountFiat.plus(feeFiat)
|
||||
|
||||
return ReceiptTokenFiat(
|
||||
amountFiat = amountFiat.stripZeroPlainString(),
|
||||
amountFiat = amountFiat.scaleToFiat().stripZeroPlainString(),
|
||||
feeFiat = feeFiat.stripZeroPlainString(),
|
||||
totalFiat = amountFiat.plus(feeFiat).stripZeroPlainString(),
|
||||
willSentTokenCrypto = amountState.amountToSendCrypto.stripZeroPlainString(),
|
||||
willSentFeeCrypto = feeCrypto.stripZeroPlainString(),
|
||||
totalFiat = totalFiat.scaleToFiat().stripZeroPlainString(),
|
||||
willSentToken = tokensToSend.stripZeroPlainString(),
|
||||
willSentFeeCoin = feeCoin.stripZeroPlainString(),
|
||||
symbols = symbols
|
||||
)
|
||||
}
|
||||
|
||||
private fun createTokenCryptoType(
|
||||
converter: CurrencyConverter,
|
||||
coinConverter: CurrencyConverter,
|
||||
tokenConverter: CurrencyConverter,
|
||||
amountState: AmountState,
|
||||
feeState: FeeState,
|
||||
symbols: ReceiptSymbols,
|
||||
showBlank: Boolean
|
||||
): ReceiptTokenCrypto {
|
||||
val feeCrypto = feeState.getCurrentFee()
|
||||
val totalFiat = converter.toFiat(amountState.amountToSendCrypto).plus(converter.toFiat(feeCrypto))
|
||||
val feeCoin = feeState.getCurrentFee()
|
||||
if (showBlank) {
|
||||
return ReceiptTokenCrypto("0", feeCrypto.stripZeroPlainString(), "0", symbols)
|
||||
return ReceiptTokenCrypto("0", feeCoin.stripZeroPlainString(), "0", symbols)
|
||||
}
|
||||
|
||||
val tokensToSend = amountState.amountToSendCrypto
|
||||
val tokenFiat = tokenConverter.toFiatUnscaled(tokensToSend)
|
||||
val feeFiat = coinConverter.toFiatUnscaled(feeCoin)
|
||||
val totalFiat = tokenFiat.plus(feeFiat)
|
||||
|
||||
return ReceiptTokenCrypto(
|
||||
amountToken = amountState.amountToSendCrypto.stripZeroPlainString(),
|
||||
feeCrypto = feeCrypto.stripZeroPlainString(),
|
||||
totalFiat = totalFiat.stripZeroPlainString(),
|
||||
amountToken = tokensToSend.stripZeroPlainString(),
|
||||
feeCoin = feeCoin.stripZeroPlainString(),
|
||||
totalFiat = totalFiat.scaleToFiat().stripZeroPlainString(),
|
||||
symbols = symbols
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.features.send.redux.reducers
|
||||
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.tap.common.CurrencyConverter
|
||||
import com.tangem.tap.features.send.redux.*
|
||||
import com.tangem.tap.features.send.redux.states.IdStateHolder
|
||||
|
|
@ -54,19 +54,34 @@ private class EmptyReducer : SendInternalReducer {
|
|||
|
||||
private class PrepareSendScreenStatesReducer : SendInternalReducer {
|
||||
override fun handle(action: SendScreenAction, sendState: SendState): SendState {
|
||||
val amount = (action as PrepareSendScreen).tokenAmount ?: action.coinAmount
|
||||
val prepareAction = action as PrepareSendScreen
|
||||
val walletManager = store.state.globalState.scanNoteResponse!!.walletManager!!
|
||||
val walletAmount = prepareAction.tokenAmount ?: prepareAction.coinAmount!!
|
||||
val decimals = walletAmount.decimals
|
||||
|
||||
val coinConverter = createCurrencyConverter(walletManager.wallet.blockchain.currency, decimals)
|
||||
val tokenConverter = createCurrencyConverter(prepareAction.tokenAmount?.currencySymbol ?: "", decimals)
|
||||
if (coinConverter == null || (walletAmount.type == AmountType.Token && tokenConverter == null)) {
|
||||
return sendState.copy(hasInitializationError = true)
|
||||
}
|
||||
return sendState.copy(
|
||||
amount = amount,
|
||||
walletManager = walletManager,
|
||||
currencyConverter = createCurrencyConverter(walletManager),
|
||||
amountState = sendState.amountState.copy(balanceCrypto = amount?.value ?: BigDecimal.ZERO)
|
||||
coinConverter = coinConverter,
|
||||
tokenConverter = tokenConverter ?: CurrencyConverter(BigDecimal.ONE, decimals),
|
||||
amountState = sendState.amountState.copy(
|
||||
walletAmount = walletAmount,
|
||||
typeOfAmount = walletAmount.type,
|
||||
balanceCrypto = walletAmount.value ?: BigDecimal.ZERO
|
||||
),
|
||||
feeState = sendState.feeState.copy(
|
||||
includeFeeSwitcherIsEnabled = walletAmount.type == AmountType.Coin
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun createCurrencyConverter(walletManager: WalletManager): CurrencyConverter {
|
||||
val rate = store.state.globalState.conversionRates.getRate(walletManager.wallet.blockchain.currency)
|
||||
return if (rate == null) CurrencyConverter(BigDecimal.ONE) else CurrencyConverter(rate)
|
||||
private fun createCurrencyConverter(currency: String, decimals: Int): CurrencyConverter? {
|
||||
val rate = store.state.globalState.conversionRates.getRate(currency)
|
||||
return if (rate == null) null else CurrencyConverter(rate, decimals)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@ data class AddressPayIdState(
|
|||
val recipientWalletAddress: String? = null,
|
||||
val error: AddressPayIdVerifyAction.Error? = null,
|
||||
val truncateHandler: ((String) -> String)? = null,
|
||||
val pasteIsEnabled: Boolean = false,
|
||||
override val stateId: StateId = StateId.ADDRESS_PAY_ID
|
||||
val pasteIsEnabled: Boolean = false
|
||||
) : SendScreenState {
|
||||
|
||||
override val stateId: StateId = StateId.ADDRESS_PAY_ID
|
||||
|
||||
fun isReady(): Boolean = error == null && recipientWalletAddress?.isNotEmpty() ?: false
|
||||
|
||||
fun isPayIdState(): Boolean = recipientWalletAddress != null && recipientWalletAddress != normalFieldValue
|
||||
|
|
|
|||
|
|
@ -19,9 +19,12 @@ data class FeeState(
|
|||
val mainLayoutIsVisible: Boolean = false,
|
||||
val controlsLayoutIsVisible: Boolean = false,
|
||||
val feeChipGroupIsVisible: Boolean = true,
|
||||
val includeFeeSwitcherIsEnabled: Boolean = true,
|
||||
val error: FeeAction.Error? = null,
|
||||
override val stateId: StateId = StateId.FEE
|
||||
) : SendScreenState {
|
||||
|
||||
override val stateId: StateId = StateId.FEE
|
||||
|
||||
fun isReady(): Boolean = error == null && currentFee != null
|
||||
|
||||
fun getCurrentFee(): BigDecimal = currentFee?.value?.value ?: BigDecimal.ZERO
|
||||
|
|
|
|||
|
|
@ -11,9 +11,10 @@ data class ReceiptState(
|
|||
val crypto: ReceiptCrypto? = null,
|
||||
val tokenFiat: ReceiptTokenFiat? = null,
|
||||
val tokenCrypto: ReceiptTokenCrypto? = null,
|
||||
val mainCurrencyType: Value<MainCurrencyType>? = null,
|
||||
override val stateId: StateId = StateId.RECEIPT
|
||||
) : SendScreenState
|
||||
val mainCurrencyType: Value<MainCurrencyType>? = null
|
||||
) : SendScreenState {
|
||||
override val stateId: StateId = StateId.RECEIPT
|
||||
}
|
||||
|
||||
data class ReceiptSymbols(
|
||||
val fiat: String,
|
||||
|
|
@ -40,7 +41,7 @@ data class ReceiptCrypto(
|
|||
|
||||
data class ReceiptTokenCrypto(
|
||||
val amountToken: String,
|
||||
val feeCrypto: String,
|
||||
val feeCoin: String,
|
||||
val totalFiat: String,
|
||||
val symbols: ReceiptSymbols
|
||||
)
|
||||
|
|
@ -49,7 +50,7 @@ data class ReceiptTokenFiat(
|
|||
val amountFiat: String,
|
||||
val feeFiat: String,
|
||||
val totalFiat: String,
|
||||
val willSentTokenCrypto: String,
|
||||
val willSentFeeCrypto: String,
|
||||
val willSentToken: String,
|
||||
val willSentFeeCoin: String,
|
||||
val symbols: ReceiptSymbols
|
||||
)
|
||||
|
|
@ -6,7 +6,7 @@ import com.tangem.blockchain.common.WalletManager
|
|||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.CurrencyConverter
|
||||
import com.tangem.tap.common.entities.TapCurrency
|
||||
import com.tangem.tap.features.send.redux.AmountAction
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.store
|
||||
import org.rekotlin.StateType
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -26,18 +26,20 @@ enum class StateId {
|
|||
interface SendScreenState : StateType, IdStateHolder
|
||||
|
||||
data class SendState(
|
||||
val amount: Amount? = null,
|
||||
val walletManager: WalletManager? = null,
|
||||
val currencyConverter: CurrencyConverter = CurrencyConverter(BigDecimal.ONE),
|
||||
val coinConverter: CurrencyConverter = CurrencyConverter(BigDecimal.ONE, 2),
|
||||
val tokenConverter: CurrencyConverter = CurrencyConverter(BigDecimal.ONE, 2),
|
||||
val lastChangedStates: LinkedHashSet<StateId> = linkedSetOf(),
|
||||
val addressPayIdState: AddressPayIdState = AddressPayIdState(),
|
||||
val amountState: AmountState = AmountState(),
|
||||
val feeState: FeeState = FeeState(),
|
||||
val receiptState: ReceiptState = ReceiptState(),
|
||||
val sendButtonState: SendButtonState = SendButtonState.DISABLED,
|
||||
override val stateId: StateId = StateId.SEND_SCREEN
|
||||
val hasInitializationError: Boolean = false
|
||||
) : SendScreenState {
|
||||
|
||||
override val stateId: StateId = StateId.SEND_SCREEN
|
||||
|
||||
fun isReadyToSend(): Boolean {
|
||||
val sendState = store.state.sendState
|
||||
return addressPayIdIsReady() && sendState.amountState.isReady() && sendState.feeState.isReady()
|
||||
|
|
@ -47,7 +49,28 @@ data class SendState(
|
|||
|
||||
fun getDecimals(type: MainCurrencyType): Int = when (type) {
|
||||
MainCurrencyType.FIAT -> 2
|
||||
MainCurrencyType.CRYPTO -> amount?.decimals ?: 0
|
||||
MainCurrencyType.CRYPTO -> amountState.walletAmount?.decimals ?: 0
|
||||
}
|
||||
|
||||
fun getConverter(): CurrencyConverter {
|
||||
return if (amountState.typeOfAmount == AmountType.Coin) coinConverter
|
||||
else tokenConverter
|
||||
}
|
||||
|
||||
fun convertToCrypto(value: BigDecimal): BigDecimal {
|
||||
return getConverter().toCrypto(value)
|
||||
}
|
||||
|
||||
fun convertToFiat(value: BigDecimal, scaleWithPrecision: Boolean = false): BigDecimal {
|
||||
val converter = getConverter()
|
||||
return if (scaleWithPrecision) converter.toFiat(value) else converter.toFiatWithPrecision(value)
|
||||
}
|
||||
|
||||
fun convertInputValueToCrypto(inputValue: BigDecimal): BigDecimal {
|
||||
return when (amountState.mainCurrency.value) {
|
||||
MainCurrencyType.FIAT -> convertToCrypto(inputValue)
|
||||
MainCurrencyType.CRYPTO -> inputValue
|
||||
}
|
||||
}
|
||||
|
||||
fun getButtonState(): SendButtonState = if (isReadyToSend()) SendButtonState.ENABLED else SendButtonState.DISABLED
|
||||
|
|
@ -58,18 +81,30 @@ enum class SendButtonState {
|
|||
}
|
||||
|
||||
data class AmountState(
|
||||
val walletAmount: Amount? = null,
|
||||
val typeOfAmount: AmountType = AmountType.Coin,
|
||||
val viewAmountValue: String = BigDecimal.ZERO.toPlainString(),
|
||||
val viewBalanceValue: String = BigDecimal.ZERO.toPlainString(),
|
||||
val mainCurrency: Value<MainCurrencyType> = Value(MainCurrencyType.FIAT, TapCurrency.DEFAULT_FIAT_CURRENCY),
|
||||
val typeOfAmount: AmountType = AmountType.Coin,
|
||||
val amountToSendCrypto: BigDecimal = BigDecimal.ZERO,
|
||||
val balanceCrypto: BigDecimal = BigDecimal.ZERO,
|
||||
val cursorAtTheSamePosition: Boolean = true,
|
||||
val maxLengthOfAmount: Int = 2,
|
||||
val error: AmountAction.Error? = null,
|
||||
override val stateId: StateId = StateId.AMOUNT
|
||||
val error: TapError? = null
|
||||
) : SendScreenState {
|
||||
|
||||
override val stateId: StateId = StateId.AMOUNT
|
||||
|
||||
fun isReady(): Boolean = error == null && !amountToSendCrypto.isZero()
|
||||
|
||||
fun isCoinAmount(): Boolean = typeOfAmount == AmountType.Coin
|
||||
|
||||
fun createMainCurrencyValue(type: MainCurrencyType): Value<MainCurrencyType> {
|
||||
return when (type) {
|
||||
MainCurrencyType.FIAT -> Value(type, store.state.globalState.appCurrency)
|
||||
MainCurrencyType.CRYPTO -> Value(type, walletAmount?.currencySymbol ?: "NONE")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class MainCurrencyType {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import com.tangem.tap.common.extensions.getDrawableCompat
|
|||
import com.tangem.tap.common.extensions.getFromClipboard
|
||||
import com.tangem.tap.common.extensions.setOnImeActionListener
|
||||
import com.tangem.tap.common.qrCodeScan.ScanQrCodeActivity
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.common.snackBar.MaxAmountSnackbar
|
||||
import com.tangem.tap.common.text.truncateMiddleWith
|
||||
import com.tangem.tap.common.toggleWidget.*
|
||||
|
|
@ -57,6 +58,11 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (store.state.sendState.hasInitializationError) {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
return
|
||||
}
|
||||
|
||||
initSendButtonStates()
|
||||
setupAddressOrPayIdLayout()
|
||||
setupAmountLayout()
|
||||
|
|
@ -187,6 +193,8 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
}
|
||||
|
||||
override fun subscribeToStore() {
|
||||
if (store.state.sendState.hasInitializationError) return
|
||||
|
||||
store.subscribe(sendSubscriber) { appState ->
|
||||
appState.skipRepeats { oldState, newState ->
|
||||
oldState.sendState == newState.sendState
|
||||
|
|
|
|||
|
|
@ -10,9 +10,10 @@ import com.tangem.tap.common.extensions.show
|
|||
import com.tangem.tap.common.extensions.update
|
||||
import com.tangem.tap.common.text.DecimalDigitsInputFilter
|
||||
import com.tangem.tap.common.toggleWidget.ProgressState
|
||||
import com.tangem.tap.domain.MultiMessageError
|
||||
import com.tangem.tap.domain.assembleErrorIds
|
||||
import com.tangem.tap.features.send.BaseStoreFragment
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error
|
||||
import com.tangem.tap.features.send.redux.AmountAction
|
||||
import com.tangem.tap.features.send.redux.FeeAction
|
||||
import com.tangem.tap.features.send.redux.states.*
|
||||
import com.tangem.tap.features.send.ui.FeeUiHelper
|
||||
|
|
@ -96,19 +97,21 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
}
|
||||
|
||||
private fun handleAmountState(fg: BaseStoreFragment, state: AmountState) {
|
||||
when (state.error) {
|
||||
AmountAction.Error.FEE_GREATER_THAN_AMOUNT -> {
|
||||
fg.amountContainer.parent?.beginDelayedTransition()
|
||||
fg.tilAmountToSend.enableError(true, fg.getString(R.string.error_fee_greater_than_amount))
|
||||
}
|
||||
AmountAction.Error.AMOUNT_WITH_FEE_GREATER_THAN_BALANCE -> {
|
||||
fg.amountContainer.parent?.beginDelayedTransition()
|
||||
fg.tilAmountToSend.enableError(true, fg.getString(R.string.error_amount_with_fee_greater_than_balance))
|
||||
}
|
||||
null -> {
|
||||
if (fg.tilAmountToSend.isErrorEnabled) fg.amountContainer.parent?.beginDelayedTransition()
|
||||
fg.tilAmountToSend.enableError(false)
|
||||
if (state.error != null) {
|
||||
val context = fg.requireContext()
|
||||
val message = when (state.error) {
|
||||
is MultiMessageError -> {
|
||||
val multiError = state.error as MultiMessageError
|
||||
val messageList = multiError.assembleErrorIds().map { context.getString(it) }
|
||||
multiError.builder(messageList)
|
||||
}
|
||||
else -> context.getString(state.error.localizedMessage)
|
||||
}
|
||||
fg.amountContainer.parent?.beginDelayedTransition()
|
||||
fg.tilAmountToSend.enableError(true, message)
|
||||
} else {
|
||||
if (fg.tilAmountToSend.isErrorEnabled) fg.amountContainer.parent?.beginDelayedTransition()
|
||||
fg.tilAmountToSend.enableError(false)
|
||||
}
|
||||
|
||||
fg.etAmountToSend.filters = arrayOf(DecimalDigitsInputFilter(12, state.maxLengthOfAmount))
|
||||
|
|
@ -162,6 +165,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
}
|
||||
}
|
||||
|
||||
fg.swIncludeFee.isEnabled = state.includeFeeSwitcherIsEnabled
|
||||
if (fg.swIncludeFee.isChecked != state.feeIsIncluded) {
|
||||
fg.swIncludeFee.isChecked = state.feeIsIncluded
|
||||
}
|
||||
|
|
@ -182,6 +186,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
val totalTokenLayout = fg.flTotalTokenCrypto as ViewGroup
|
||||
fun getString(id: Int): String = mainLayout.context.getString(id)
|
||||
|
||||
val rough = getString(R.string.sign_rough)
|
||||
when (state.visibleTypeOfReceipt) {
|
||||
ReceiptLayoutType.FIAT -> {
|
||||
val receipt = state.fiat ?: return
|
||||
|
|
@ -190,7 +195,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
totalTokenLayout.show(false)
|
||||
fg.tvReceiptAmountValue.update("${receipt.amountFiat} ${receipt.symbols.fiat}")
|
||||
fg.tvReceiptFeeValue.update("${receipt.feeFiat} ${receipt.symbols.fiat}")
|
||||
totalLayout.tvTotalValue.update("${receipt.totalFiat} ${receipt.symbols.fiat}")
|
||||
totalLayout.tvTotalValue.update("$rough ${receipt.totalFiat} ${receipt.symbols.fiat}")
|
||||
|
||||
val willSent = SpannableStringBuilder()
|
||||
.bold { append(receipt.willSentCrypto) }.append(" ")
|
||||
|
|
@ -210,7 +215,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
|
||||
val willSent = SpannableStringBuilder()
|
||||
.bold {
|
||||
append(getString(R.string.sign_rough)).append(" ")
|
||||
append(rough).append(" ")
|
||||
append(receipt.willSentFiat).append(" ")
|
||||
append(receipt.symbols.fiat)
|
||||
append(" (fee: ${receipt.feeFiat} ")
|
||||
|
|
@ -231,11 +236,11 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
.bold {
|
||||
append(receipt.symbols.token)
|
||||
append(" ")
|
||||
append(receipt.willSentFeeCrypto)
|
||||
append(receipt.willSentToken)
|
||||
}.append(" ").append(getString(R.string.generic_and)).append(" ")
|
||||
.bold {
|
||||
append(receipt.symbols.crypto).append(" ")
|
||||
append(receipt.willSentFeeCrypto).append(" ")
|
||||
append(receipt.willSentFeeCoin).append(" ")
|
||||
}
|
||||
.append(mainLayout.context.getString(R.string.send_total_will_be_sent))
|
||||
totalLayout.tvWillBeSentValue.update(willSent.toString())
|
||||
|
|
@ -247,7 +252,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
totalTokenLayout.show(true)
|
||||
|
||||
fg.tvReceiptAmountValue.update("${receipt.amountToken} ${receipt.symbols.token}")
|
||||
fg.tvReceiptFeeValue.update("${receipt.feeCrypto} ${receipt.symbols.crypto}")
|
||||
fg.tvReceiptFeeValue.update("${receipt.feeCoin} ${receipt.symbols.crypto}")
|
||||
|
||||
val willSent = SpannableStringBuilder()
|
||||
.bold {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue