Updated on 2026-08-14

This commit is contained in:
Tangem 2022-03-18 21:28:08 +03:00
parent 6dd6f50a45
commit eb073895c1
9 changed files with 134 additions and 104 deletions

View file

@ -4,6 +4,7 @@ import android.graphics.Bitmap
import com.tangem.blockchain.common.*
import com.tangem.blockchain.common.address.AddressType
import com.tangem.blockchain.extensions.isAboveZero
import com.tangem.common.extensions.isZero
import com.tangem.tap.common.entities.Button
import com.tangem.tap.common.extensions.toQrCode
import com.tangem.tap.common.redux.StateDialog
@ -248,17 +249,27 @@ data class WalletData(
val currencyData: BalanceWidgetData = BalanceWidgetData(),
val updatingWallet: Boolean = false,
val tradeCryptoState: TradeCryptoState = TradeCryptoState(),
val allowToSend: Boolean = true,
val fiatRateString: String? = null,
val fiatRate: BigDecimal? = null,
val mainButton: WalletMainButton = WalletMainButton.SendButton(false),
val currency: Currency,
val walletRent: WalletRent? = null,
val warningRent: WalletRent? = null,
val blockchainAmount: BigDecimal? = BigDecimal.ZERO
) {
fun shouldShowMultipleAddress(): Boolean {
val listOfAddresses = walletAddresses?.list ?: return false
return listOfAddresses.size > 1
}
fun shouldShowCoinAmountWarning(): Boolean = when (currency) {
is Currency.Blockchain -> false
is Currency.Token -> blockchainAmountIsEmpty() && !tokenAmountIsEmpty()
}
fun shouldEnableTokenSendButton(): Boolean = !blockchainAmountIsEmpty() || !tokenAmountIsEmpty()
private fun blockchainAmountIsEmpty(): Boolean = blockchainAmount?.isZero() ?: false
private fun tokenAmountIsEmpty(): Boolean = currencyData.amount?.isZero() == true
}
data class WalletRent(

View file

@ -29,15 +29,15 @@ class MultiWalletReducer {
null
}
WalletData(
currencyData = BalanceWidgetData(
BalanceStatus.Loading,
blockchain.fullName,
currencySymbol = blockchain.currency,
token = cardToken
),
walletAddresses = createAddressList(wallet),
mainButton = WalletMainButton.SendButton(false),
currency = Currency.Blockchain(blockchain),
currencyData = BalanceWidgetData(
BalanceStatus.Loading,
blockchain.fullName,
currencySymbol = blockchain.currency,
token = cardToken
),
walletAddresses = createAddressList(wallet),
mainButton = WalletMainButton.SendButton(false),
currency = Currency.Blockchain(blockchain),
)
}
@ -47,21 +47,21 @@ class MultiWalletReducer {
state.selectedCurrency
}
state.copy(
walletsData = walletsData,
selectedCurrency = selectedCurrency
walletsData = walletsData,
selectedCurrency = selectedCurrency
)
}
is WalletAction.MultiWallet.AddBlockchain -> {
val wallet = state.getWalletManager(action.blockchain)?.wallet
val walletData = WalletData(
currencyData = BalanceWidgetData(
BalanceStatus.Loading,
action.blockchain.fullName,
currencySymbol = action.blockchain.currency,
),
walletAddresses = createAddressList(wallet),
mainButton = WalletMainButton.SendButton(false),
currency = Currency.Blockchain(action.blockchain),
currencyData = BalanceWidgetData(
BalanceStatus.Loading,
action.blockchain.fullName,
currencySymbol = action.blockchain.currency,
),
walletAddresses = createAddressList(wallet),
mainButton = WalletMainButton.SendButton(false),
currency = Currency.Blockchain(action.blockchain),
)
val newState = state.copy(walletsData = state.replaceWalletInWallets(walletData))
if (wallet != null && wallet.amounts[AmountType.Coin]?.value != null) {
@ -80,13 +80,13 @@ class MultiWalletReducer {
}
is WalletAction.MultiWallet.TokenLoaded -> {
val pendingTransactions = state.getWalletManager(action.token)
?.wallet?.let { wallet ->
wallet.recentTransactions.toPendingTransactions(wallet.address)
} ?: emptyList()
?.wallet?.let { wallet ->
wallet.recentTransactions.toPendingTransactions(wallet.address)
} ?: emptyList()
val sendButtonEnabled = action.amount.value?.isZero() == false && pendingTransactions.isEmpty()
val tokenPendingTransactions = pendingTransactions
.filter { it.currency == action.amount.currencySymbol }
.filter { it.currency == action.amount.currencySymbol }
val tokenBalanceStatus = when {
tokenPendingTransactions.isNotEmpty() -> BalanceStatus.TransactionInProgress
pendingTransactions.isNotEmpty() -> BalanceStatus.SameCurrencyTransactionInProgress
@ -94,19 +94,20 @@ class MultiWalletReducer {
}
val tokenWalletData = state.getWalletData(action.token)
val newTokenWalletData = tokenWalletData?.copy(
currencyData = tokenWalletData.currencyData.copy(
status = tokenBalanceStatus,
amount = action.amount.value?.toFormattedCurrencyString(
action.amount.decimals, action.amount.currencySymbol
),
fiatAmountFormatted = tokenWalletData.fiatRate?.let {
action.amount.value
?.toFiatString(it, store.state.globalState.appCurrency)
}
currencyData = tokenWalletData.currencyData.copy(
status = tokenBalanceStatus,
amount = action.amount.value,
amountFormatted = action.amount.value?.toFormattedCurrencyString(
action.amount.decimals, action.amount.currencySymbol
),
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
currency = Currency.Token(action.token)
fiatAmountFormatted = tokenWalletData.fiatRate?.let {
action.amount.value
?.toFiatString(it, store.state.globalState.appCurrency)
}
),
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
currency = Currency.Token(action.token)
)
val wallets = state.replaceWalletInWallets(newTokenWalletData)
state.copy(walletsData = wallets)

View file

@ -36,11 +36,11 @@ class OnWalletLoadedReducer {
return walletState
}
val formattedAmount = coinAmountValue?.toFormattedCurrencyString(
wallet.blockchain.decimals(),
wallet.blockchain.currency)
wallet.blockchain.decimals(),
wallet.blockchain.currency)
val pendingTransactions = wallet.recentTransactions
.toPendingTransactions(wallet.address)
.toPendingTransactions(wallet.address)
val coinSendButton = coinAmountValue?.isZero() == false && pendingTransactions.isEmpty()
val balanceStatus = if (pendingTransactions.isNotEmpty()) {
@ -52,17 +52,19 @@ class OnWalletLoadedReducer {
val fiatAmount = walletData?.fiatRate?.let { coinAmountValue?.toFiatValue(it) }
val newWalletData = walletData?.copy(
currencyData = walletData.currencyData.copy(
status = balanceStatus, currency = wallet.blockchain.fullName,
currencySymbol = wallet.blockchain.currency,
amount = formattedAmount,
fiatAmount = fiatAmount,
fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrencySymbol)
),
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
mainButton = WalletMainButton.SendButton(coinSendButton),
currency = Currency.Blockchain(wallet.blockchain),
tradeCryptoState = TradeCryptoState.from(exchangeManager, walletData)
currencyData = walletData.currencyData.copy(
status = balanceStatus, currency = wallet.blockchain.fullName,
currencySymbol = wallet.blockchain.currency,
amount = coinAmountValue,
amountFormatted = formattedAmount,
fiatAmount = fiatAmount,
fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrencySymbol)
),
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
mainButton = WalletMainButton.SendButton(coinSendButton),
currency = Currency.Blockchain(wallet.blockchain),
tradeCryptoState = TradeCryptoState.from(exchangeManager, walletData),
blockchainAmount = coinAmountValue
)
val tokens = wallet.getTokens().mapNotNull { token ->
@ -73,20 +75,23 @@ class OnWalletLoadedReducer {
pendingTransactions.isNotEmpty() -> BalanceStatus.SameCurrencyTransactionInProgress
else -> BalanceStatus.VerifiedOnline
}
val tokenAmountValue = wallet.getTokenAmount(token)?.value
val tokenFiatAmount = tokenWalletData?.fiatRate?.let { rate -> tokenAmountValue?.toFiatValue(rate)}
val tokenAmountValue = wallet.getTokenAmount(token)?.value
val tokenFiatAmount = tokenWalletData?.fiatRate?.let { rate -> tokenAmountValue?.toFiatValue(rate) }
val tokenSendButton = tokenAmountValue?.isZero() == false && tokenPendingTransactions.isEmpty()
val tokenSendButton = newWalletData?.shouldEnableTokenSendButton() == true
&& tokenPendingTransactions.isEmpty()
tokenWalletData?.copy(
currencyData = tokenWalletData.currencyData.copy(
status = tokenBalanceStatus,
amount = tokenAmountValue?.toFormattedCurrencyString(token.decimals, token.symbol),
fiatAmount = tokenFiatAmount,
fiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrencySymbol)
),
pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(),
mainButton = WalletMainButton.SendButton(tokenSendButton),
tradeCryptoState = TradeCryptoState.from(exchangeManager, tokenWalletData)
currencyData = tokenWalletData.currencyData.copy(
status = tokenBalanceStatus,
amount = tokenAmountValue,
amountFormatted = tokenAmountValue?.toFormattedCurrencyString(token.decimals, token.symbol),
fiatAmount = tokenFiatAmount,
fiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrencySymbol)
),
pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(),
mainButton = WalletMainButton.SendButton(tokenSendButton),
tradeCryptoState = TradeCryptoState.from(exchangeManager, tokenWalletData),
blockchainAmount = coinAmountValue
)
}
val newWallets = (tokens + newWalletData).mapNotNull { it }
@ -98,7 +103,7 @@ class OnWalletLoadedReducer {
ProgressState.Done
}
return walletState.copy(
state = state, walletsData = wallets, error = null
state = state, walletsData = wallets, error = null
)
}
@ -128,16 +133,13 @@ class OnWalletLoadedReducer {
}
val amount = wallet.amounts[AmountType.Coin]?.value
val formattedAmount = amount?.toFormattedCurrencyString(
wallet.blockchain.decimals(),
wallet.blockchain.currency)
wallet.blockchain.decimals(),
wallet.blockchain.currency)
val fiatRate = walletState.primaryWallet?.fiatRate
val fiatAmountRaw = fiatRate?.multiply(amount)?.setScale(2, RoundingMode.DOWN)
val fiatAmount = fiatRate?.let { amount?.toFiatString(it, fiatCurrencySymbol) }
val pendingTransactions = wallet.recentTransactions
.toPendingTransactions(wallet.address)
//TO:
val pendingTransactions = wallet.recentTransactions.toPendingTransactions(wallet.address)
val sendButtonEnabled = amount?.isZero() == false && pendingTransactions.isEmpty()
val balanceStatus = if (pendingTransactions.isNotEmpty()) {
BalanceStatus.TransactionInProgress
@ -145,21 +147,23 @@ class OnWalletLoadedReducer {
BalanceStatus.VerifiedOnline
}
val walletData = walletState.primaryWallet?.copy(
currencyData = BalanceWidgetData(
balanceStatus, wallet.blockchain.fullName,
currencySymbol = wallet.blockchain.currency,
formattedAmount,
token = tokenData,
fiatAmountFormatted = fiatAmount,
fiatAmount = fiatAmountRaw
),
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
tradeCryptoState = TradeCryptoState.from(exchangeManager, walletState.primaryWallet)
currencyData = BalanceWidgetData(
balanceStatus, wallet.blockchain.fullName,
currencySymbol = wallet.blockchain.currency,
token = tokenData,
amount = amount,
amountFormatted = formattedAmount,
fiatAmountFormatted = fiatAmount,
fiatAmount = fiatAmountRaw
),
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
tradeCryptoState = TradeCryptoState.from(exchangeManager, walletState.primaryWallet),
blockchainAmount = amount
)
val wallets = walletData?.let { listOf(walletData) } ?: emptyList()
return walletState.copy(
state = ProgressState.Done, walletsData = wallets, error = null
state = ProgressState.Done, walletsData = wallets, error = null
)
}
}

View file

@ -246,7 +246,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
if (walletData == null) {
newState
} else {
walletData = walletData.copy(walletRent = WalletRent(action.minRent, action.rentExempt))
walletData = walletData.copy(warningRent = WalletRent(action.minRent, action.rentExempt))
newState = newState.copy(
walletsData = newState.replaceSomeWallets(listOf(walletData))
)

View file

@ -22,7 +22,8 @@ data class BalanceWidgetData(
val status: BalanceStatus? = null,
val currency: String? = null,
val currencySymbol: String? = null,
val amount: String? = null,
val amount: BigDecimal? = null,
val amountFormatted: String? = null,
val fiatAmountFormatted: String? = null,
val fiatAmount: BigDecimal? = null,
val token: TokenData? = null,
@ -149,7 +150,7 @@ class BalanceWidget(
tvCurrency.text = data.token?.tokenSymbol
tvBaseCurrency.text = data.currency
tvAmount.text = if (showAmount) data.token?.amount else ""
tvBaseAmount.text = if (showAmount) data.amount else ""
tvBaseAmount.text = if (showAmount) data.amountFormatted else ""
if (showAmount) {
tvFiatAmount.show()
tvFiatAmount.text = data.token?.fiatAmount
@ -160,7 +161,7 @@ class BalanceWidget(
with(binding.lBalance) {
groupBaseCurrency.hide()
tvCurrency.text = data.currency
tvAmount.text = if (showAmount) data.amount else ""
tvAmount.text = if (showAmount) data.amountFormatted else ""
if (showAmount) {
tvFiatAmount.show()
tvFiatAmount.text = data.fiatAmountFormatted

View file

@ -107,8 +107,8 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
handleDialogs(state.walletDialog)
handleCurrencyIcon(selectedWallet)
handleWalletRent(selectedWallet.walletRent)
handleWalletRent(selectedWallet.warningRent)
handleNotEnoughFundsOnMainCurrency(selectedWallet)
binding.srlWalletDetails.setOnRefreshListener {
if (selectedWallet.currencyData.status != BalanceStatus.Loading) {
@ -153,14 +153,27 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
private fun handleWalletRent(rent: WalletRent?) = with(binding) {
val rent = rent.guard {
lRentWarning.root.hide()
lWarning.root.hide()
return
}
val warningMessage = requireContext().getString(
R.string.solana_rent_warning, rent.minRentValue, rent.rentExemptValue
)
lRentWarning.tvRentWarningMessage.text = warningMessage
lRentWarning.root.show()
lWarning.tvWarningMessage.text = warningMessage
lWarning.root.show()
}
private fun handleNotEnoughFundsOnMainCurrency(selectedWalletData: WalletData) = with(binding) {
if (selectedWalletData.shouldShowCoinAmountWarning()) {
val blockchainName = selectedWalletData.currency.blockchain.fullName
val warningMessage = requireContext().getString(
R.string.token_details_send_blocked_fee_format, blockchainName, blockchainName
)
lWarning.tvWarningMessage.text = warningMessage
lWarning.root.show()
} else {
lWarning.root.hide()
}
}
private fun handleCurrencyIcon(wallet: WalletData) = with(binding.lWalletDetails.lBalance) {
@ -234,7 +247,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
lBalance.root.show()
lBalance.groupBalance.show()
lBalance.tvError.hide()
lBalance.tvAmount.text = data.amount
lBalance.tvAmount.text = data.amountFormatted
lBalance.tvFiatAmount.text = data.fiatAmountFormatted
lBalance.tvStatus.setLoadingStatus(R.string.wallet_balance_loading)
}
@ -244,7 +257,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
lBalance.root.show()
lBalance.groupBalance.show()
lBalance.tvError.hide()
lBalance.tvAmount.text = data.amount
lBalance.tvAmount.text = data.amountFormatted
lBalance.tvFiatAmount.text = data.fiatAmountFormatted
when (data.status) {
BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress -> {

View file

@ -57,8 +57,8 @@ class WalletAdapter
fun bind(wallet: WalletData) = with(binding) {
tvCurrency.text = wallet.currencyData.currency
tvAmount.text = wallet.currencyData.amount?.takeWhile { !it.isWhitespace() }
tvCurrencySymbol.text = wallet.currencyData.amount?.takeLastWhile { !it.isWhitespace() }
tvAmount.text = wallet.currencyData.amountFormatted?.takeWhile { !it.isWhitespace() }
tvCurrencySymbol.text = wallet.currencyData.amountFormatted?.takeLastWhile { !it.isWhitespace() }
tvAmountFiat.text = wallet.currencyData.fiatAmountFormatted
tvExchangeRate.text = wallet.fiatRateString
cardWallet.setOnClickListener {
@ -77,7 +77,7 @@ class WalletAdapter
BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress -> hideWarning()
BalanceStatus.Loading -> {
hideWarning()
if (wallet.currencyData.amount == null) {
if (wallet.currencyData.amountFormatted == null) {
tvExchangeRate.text = root.getString(R.string.wallet_balance_loading)
}
}

View file

@ -99,8 +99,8 @@
app:layout_constraintTop_toBottomOf="@id/rv_pending_transaction" />
<include
android:id="@+id/l_rent_warning"
layout="@layout/layout_wallet_details_rent"
android:id="@+id/l_warning"
layout="@layout/layout_wallet_details_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@ -168,7 +168,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn_sell"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/l_rent_warning"
app:layout_constraintTop_toBottomOf="@+id/l_warning"
app:layout_constraintVertical_bias="1" />
<com.google.android.material.button.MaterialButton
@ -185,7 +185,7 @@
app:layout_constraintEnd_toStartOf="@id/btn_confirm"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@id/btn_trade"
app:layout_constraintTop_toBottomOf="@+id/l_rent_warning"
app:layout_constraintTop_toBottomOf="@+id/l_warning"
app:layout_constraintVertical_bias="1" />
<com.google.android.material.button.MaterialButton
@ -201,7 +201,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/btn_sell"
app:layout_constraintTop_toBottomOf="@+id/l_rent_warning"
app:layout_constraintTop_toBottomOf="@+id/l_warning"
app:layout_constraintVertical_bias="1" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -13,7 +13,7 @@
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_rent_warning_title"
android:id="@+id/tv_warning_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@ -27,7 +27,7 @@
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_rent_warning_message"
android:id="@+id/tv_warning_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@ -39,7 +39,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_rent_warning_title"
app:layout_constraintTop_toBottomOf="@+id/tv_warning_title"
tools:text="@string/solana_rent_warning" />
</androidx.constraintlayout.widget.ConstraintLayout>