Updated on 2026-08-14
This commit is contained in:
parent
5448004713
commit
6eee63c0d4
8 changed files with 53 additions and 41 deletions
|
|
@ -64,7 +64,7 @@ dependencies {
|
|||
implementation 'com.google.android.material:material:1.2.1'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
|
||||
|
||||
implementation 'com.tangem:blockchain:1.35.0'
|
||||
implementation 'com.tangem:blockchain:1.37.0'
|
||||
|
||||
//lifecycle
|
||||
implementation "androidx.lifecycle:lifecycle-runtime:2.2.0"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.tap.features.send.redux.middlewares
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.TransactionError
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
@ -41,11 +40,7 @@ class AmountMiddleware {
|
|||
if (inputValue.isZero() && amountState.amountToSendCrypto.isZero()) return
|
||||
|
||||
val inputValueCrypto = if (amountState.mainCurrency.type == MainCurrencyType.CRYPTO) inputValue
|
||||
else when (amountState.typeOfAmount) {
|
||||
AmountType.Coin -> sendState.convertFiatToCoin(inputValue)
|
||||
AmountType.Token -> sendState.convertFiatToToken(inputValue)
|
||||
else -> inputValue
|
||||
}
|
||||
else sendState.convertFiatToExtractCrypto(inputValue)
|
||||
|
||||
dispatch(AmountAction.SetAmount(inputValueCrypto, true))
|
||||
dispatch(AmountActionUi.CheckAmountToSend)
|
||||
|
|
@ -54,6 +49,7 @@ class AmountMiddleware {
|
|||
private fun checkAmountToSend(appState: AppState?, dispatch: (Action) -> Unit) {
|
||||
val sendState = appState?.sendState ?: return
|
||||
val walletManager = sendState.walletManager ?: return
|
||||
val typedAmount = sendState.amountState.amountToExtract ?: return
|
||||
|
||||
val inputCrypto = sendState.amountState.amountToSendCrypto
|
||||
if (sendState.amountState.viewAmountValue.value == "0" && inputCrypto.isZero()) {
|
||||
|
|
@ -62,12 +58,8 @@ class AmountMiddleware {
|
|||
return
|
||||
}
|
||||
|
||||
val feeCrypto = sendState.feeState.getCurrentFee()
|
||||
|
||||
val feeAmount = Amount(feeCrypto, walletManager.wallet.blockchain)
|
||||
val totalAmount = Amount(sendState.getTotalAmountToSend(inputCrypto), walletManager.wallet.blockchain)
|
||||
|
||||
val transactionErrors = walletManager.validateTransaction(totalAmount, feeAmount)
|
||||
val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend(inputCrypto))
|
||||
val transactionErrors = walletManager.validateTransaction(amountToSend, sendState.feeState.currentFee)
|
||||
if (transactionErrors.isEmpty()) {
|
||||
dispatch(AmountAction.SetAmountError(null))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.Middleware
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -43,10 +44,9 @@ private fun verifyAndSendTransaction(appState: AppState?, dispatch: (Action) ->
|
|||
val walletManager = appState.globalState.scanNoteResponse?.walletManager ?: return
|
||||
val recipientAddress = sendState.addressPayIdState.recipientWalletAddress ?: return
|
||||
val typedAmount = sendState.amountState.amountToExtract ?: return
|
||||
val feeAmount = sendState.feeState.currentFee ?: return
|
||||
|
||||
val feeAmount = Amount(sendState.feeState.getCurrentFee(), walletManager.wallet.blockchain)
|
||||
val totalToSend = sendState.getTotalAmountToSend()
|
||||
val amountToSend = Amount(typedAmount.currencySymbol, totalToSend, recipientAddress, typedAmount.decimals, typedAmount.type)
|
||||
val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend())
|
||||
|
||||
val verifyResult = walletManager.validateTransaction(amountToSend, feeAmount)
|
||||
if (verifyResult.isNotEmpty()) {
|
||||
|
|
@ -57,6 +57,7 @@ private fun verifyAndSendTransaction(appState: AppState?, dispatch: (Action) ->
|
|||
dispatch(SendAction.ChangeSendButtonState(SendButtonState.PROGRESS))
|
||||
val txData = walletManager.createTransaction(amountToSend, feeAmount, recipientAddress)
|
||||
scope.launch {
|
||||
walletManager.update()
|
||||
val result = (walletManager as TransactionSender).send(txData, Signer(tangemSdk))
|
||||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
|
|
@ -76,6 +77,7 @@ private fun verifyAndSendTransaction(appState: AppState?, dispatch: (Action) ->
|
|||
// user was cancelled the operation by closing the Sdk bottom sheet
|
||||
}
|
||||
else -> {
|
||||
Timber.e(result.error)
|
||||
dispatch(SendAction.SendError(TapError.BlockchainInternalError))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ class AmountReducer : SendInternalReducer {
|
|||
when (val currency = if (currencyCanBeSwitched) action.mainCurrency else MainCurrencyType.CRYPTO) {
|
||||
MainCurrencyType.FIAT -> {
|
||||
val fiatToSend = if (state.amountToSendCrypto.isZero()) BigDecimal.ZERO
|
||||
else sendState.convertCoinToFiat(state.amountToSendCrypto)
|
||||
val rescaledBalance = sendState.convertCoinToFiat(state.balanceCrypto, true)
|
||||
else sendState.convertExtractCryptoToFiat(state.amountToSendCrypto)
|
||||
val rescaledBalance = sendState.convertExtractCryptoToFiat(state.balanceCrypto, true)
|
||||
state.copy(
|
||||
viewAmountValue = InputViewValue(fiatToSend.stripZeroPlainString()),
|
||||
viewBalanceValue = rescaledBalance.stripZeroPlainString(),
|
||||
|
|
@ -61,7 +61,7 @@ class AmountReducer : SendInternalReducer {
|
|||
val result = when (action) {
|
||||
is AmountAction.SetAmount -> {
|
||||
val amount = if (state.mainCurrency.type == MainCurrencyType.CRYPTO) action.amountCrypto
|
||||
else sendState.convertCoinToFiat(action.amountCrypto, true)
|
||||
else sendState.convertExtractCryptoToFiat(action.amountCrypto, true)
|
||||
state.copy(
|
||||
viewAmountValue = InputViewValue(amount.stripZeroPlainString(), action.isUserInput),
|
||||
amountToSendCrypto = action.amountCrypto,
|
||||
|
|
|
|||
|
|
@ -15,10 +15,13 @@ import java.math.BigDecimal
|
|||
*/
|
||||
class ReceiptReducer : SendInternalReducer {
|
||||
|
||||
companion object {
|
||||
const val EMPTY = "-"
|
||||
}
|
||||
|
||||
private lateinit var sendState: SendState
|
||||
private lateinit var amountState: AmountState
|
||||
private lateinit var feeState: FeeState
|
||||
private val EMPTY = "-"
|
||||
|
||||
override fun handle(action: SendScreenAction, sendState: SendState): SendState {
|
||||
this.sendState = sendState
|
||||
|
|
@ -50,7 +53,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
}
|
||||
|
||||
private fun createFiatType(symbols: ReceiptSymbols, showBlank: Boolean): ReceiptFiat {
|
||||
val feeCrypto = feeState.getCurrentFee()
|
||||
val feeCrypto = feeState.getCurrentFeeValue()
|
||||
val feeFiat = convertToFiatPrecision(feeCrypto)
|
||||
|
||||
if (showBlank) {
|
||||
|
|
@ -82,7 +85,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
}
|
||||
|
||||
private fun createCryptoType(symbols: ReceiptSymbols, showBlank: Boolean): ReceiptCrypto {
|
||||
val feeCrypto = feeState.getCurrentFee()
|
||||
val feeCrypto = feeState.getCurrentFeeValue()
|
||||
val feeFiat = convertToFiatPrecision(feeCrypto)
|
||||
if (showBlank) {
|
||||
return ReceiptCrypto("0", feeCrypto.stripZeroPlainString(), "0", "0", "0", symbols)
|
||||
|
|
@ -111,7 +114,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
}
|
||||
|
||||
private fun createTokenFiatType(symbols: ReceiptSymbols, showBlank: Boolean): ReceiptTokenFiat {
|
||||
val feeCoin = feeState.getCurrentFee()
|
||||
val feeCoin = feeState.getCurrentFeeValue()
|
||||
if (showBlank) {
|
||||
val feeFiat = convertToFiatPrecision(feeCoin)
|
||||
return ReceiptTokenFiat("0", feeFiat, "0", "0", "0", symbols)
|
||||
|
|
@ -124,9 +127,9 @@ class ReceiptReducer : SendInternalReducer {
|
|||
val amountFiat = sendState.tokenConverter!!.toFiatUnscaled(tokensToSend)
|
||||
val totalFiat = amountFiat.plus(feeFiat)
|
||||
ReceiptTokenFiat(
|
||||
amountFiat = amountFiat.scaleToFiat().stripZeroPlainString(),
|
||||
feeFiat = feeFiat.stripZeroPlainString(),
|
||||
totalFiat = totalFiat.scaleToFiat().stripZeroPlainString(),
|
||||
amountFiat = amountFiat.scaleToFiat(true).stripZeroPlainString(),
|
||||
feeFiat = feeFiat.scaleToFiat(true).stripZeroPlainString(),
|
||||
totalFiat = totalFiat.scaleToFiat(true).stripZeroPlainString(),
|
||||
willSentToken = tokensToSend.stripZeroPlainString(),
|
||||
willSentFeeCoin = feeCoin.stripZeroPlainString(),
|
||||
symbols = symbols
|
||||
|
|
@ -144,7 +147,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
}
|
||||
|
||||
private fun createTokenCryptoType(symbols: ReceiptSymbols, showBlank: Boolean): ReceiptTokenCrypto {
|
||||
val feeCoin = feeState.getCurrentFee()
|
||||
val feeCoin = feeState.getCurrentFeeValue()
|
||||
if (showBlank) {
|
||||
return ReceiptTokenCrypto("0", feeCoin.stripZeroPlainString(), "0", symbols)
|
||||
}
|
||||
|
|
@ -158,7 +161,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
ReceiptTokenCrypto(
|
||||
amountToken = tokensToSend.stripZeroPlainString(),
|
||||
feeCoin = feeCoin.stripZeroPlainString(),
|
||||
totalFiat = totalFiat.scaleToFiat().stripZeroPlainString(),
|
||||
totalFiat = totalFiat.scaleToFiat(true).stripZeroPlainString(),
|
||||
symbols = symbols
|
||||
)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -27,5 +27,5 @@ data class FeeState(
|
|||
|
||||
fun isReady(): Boolean = error == null && currentFee != null
|
||||
|
||||
fun getCurrentFee(): BigDecimal = currentFee?.value ?: BigDecimal.ZERO
|
||||
fun getCurrentFeeValue(): BigDecimal = currentFee?.value ?: BigDecimal.ZERO
|
||||
}
|
||||
|
|
@ -56,6 +56,11 @@ data class SendState(
|
|||
else coinConverter!!.toCrypto(value)
|
||||
}
|
||||
|
||||
fun convertFiatToToken(value: BigDecimal): BigDecimal {
|
||||
return if (!this.tokenIsConvertible()) value
|
||||
else tokenConverter!!.toCrypto(value)
|
||||
}
|
||||
|
||||
fun convertCoinToFiat(value: BigDecimal, scaleWithPrecision: Boolean = false): BigDecimal {
|
||||
if (!this.coinIsConvertible()) return value
|
||||
|
||||
|
|
@ -63,11 +68,6 @@ data class SendState(
|
|||
return if (!scaleWithPrecision) converter.toFiat(value) else converter.toFiatWithPrecision(value)
|
||||
}
|
||||
|
||||
fun convertFiatToToken(value: BigDecimal): BigDecimal {
|
||||
return if (!this.tokenIsConvertible()) value
|
||||
else tokenConverter!!.toCrypto(value)
|
||||
}
|
||||
|
||||
fun convertTokenToFiat(value: BigDecimal, scaleWithPrecision: Boolean = false): BigDecimal {
|
||||
if (!this.tokenIsConvertible()) return value
|
||||
|
||||
|
|
@ -75,11 +75,25 @@ data class SendState(
|
|||
return if (!scaleWithPrecision) converter.toFiat(value) else converter.toFiatWithPrecision(value)
|
||||
}
|
||||
|
||||
fun convertFiatToExtractCrypto(fiatValue: BigDecimal): BigDecimal = when (amountState.typeOfAmount) {
|
||||
AmountType.Coin -> convertFiatToCoin(fiatValue)
|
||||
AmountType.Token -> convertFiatToToken(fiatValue)
|
||||
AmountType.Reserve -> fiatValue
|
||||
}
|
||||
|
||||
fun convertExtractCryptoToFiat(cryptoValue: BigDecimal, scaleWithPrecision: Boolean = false): BigDecimal {
|
||||
return when (amountState.typeOfAmount) {
|
||||
AmountType.Coin -> convertCoinToFiat(cryptoValue, scaleWithPrecision)
|
||||
AmountType.Token -> convertTokenToFiat(cryptoValue, scaleWithPrecision)
|
||||
AmountType.Reserve -> cryptoValue
|
||||
}
|
||||
}
|
||||
|
||||
fun getButtonState(): SendButtonState = if (isReadyToSend()) SendButtonState.ENABLED else SendButtonState.DISABLED
|
||||
|
||||
fun getTotalAmountToSend(value: BigDecimal = amountState.amountToSendCrypto): BigDecimal {
|
||||
val needToExtractFee = amountState.isCoinAmount() && feeState.feeIsIncluded
|
||||
return if (needToExtractFee) value.minus(feeState.getCurrentFee()) else value
|
||||
return if (needToExtractFee) value.minus(feeState.getCurrentFeeValue()) else value
|
||||
}
|
||||
|
||||
fun coinIsConvertible(): Boolean = coinConverter != null
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ 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.FeeAction
|
||||
import com.tangem.tap.features.send.redux.reducers.ReceiptReducer
|
||||
import com.tangem.tap.features.send.redux.states.*
|
||||
import com.tangem.tap.features.send.ui.FeeUiHelper
|
||||
import com.tangem.tap.features.send.ui.SendFragment
|
||||
|
|
@ -183,6 +184,8 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
fun getString(id: Int): String = mainLayout.context.getString(id)
|
||||
|
||||
val rough = getString(R.string.sign_rough)
|
||||
fun roughOrEmpty(value: String): String = if (value == ReceiptReducer.EMPTY) value else "$rough $value"
|
||||
|
||||
when (state.visibleTypeOfReceipt) {
|
||||
ReceiptLayoutType.FIAT -> {
|
||||
val receipt = state.fiat ?: return
|
||||
|
|
@ -191,7 +194,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("$rough ${receipt.totalFiat} ${receipt.symbols.fiat}")
|
||||
totalLayout.tvTotalValue.update("${roughOrEmpty(receipt.totalFiat)} ${receipt.symbols.fiat}")
|
||||
|
||||
val willSent = SpannableStringBuilder()
|
||||
.bold { append(receipt.willSentCrypto) }.append(" ")
|
||||
|
|
@ -211,8 +214,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
|
||||
val willSent = SpannableStringBuilder()
|
||||
.bold {
|
||||
append(rough).append(" ")
|
||||
append(receipt.willSentFiat).append(" ")
|
||||
append(roughOrEmpty(receipt.willSentFiat)).append(" ")
|
||||
append(receipt.symbols.fiat)
|
||||
append(" (fee: ${receipt.feeFiat} ")
|
||||
append(receipt.symbols.fiat).append(")")
|
||||
|
|
@ -226,7 +228,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("${roughOrEmpty(receipt.totalFiat)} ${receipt.symbols.fiat}")
|
||||
|
||||
val willSent = SpannableStringBuilder()
|
||||
.bold {
|
||||
|
|
@ -252,8 +254,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
|
||||
val willSent = SpannableStringBuilder()
|
||||
.bold {
|
||||
append(getString(R.string.sign_rough)).append(" ")
|
||||
append(receipt.totalFiat).append(" ")
|
||||
append(roughOrEmpty(receipt.totalFiat)).append(" ")
|
||||
append(receipt.symbols.fiat)
|
||||
}
|
||||
totalTokenLayout.tvTotalTokenCryptoValue.update(willSent.toString())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue