Updated on 2026-08-14
This commit is contained in:
commit
2c593eae50
31 changed files with 465 additions and 458 deletions
|
|
@ -9,6 +9,7 @@ import com.tangem.domain.common.util.UserWalletId
|
||||||
import com.tangem.tap.common.analytics.converters.TopUpEventConverter
|
import com.tangem.tap.common.analytics.converters.TopUpEventConverter
|
||||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||||
import com.tangem.tap.common.extensions.copy
|
import com.tangem.tap.common.extensions.copy
|
||||||
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
import com.tangem.tap.domain.model.UserWallet
|
import com.tangem.tap.domain.model.UserWallet
|
||||||
import com.tangem.tap.domain.model.WalletDataModel
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.domain.model.WalletStoreModel
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
|
|
@ -17,7 +18,6 @@ import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||||
import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
|
import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
|
||||||
import com.tangem.tap.domain.walletStores.WalletStoresManager
|
import com.tangem.tap.domain.walletStores.WalletStoresManager
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
|
||||||
import com.tangem.tap.persistence.ToppedUpWalletStorage
|
import com.tangem.tap.persistence.ToppedUpWalletStorage
|
||||||
import com.tangem.tap.scope
|
import com.tangem.tap.scope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -60,8 +60,8 @@ class TopUpController(
|
||||||
hadMissedDerivations = blockchains.isNotEmpty()
|
hadMissedDerivations = blockchains.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun totalBalanceStateChanged(state: ProgressState) {
|
fun totalBalanceStateChanged(totalFiatBalance: TotalFiatBalance) {
|
||||||
if (state == ProgressState.Done) tryToSend()
|
if (totalFiatBalance is TotalFiatBalance.Loaded) tryToSend()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadDataSuccess() {
|
fun loadDataSuccess() {
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,8 @@ import com.tangem.tap.common.TestActions
|
||||||
import com.tangem.tap.domain.TapError
|
import com.tangem.tap.domain.TapError
|
||||||
import com.tangem.tap.domain.extensions.amountToCreateAccount
|
import com.tangem.tap.domain.extensions.amountToCreateAccount
|
||||||
import com.tangem.tap.domain.getFirstToken
|
import com.tangem.tap.domain.getFirstToken
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.features.demo.isDemoCard
|
import com.tangem.tap.features.demo.isDemoCard
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
|
||||||
import com.tangem.tap.features.wallet.redux.AddressData
|
|
||||||
import com.tangem.tap.features.wallet.redux.reducers.createAddressesData
|
import com.tangem.tap.features.wallet.redux.reducers.createAddressesData
|
||||||
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
|
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
|
||||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
|
|
@ -81,7 +80,7 @@ fun WalletManager.getTopUpUrl(): String? {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun WalletManager?.getAddressData(): AddressData? {
|
fun WalletManager?.getAddressData(): WalletDataModel.AddressData? {
|
||||||
val wallet = this?.wallet ?: return null
|
val wallet = this?.wallet ?: return null
|
||||||
|
|
||||||
val addressDataList = wallet.createAddressesData()
|
val addressDataList = wallet.createAddressesData()
|
||||||
|
|
@ -100,11 +99,6 @@ fun <T> WalletManager.Companion.stub(): T {
|
||||||
} as T
|
} as T
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Wallet.getTxHistory(currency: Currency): List<TransactionData> {
|
|
||||||
return (currency as? Currency.Token)?.let { this.getTokenTxHistory(it.token) }
|
|
||||||
?: getBlockchainTxHistory()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Wallet.getBlockchainTxHistory(): List<TransactionData> {
|
fun Wallet.getBlockchainTxHistory(): List<TransactionData> {
|
||||||
return historyTransactions.filter {
|
return historyTransactions.filter {
|
||||||
it.contractAddress.isNullOrEmpty()
|
it.contractAddress.isNullOrEmpty()
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ package com.tangem.tap.common.redux
|
||||||
|
|
||||||
import com.tangem.common.extensions.VoidCallback
|
import com.tangem.common.extensions.VoidCallback
|
||||||
import com.tangem.tap.common.TestAction
|
import com.tangem.tap.common.TestAction
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
import com.tangem.tap.features.wallet.redux.AddressData
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
@ -24,7 +24,7 @@ sealed class AppDialog : StateDialog {
|
||||||
|
|
||||||
data class AddressInfoDialog(
|
data class AddressInfoDialog(
|
||||||
val currency: Currency,
|
val currency: Currency,
|
||||||
val addressData: AddressData,
|
val addressData: WalletDataModel.AddressData,
|
||||||
) : AppDialog()
|
) : AppDialog()
|
||||||
|
|
||||||
data class TestActionsDialog(
|
data class TestActionsDialog(
|
||||||
|
|
|
||||||
|
|
@ -184,10 +184,6 @@ private fun getExistentialDeposit(walletManager: WalletManager?): BigDecimal? {
|
||||||
private fun Wallet.getWalletAddresses(): WalletDataModel.WalletAddresses? {
|
private fun Wallet.getWalletAddresses(): WalletDataModel.WalletAddresses? {
|
||||||
return this.createAddressesData()
|
return this.createAddressesData()
|
||||||
.takeIf { it.isNotEmpty() }
|
.takeIf { it.isNotEmpty() }
|
||||||
?.map {
|
|
||||||
// TODO: Will be removed in next MR
|
|
||||||
with(it) { WalletDataModel.AddressData(address, type, shareUrl, exploreUrl) }
|
|
||||||
}
|
|
||||||
?.let { addresses ->
|
?.let { addresses ->
|
||||||
WalletDataModel.WalletAddresses(
|
WalletDataModel.WalletAddresses(
|
||||||
list = addresses,
|
list = addresses,
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,9 @@ import com.tangem.tap.common.extensions.dispatchDialogHide
|
||||||
import com.tangem.tap.common.extensions.dispatchShare
|
import com.tangem.tap.common.extensions.dispatchShare
|
||||||
import com.tangem.tap.common.extensions.dispatchToastNotification
|
import com.tangem.tap.common.extensions.dispatchToastNotification
|
||||||
import com.tangem.tap.common.extensions.getString
|
import com.tangem.tap.common.extensions.getString
|
||||||
|
import com.tangem.tap.common.extensions.toQrCode
|
||||||
import com.tangem.tap.common.redux.AppDialog
|
import com.tangem.tap.common.redux.AppDialog
|
||||||
import com.tangem.tap.features.wallet.redux.AddressData
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import com.tangem.wallet.databinding.DialogOnboardingAddressInfoBinding
|
import com.tangem.wallet.databinding.DialogOnboardingAddressInfoBinding
|
||||||
|
|
@ -46,12 +47,12 @@ class AddressInfoBottomSheetDialog(
|
||||||
showData(data = stateDialog.addressData)
|
showData(data = stateDialog.addressData)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showData(data: AddressData) = with(binding!!) {
|
private fun showData(data: WalletDataModel.AddressData) = with(binding!!) {
|
||||||
pseudoToolbar.imvClose.setOnClickListener {
|
pseudoToolbar.imvClose.setOnClickListener {
|
||||||
dismissWithAnimation = true
|
dismissWithAnimation = true
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
imvQrCode.setImageBitmap(data.qrCode)
|
imvQrCode.setImageBitmap(data.shareUrl.toQrCode())
|
||||||
tvAddress.text = data.address
|
tvAddress.text = data.address
|
||||||
btnFlCopyAddress.setOnClickListener {
|
btnFlCopyAddress.setOnClickListener {
|
||||||
Analytics.send(Token.Receive.ButtonCopyAddress())
|
Analytics.send(Token.Receive.ButtonCopyAddress())
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ import com.tangem.tap.features.send.redux.states.ReceiptSymbols
|
||||||
import com.tangem.tap.features.send.redux.states.ReceiptTokenCrypto
|
import com.tangem.tap.features.send.redux.states.ReceiptTokenCrypto
|
||||||
import com.tangem.tap.features.send.redux.states.ReceiptTokenFiat
|
import com.tangem.tap.features.send.redux.states.ReceiptTokenFiat
|
||||||
import com.tangem.tap.features.send.redux.states.SendState
|
import com.tangem.tap.features.send.redux.states.SendState
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.CAN_BE_LOWER_SIGN
|
import com.tangem.tap.features.wallet.redux.utils.CAN_BE_LOWER_SIGN
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ import com.tangem.tap.features.send.ui.dialogs.RequestFeeErrorDialog
|
||||||
import com.tangem.tap.features.send.ui.dialogs.SendTransactionFailsDialog
|
import com.tangem.tap.features.send.ui.dialogs.SendTransactionFailsDialog
|
||||||
import com.tangem.tap.features.send.ui.dialogs.TezosWarningDialog
|
import com.tangem.tap.features.send.ui.dialogs.TezosWarningDialog
|
||||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.ROUGH_SIGN
|
import com.tangem.tap.features.wallet.redux.utils.ROUGH_SIGN
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||||
import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter
|
import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ package com.tangem.tap.features.tokens.redux
|
||||||
import com.tangem.blockchain.common.Blockchain
|
import com.tangem.blockchain.common.Blockchain
|
||||||
import com.tangem.blockchain.common.DerivationStyle
|
import com.tangem.blockchain.common.DerivationStyle
|
||||||
import com.tangem.domain.common.ScanResponse
|
import com.tangem.domain.common.ScanResponse
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.domain.tokens.Currency
|
import com.tangem.tap.domain.tokens.Currency
|
||||||
import com.tangem.tap.features.wallet.redux.WalletData
|
|
||||||
import org.rekotlin.Action
|
import org.rekotlin.Action
|
||||||
|
|
||||||
sealed class TokensAction : Action {
|
sealed class TokensAction : Action {
|
||||||
|
|
@ -23,7 +23,7 @@ sealed class TokensAction : Action {
|
||||||
) : TokensAction()
|
) : TokensAction()
|
||||||
|
|
||||||
data class SetAddedCurrencies(
|
data class SetAddedCurrencies(
|
||||||
val wallets: List<WalletData>,
|
val wallets: List<WalletDataModel>,
|
||||||
val derivationStyle: DerivationStyle?,
|
val derivationStyle: DerivationStyle?,
|
||||||
) : TokensAction()
|
) : TokensAction()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import com.tangem.blockchain.common.Token
|
||||||
import com.tangem.domain.common.ScanResponse
|
import com.tangem.domain.common.ScanResponse
|
||||||
import com.tangem.domain.common.extensions.canHandleToken
|
import com.tangem.domain.common.extensions.canHandleToken
|
||||||
import com.tangem.domain.common.extensions.fromNetworkId
|
import com.tangem.domain.common.extensions.fromNetworkId
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.domain.tokens.Currency
|
import com.tangem.tap.domain.tokens.Currency
|
||||||
import com.tangem.tap.features.wallet.redux.WalletData
|
|
||||||
import org.rekotlin.StateType
|
import org.rekotlin.StateType
|
||||||
import com.tangem.tap.features.wallet.models.Currency.Token as CurrencyToken
|
import com.tangem.tap.features.wallet.models.Currency.Token as CurrencyToken
|
||||||
|
|
||||||
data class TokensState(
|
data class TokensState(
|
||||||
val addedWallets: List<WalletData> = emptyList(),
|
val addedWallets: List<WalletDataModel> = emptyList(),
|
||||||
val addedTokens: List<TokenWithBlockchain> = emptyList(),
|
val addedTokens: List<TokenWithBlockchain> = emptyList(),
|
||||||
val addedBlockchains: List<Blockchain> = emptyList(),
|
val addedBlockchains: List<Blockchain> = emptyList(),
|
||||||
val currencies: List<Currency> = emptyList(),
|
val currencies: List<Currency> = emptyList(),
|
||||||
|
|
@ -31,17 +31,9 @@ data class TokensState(
|
||||||
|
|
||||||
typealias ContractAddress = String
|
typealias ContractAddress = String
|
||||||
|
|
||||||
fun List<WalletData>.toTokensContractAddresses(): List<ContractAddress> {
|
fun List<WalletDataModel>.toNonCustomTokensWithBlockchains(
|
||||||
return mapNotNull { (it.currency as? CurrencyToken)?.token?.contractAddress }.distinct()
|
derivationStyle: DerivationStyle?,
|
||||||
}
|
): List<TokenWithBlockchain> {
|
||||||
|
|
||||||
fun List<WalletData>.toNonCustomTokens(derivationStyle: DerivationStyle?): List<Token> {
|
|
||||||
return filter { !it.currency.isCustomCurrency(derivationStyle) }
|
|
||||||
.mapNotNull { (it.currency as? CurrencyToken)?.token }
|
|
||||||
.distinct()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun List<WalletData>.toNonCustomTokensWithBlockchains(derivationStyle: DerivationStyle?): List<TokenWithBlockchain> {
|
|
||||||
return mapNotNull {
|
return mapNotNull {
|
||||||
if (it.currency !is CurrencyToken) return@mapNotNull null
|
if (it.currency !is CurrencyToken) return@mapNotNull null
|
||||||
if (it.currency.isCustomCurrency(derivationStyle)) return@mapNotNull null
|
if (it.currency.isCustomCurrency(derivationStyle)) return@mapNotNull null
|
||||||
|
|
@ -49,7 +41,7 @@ fun List<WalletData>.toNonCustomTokensWithBlockchains(derivationStyle: Derivatio
|
||||||
}.distinct()
|
}.distinct()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List<WalletData>.toNonCustomBlockchains(derivationStyle: DerivationStyle?): List<Blockchain> {
|
fun List<WalletDataModel>.toNonCustomBlockchains(derivationStyle: DerivationStyle?): List<Blockchain> {
|
||||||
return mapNotNull {
|
return mapNotNull {
|
||||||
if (it.currency.isCustomCurrency(derivationStyle)) {
|
if (it.currency.isCustomCurrency(derivationStyle)) {
|
||||||
null
|
null
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package com.tangem.tap.features.wallet.models
|
package com.tangem.tap.features.wallet.models
|
||||||
|
|
||||||
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
|
|
||||||
sealed class WalletWarning(val showingPosition: Int) {
|
sealed class WalletWarning(val showingPosition: Int) {
|
||||||
|
|
||||||
data class ExistentialDeposit(
|
data class ExistentialDeposit(
|
||||||
|
|
@ -15,7 +17,7 @@ sealed class WalletWarning(val showingPosition: Int) {
|
||||||
val blockchainSymbol: String,
|
val blockchainSymbol: String,
|
||||||
) : WalletWarning(showingPosition = 30)
|
) : WalletWarning(showingPosition = 30)
|
||||||
|
|
||||||
data class Rent(val walletRent: WalletRent) : WalletWarning(showingPosition = 40)
|
data class Rent(val walletRent: WalletStoreModel.WalletRent) : WalletWarning(showingPosition = 40)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class WalletWarningDescription(val title: String, val message: String)
|
data class WalletWarningDescription(val title: String, val message: String)
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,12 @@ import com.tangem.tap.common.entities.FiatCurrency
|
||||||
import com.tangem.tap.common.redux.NotificationAction
|
import com.tangem.tap.common.redux.NotificationAction
|
||||||
import com.tangem.tap.domain.TapError
|
import com.tangem.tap.domain.TapError
|
||||||
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
|
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
|
||||||
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
import com.tangem.tap.domain.model.UserWallet
|
import com.tangem.tap.domain.model.UserWallet
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.domain.model.WalletStoreModel
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
|
||||||
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import org.rekotlin.Action
|
import org.rekotlin.Action
|
||||||
|
|
@ -38,7 +39,6 @@ sealed class WalletAction : Action {
|
||||||
data class RemoveWallet(val currency: Currency) : MultiWallet()
|
data class RemoveWallet(val currency: Currency) : MultiWallet()
|
||||||
|
|
||||||
object BackupWallet : MultiWallet()
|
object BackupWallet : MultiWallet()
|
||||||
object ScheduleCheckForMissingDerivation : MultiWallet()
|
|
||||||
data class AddMissingDerivations(val blockchains: List<BlockchainNetwork>) : MultiWallet()
|
data class AddMissingDerivations(val blockchains: List<BlockchainNetwork>) : MultiWallet()
|
||||||
object ScanToGetDerivations : MultiWallet()
|
object ScanToGetDerivations : MultiWallet()
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +78,7 @@ sealed class WalletAction : Action {
|
||||||
sealed class DialogAction : WalletAction() {
|
sealed class DialogAction : WalletAction() {
|
||||||
data class QrCode(
|
data class QrCode(
|
||||||
val currency: Currency,
|
val currency: Currency,
|
||||||
val selectedAddress: AddressData,
|
val selectedAddress: WalletDataModel.AddressData,
|
||||||
) : DialogAction()
|
) : DialogAction()
|
||||||
|
|
||||||
object SignedHashesMultiWalletDialog : DialogAction()
|
object SignedHashesMultiWalletDialog : DialogAction()
|
||||||
|
|
@ -127,9 +127,7 @@ sealed class WalletAction : Action {
|
||||||
}
|
}
|
||||||
|
|
||||||
data class UserWalletChanged(val userWallet: UserWallet) : WalletAction()
|
data class UserWalletChanged(val userWallet: UserWallet) : WalletAction()
|
||||||
data class WalletStoresChanged(val walletStores: List<WalletStoreModel>) : WalletAction() {
|
data class WalletStoresChanged(val walletStores: List<WalletStoreModel>) : WalletAction()
|
||||||
data class UpdateWalletStores(val reduxWalletStores: List<WalletStore>) : WalletAction()
|
|
||||||
}
|
|
||||||
|
|
||||||
data class TotalFiatBalanceChanged(val balance: TotalBalance) : WalletAction()
|
data class TotalFiatBalanceChanged(val balance: TotalFiatBalance) : WalletAction()
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +85,8 @@ data class WalletData(
|
||||||
walletWarnings.add(WalletWarning.TransactionInProgress(currency.currencyName))
|
walletWarnings.add(WalletWarning.TransactionInProgress(currency.currencyName))
|
||||||
}
|
}
|
||||||
if (walletRent != null) {
|
if (walletRent != null) {
|
||||||
walletWarnings.add(WalletWarning.Rent(walletRent))
|
// TODO: Will be removed in next MR
|
||||||
|
// walletWarnings.add(WalletWarning.Rent(walletRent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,29 +9,30 @@ import com.tangem.tap.common.extensions.toQrCode
|
||||||
import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
||||||
import com.tangem.tap.common.toggleWidget.WidgetState
|
import com.tangem.tap.common.toggleWidget.WidgetState
|
||||||
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
|
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
|
||||||
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
|
import com.tangem.tap.domain.model.UserWallet
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
|
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
|
||||||
import com.tangem.tap.features.wallet.redux.reducers.findProgressState
|
|
||||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import org.rekotlin.StateType
|
import org.rekotlin.StateType
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
|
|
||||||
data class WalletState(
|
data class WalletState(
|
||||||
val cardId: String = "",
|
val userWallet: UserWallet? = null,
|
||||||
val state: ProgressState = ProgressState.Done,
|
val state: ProgressState = ProgressState.Done,
|
||||||
val error: ErrorType? = null,
|
val error: ErrorType? = null,
|
||||||
val cardImage: Artwork? = null,
|
val cardImage: Artwork? = null,
|
||||||
val hashesCountVerified: Boolean? = null,
|
val hashesCountVerified: Boolean? = null,
|
||||||
val mainWarningsList: List<WarningMessage> = mutableListOf(),
|
val mainWarningsList: List<WarningMessage> = mutableListOf(),
|
||||||
val walletsStores: List<WalletStore> = listOf(),
|
val walletsStores: List<WalletStoreModel> = listOf(),
|
||||||
val isMultiwalletAllowed: Boolean = false,
|
val isMultiwalletAllowed: Boolean = false,
|
||||||
val cardCurrency: CryptoCurrencyName? = null,
|
val cardCurrency: CryptoCurrencyName? = null,
|
||||||
val selectedCurrency: Currency? = null,
|
val selectedCurrency: Currency? = null,
|
||||||
val isTestnet: Boolean = false,
|
val isTestnet: Boolean = false,
|
||||||
val totalBalance: TotalBalance? = null,
|
val totalBalance: TotalFiatBalance? = null,
|
||||||
val showBackupWarning: Boolean = false,
|
val showBackupWarning: Boolean = false,
|
||||||
val missingDerivations: List<BlockchainNetwork> = emptyList(),
|
val missingDerivations: List<BlockchainNetwork> = emptyList(),
|
||||||
val loadingUserTokens: Boolean = false,
|
val loadingUserTokens: Boolean = false,
|
||||||
|
|
@ -39,10 +40,10 @@ data class WalletState(
|
||||||
val canSaveUserWallets: Boolean = false,
|
val canSaveUserWallets: Boolean = false,
|
||||||
) : StateType {
|
) : StateType {
|
||||||
|
|
||||||
val walletsDataFromStores: List<WalletData>
|
val walletsDataFromStores: List<WalletDataModel>
|
||||||
get() = walletsStores.map { it.walletsData }.flatten()
|
get() = walletsStores.flatMap { it.walletsData }
|
||||||
|
|
||||||
val selectedWalletData: WalletData?
|
val selectedWalletData: WalletDataModel?
|
||||||
get() = walletsDataFromStores.firstOrNull { it.currency == selectedCurrency }
|
get() = walletsDataFromStores.firstOrNull { it.currency == selectedCurrency }
|
||||||
|
|
||||||
// if you do not delegate - the application crashes on startup,
|
// if you do not delegate - the application crashes on startup,
|
||||||
|
|
@ -66,7 +67,7 @@ data class WalletState(
|
||||||
val walletManagers: List<WalletManager>
|
val walletManagers: List<WalletManager>
|
||||||
get() = walletsStores.mapNotNull { it.walletManager }
|
get() = walletsStores.mapNotNull { it.walletManager }
|
||||||
|
|
||||||
private val primaryWalletStore: WalletStore?
|
private val primaryWalletStore: WalletStoreModel?
|
||||||
get() = if (isMultiwalletAllowed || walletsStores.isEmpty() || walletsStores.size > 1) {
|
get() = if (isMultiwalletAllowed || walletsStores.isEmpty() || walletsStores.size > 1) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -76,17 +77,15 @@ data class WalletState(
|
||||||
val primaryWalletManager: WalletManager?
|
val primaryWalletManager: WalletManager?
|
||||||
get() = primaryWalletStore?.walletManager
|
get() = primaryWalletStore?.walletManager
|
||||||
|
|
||||||
val primaryWalletData: WalletData?
|
val primaryWalletData: WalletDataModel?
|
||||||
get() = primaryWalletStore?.walletsData?.firstOrNull()
|
get() = primaryWalletStore?.blockchainWalletData
|
||||||
|
|
||||||
val primaryTokenData: WalletData?
|
val primaryTokenData: WalletDataModel?
|
||||||
get() = primaryWalletStore?.walletsData?.toMutableList()
|
get() = primaryWalletStore?.walletsData
|
||||||
?.apply { remove(primaryWalletData) }
|
?.firstOrNull { it.currency !is Currency.Blockchain }
|
||||||
?.firstOrNull()
|
|
||||||
|
|
||||||
val shouldShowDetails: Boolean =
|
val shouldShowDetails: Boolean =
|
||||||
primaryWalletData?.currencyData?.status != BalanceStatus.EmptyCard &&
|
primaryWalletData?.status !is WalletDataModel.Unreachable
|
||||||
primaryWalletData?.currencyData?.status != BalanceStatus.UnknownBlockchain
|
|
||||||
|
|
||||||
fun getWalletManager(currency: Currency?): WalletManager? {
|
fun getWalletManager(currency: Currency?): WalletManager? {
|
||||||
if (currency?.blockchain == null) return null
|
if (currency?.blockchain == null) return null
|
||||||
|
|
@ -94,95 +93,27 @@ data class WalletState(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getWalletManager(blockchain: BlockchainNetwork): WalletManager? {
|
fun getWalletManager(blockchain: BlockchainNetwork): WalletManager? {
|
||||||
return walletsStores.find { it.blockchainNetwork == blockchain }?.walletManager
|
return walletsStores.firstOrNull {
|
||||||
|
it.blockchain == blockchain.blockchain &&
|
||||||
|
it.derivationPath?.rawPath == blockchain.derivationPath
|
||||||
|
}?.walletManager
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getWalletData(blockchain: BlockchainNetwork?): WalletData? {
|
fun getWalletStore(currency: Currency?): WalletStoreModel? {
|
||||||
if (blockchain == null) return null
|
|
||||||
return walletsDataFromStores.find {
|
|
||||||
it.currency is Currency.Blockchain &&
|
|
||||||
it.currency.blockchain == blockchain.blockchain &&
|
|
||||||
it.currency.derivationPath == blockchain.derivationPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWalletStore(currency: Currency?): WalletStore? {
|
|
||||||
if (currency == null) return null
|
if (currency == null) return null
|
||||||
return walletsStores.firstOrNull {
|
return walletsStores.firstOrNull {
|
||||||
it.blockchainNetwork.derivationPath == currency.derivationPath &&
|
it.blockchain == currency.blockchain &&
|
||||||
it.blockchainNetwork.blockchain == currency.blockchain
|
it.derivationPath?.rawPath == currency.derivationPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getWalletStore(blockchainNetwork: BlockchainNetwork?): WalletStore? {
|
|
||||||
if (blockchainNetwork == null) return null
|
|
||||||
return walletsStores.firstOrNull {
|
|
||||||
it.blockchainNetwork.derivationPath == blockchainNetwork.derivationPath &&
|
|
||||||
it.blockchainNetwork.blockchain == blockchainNetwork.blockchain
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWalletData(currency: Currency?): WalletData? {
|
|
||||||
if (currency == null) return null
|
|
||||||
return getWalletStore(currency)?.walletsData?.firstOrNull { it.currency == currency }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateWalletData(walletData: WalletData?): WalletState {
|
|
||||||
if (walletData == null) return this
|
|
||||||
return updateWalletsData(listOf(walletData))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateWalletsData(walletsData: List<WalletData>): WalletState {
|
|
||||||
val walletStores = walletsData
|
|
||||||
.map { BlockchainNetwork(it.currency.blockchain, it.currency.derivationPath, emptyList()) }
|
|
||||||
.distinct().map { getWalletStore(it) }.mapNotNull { it?.updateWallets(walletsData) }
|
|
||||||
|
|
||||||
return updateWalletsStores(walletStores)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateWalletsStores(walletStores: List<WalletStore>): WalletState {
|
|
||||||
val walletStoresMutable = walletStores.toMutableList()
|
|
||||||
val updatedWallets = walletsStores.map { oldWalletStore ->
|
|
||||||
val walletStore = walletStoresMutable.find {
|
|
||||||
it.blockchainNetwork == oldWalletStore.blockchainNetwork
|
|
||||||
}
|
|
||||||
if (walletStore != null) {
|
|
||||||
walletStoresMutable.remove(walletStore)
|
|
||||||
walletStore
|
|
||||||
} else {
|
|
||||||
oldWalletStore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return copy(walletsStores = updatedWallets + walletStoresMutable)
|
|
||||||
.updateProgressState()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateProgressState(): WalletState {
|
|
||||||
val walletsData = this.walletsStores
|
|
||||||
.flatMap(WalletStore::walletsData)
|
|
||||||
|
|
||||||
return if (walletsData.isNotEmpty()) {
|
|
||||||
val newProgressState = walletsData.findProgressState()
|
|
||||||
|
|
||||||
this.copy(
|
|
||||||
state = walletsData.findProgressState(),
|
|
||||||
error = this.error.takeIf { newProgressState == ProgressState.Error },
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val UNKNOWN_AMOUNT_SIGN = "—"
|
|
||||||
const val ROUGH_SIGN = "≈"
|
|
||||||
const val CAN_BE_LOWER_SIGN = "<"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ProgressState : WidgetState { Loading, Refreshing, Done, Error }
|
enum class ProgressState : WidgetState { Loading, Refreshing, Done, Error }
|
||||||
|
|
||||||
enum class ErrorType { NoInternetConnection }
|
enum class ErrorType {
|
||||||
|
NoInternetConnection,
|
||||||
|
UnknownBlockchain,
|
||||||
|
}
|
||||||
|
|
||||||
sealed class WalletMainButton(enabled: Boolean) : Button(enabled) {
|
sealed class WalletMainButton(enabled: Boolean) : Button(enabled) {
|
||||||
class SendButton(enabled: Boolean) : WalletMainButton(enabled)
|
class SendButton(enabled: Boolean) : WalletMainButton(enabled)
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ private fun WalletDataModel.mapToReduxModel(
|
||||||
|
|
||||||
return WalletData(
|
return WalletData(
|
||||||
currency = currency,
|
currency = currency,
|
||||||
// TODO: Will be updated in next MR
|
// TODO: Will be updated in next MRs
|
||||||
walletAddresses = walletAddresses?.let { addresses ->
|
walletAddresses = walletAddresses?.let { addresses ->
|
||||||
WalletAddresses(
|
WalletAddresses(
|
||||||
selectedAddress = with(addresses.selectedAddress) {
|
selectedAddress = with(addresses.selectedAddress) {
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,7 @@ import com.tangem.tap.features.send.redux.PrepareSendScreen
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
import com.tangem.tap.features.wallet.models.getSendableAmounts
|
import com.tangem.tap.features.wallet.models.getSendableAmounts
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.features.wallet.redux.WalletData
|
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState
|
import com.tangem.tap.features.wallet.redux.WalletState
|
||||||
import com.tangem.tap.features.wallet.redux.WalletStore
|
|
||||||
import com.tangem.tap.features.wallet.redux.reducers.findSelectedCurrency
|
|
||||||
import com.tangem.tap.preferencesStorage
|
import com.tangem.tap.preferencesStorage
|
||||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import com.tangem.tap.scope
|
import com.tangem.tap.scope
|
||||||
|
|
@ -106,7 +103,7 @@ class WalletMiddleware {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
when (val result = tangemSdkManager.createWallet(globalState.scanResponse?.card?.cardId)) {
|
when (val result = tangemSdkManager.createWallet(globalState.scanResponse?.card?.cardId)) {
|
||||||
is CompletionResult.Success -> {
|
is CompletionResult.Success -> {
|
||||||
val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard {
|
val selectedUserWallet = walletState.userWallet.guard {
|
||||||
Timber.e("Unable to create wallet, no user wallet selected")
|
Timber.e("Unable to create wallet, no user wallet selected")
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +129,7 @@ class WalletMiddleware {
|
||||||
is WalletAction.LoadData,
|
is WalletAction.LoadData,
|
||||||
is WalletAction.LoadData.Refresh,
|
is WalletAction.LoadData.Refresh,
|
||||||
-> {
|
-> {
|
||||||
val selectedWallet = userWalletsListManager.selectedUserWalletSync.guard {
|
val selectedWallet = walletState.userWallet.guard {
|
||||||
Timber.e("Unable to load/refresh wallets data, no user wallet selected")
|
Timber.e("Unable to load/refresh wallets data, no user wallet selected")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -188,7 +185,6 @@ class WalletMiddleware {
|
||||||
is WalletAction.WalletStoresChanged -> {
|
is WalletAction.WalletStoresChanged -> {
|
||||||
// Cancel update job when new wallet stores received
|
// Cancel update job when new wallet stores received
|
||||||
updateWalletStoresJob = scope.launch(Dispatchers.Default) {
|
updateWalletStoresJob = scope.launch(Dispatchers.Default) {
|
||||||
ifActive { updateWalletStores(action.walletStores, walletState) }
|
|
||||||
ifActive { fetchTotalFiatBalance(action.walletStores) }
|
ifActive { fetchTotalFiatBalance(action.walletStores) }
|
||||||
ifActive { findMissedDerivations(action.walletStores) }
|
ifActive { findMissedDerivations(action.walletStores) }
|
||||||
ifActive { tryToShowAppRatingWarning(action.walletStores) }
|
ifActive { tryToShowAppRatingWarning(action.walletStores) }
|
||||||
|
|
@ -227,26 +223,8 @@ class WalletMiddleware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateWalletStores(walletsStores: List<WalletStoreModel>, state: WalletState) {
|
|
||||||
val reduxWalletStores = walletsStores.mapToReduxModels()
|
|
||||||
if (!state.isMultiwalletAllowed) {
|
|
||||||
findSelectedCurrency(
|
|
||||||
walletsStores = reduxWalletStores,
|
|
||||||
currentSelectedCurrency = null,
|
|
||||||
isMultiWalletAllowed = false,
|
|
||||||
)?.let {
|
|
||||||
store.dispatchOnMain(WalletAction.MultiWallet.SetSingleWalletCurrency(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
store.dispatchOnMain(
|
|
||||||
WalletAction.WalletStoresChanged.UpdateWalletStores(
|
|
||||||
reduxWalletStores = reduxWalletStores,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun fetchTotalFiatBalance(walletStores: List<WalletStoreModel>) {
|
private suspend fun fetchTotalFiatBalance(walletStores: List<WalletStoreModel>) {
|
||||||
val totalFiatBalance = totalFiatBalanceCalculator.calculateOrNull(walletStores)?.mapToReduxModel()
|
val totalFiatBalance = totalFiatBalanceCalculator.calculateOrNull(walletStores)
|
||||||
|
|
||||||
if (totalFiatBalance != null) {
|
if (totalFiatBalance != null) {
|
||||||
store.dispatchOnMain(WalletAction.TotalFiatBalanceChanged(totalFiatBalance))
|
store.dispatchOnMain(WalletAction.TotalFiatBalanceChanged(totalFiatBalance))
|
||||||
|
|
@ -300,7 +278,7 @@ class WalletMiddleware {
|
||||||
|
|
||||||
return if (amount != null) {
|
return if (amount != null) {
|
||||||
if (amount.type is AmountType.Token) {
|
if (amount.type is AmountType.Token) {
|
||||||
prepareSendActionForToken(amount, state, selectedWalletData, walletStore)
|
prepareSendActionForToken(amount, selectedWalletData, walletStore)
|
||||||
} else {
|
} else {
|
||||||
PrepareSendScreen(amount, selectedWalletData?.fiatRate, walletStore?.walletManager)
|
PrepareSendScreen(amount, selectedWalletData?.fiatRate, walletStore?.walletManager)
|
||||||
}
|
}
|
||||||
|
|
@ -322,7 +300,6 @@ class WalletMiddleware {
|
||||||
?: return WalletAction.DialogAction.ChooseCurrency(amounts)
|
?: return WalletAction.DialogAction.ChooseCurrency(amounts)
|
||||||
prepareSendActionForToken(
|
prepareSendActionForToken(
|
||||||
amount = amountToSend,
|
amount = amountToSend,
|
||||||
state = state,
|
|
||||||
selectedWalletData = selectedWalletData,
|
selectedWalletData = selectedWalletData,
|
||||||
walletStore = walletStore,
|
walletStore = walletStore,
|
||||||
)
|
)
|
||||||
|
|
@ -346,11 +323,10 @@ class WalletMiddleware {
|
||||||
|
|
||||||
private fun prepareSendActionForToken(
|
private fun prepareSendActionForToken(
|
||||||
amount: Amount,
|
amount: Amount,
|
||||||
state: WalletState?,
|
selectedWalletData: WalletDataModel?,
|
||||||
selectedWalletData: WalletData?,
|
walletStore: WalletStoreModel?,
|
||||||
walletStore: WalletStore?,
|
|
||||||
): PrepareSendScreen {
|
): PrepareSendScreen {
|
||||||
val coinRate = state?.getWalletData(walletStore?.blockchainNetwork)?.fiatRate
|
val coinRate = walletStore?.blockchainWalletData?.fiatRate
|
||||||
val tokenRate = selectedWalletData?.fiatRate
|
val tokenRate = selectedWalletData?.fiatRate
|
||||||
val coinAmount = walletStore?.walletManager?.wallet?.amounts?.get(AmountType.Coin)
|
val coinAmount = walletStore?.walletManager?.wallet?.amounts?.get(AmountType.Coin)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,18 @@
|
||||||
package com.tangem.tap.features.wallet.redux.reducers
|
package com.tangem.tap.features.wallet.redux.reducers
|
||||||
|
|
||||||
import com.tangem.blockchain.common.Blockchain
|
|
||||||
import com.tangem.blockchain.common.Wallet
|
import com.tangem.blockchain.common.Wallet
|
||||||
import com.tangem.domain.common.CardDTO
|
import com.tangem.domain.common.CardDTO
|
||||||
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import com.tangem.tap.domain.TapError
|
import com.tangem.tap.domain.TapError
|
||||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
import com.tangem.tap.features.wallet.redux.AddressData
|
|
||||||
import com.tangem.tap.features.wallet.redux.Artwork
|
import com.tangem.tap.features.wallet.redux.Artwork
|
||||||
import com.tangem.tap.features.wallet.redux.ErrorType
|
import com.tangem.tap.features.wallet.redux.ErrorType
|
||||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.features.wallet.redux.WalletData
|
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState
|
import com.tangem.tap.features.wallet.redux.WalletState
|
||||||
import com.tangem.tap.features.wallet.redux.WalletStore
|
|
||||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
|
||||||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
|
||||||
import com.tangem.tap.proxy.AppStateHolder
|
import com.tangem.tap.proxy.AppStateHolder
|
||||||
import org.rekotlin.Action
|
import org.rekotlin.Action
|
||||||
|
|
||||||
|
|
@ -41,44 +36,15 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS
|
||||||
is WalletAction.LoadData.Failure -> {
|
is WalletAction.LoadData.Failure -> {
|
||||||
when (action.error) {
|
when (action.error) {
|
||||||
is TapError.NoInternetConnection -> {
|
is TapError.NoInternetConnection -> {
|
||||||
val wallets = newState.walletsStores
|
|
||||||
.map { store ->
|
|
||||||
store.copy(
|
|
||||||
walletsData = store.walletsData.map {
|
|
||||||
it.copy(
|
|
||||||
currencyData = it.currencyData.copy(
|
|
||||||
status = BalanceStatus.Unreachable,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
newState = newState.copy(
|
newState = newState.copy(
|
||||||
state = ProgressState.Error,
|
state = ProgressState.Error,
|
||||||
error = ErrorType.NoInternetConnection,
|
error = ErrorType.NoInternetConnection,
|
||||||
walletsStores = wallets,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is TapError.UnknownBlockchain -> {
|
is TapError.UnknownBlockchain -> {
|
||||||
newState = newState.copy(
|
newState = newState.copy(
|
||||||
state = ProgressState.Done,
|
state = ProgressState.Error,
|
||||||
walletsStores = listOf(
|
error = ErrorType.UnknownBlockchain,
|
||||||
WalletStore(
|
|
||||||
walletManager = null,
|
|
||||||
blockchainNetwork = BlockchainNetwork(
|
|
||||||
Blockchain.Unknown,
|
|
||||||
null,
|
|
||||||
emptyList(),
|
|
||||||
),
|
|
||||||
walletsData = listOf(
|
|
||||||
WalletData(
|
|
||||||
currencyData = BalanceWidgetData(BalanceStatus.UnknownBlockchain),
|
|
||||||
currency = Currency.Blockchain(Blockchain.Unknown, null),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
@ -107,7 +73,7 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS
|
||||||
is WalletAction.UserWalletChanged -> with(action.userWallet) {
|
is WalletAction.UserWalletChanged -> with(action.userWallet) {
|
||||||
val card = scanResponse.card
|
val card = scanResponse.card
|
||||||
newState = WalletState(
|
newState = WalletState(
|
||||||
cardId = card.cardId,
|
userWallet = this,
|
||||||
isMultiwalletAllowed = isMultiCurrency,
|
isMultiwalletAllowed = isMultiCurrency,
|
||||||
cardImage = Artwork(
|
cardImage = Artwork(
|
||||||
artworkId = artworkUrl,
|
artworkId = artworkUrl,
|
||||||
|
|
@ -126,10 +92,9 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is WalletAction.WalletStoresChanged.UpdateWalletStores -> {
|
is WalletAction.WalletStoresChanged -> {
|
||||||
newState = newState.copy(
|
newState = newState.copy(
|
||||||
state = action.reduxWalletStores.flatMap { it.walletsData }.findProgressState(newState.state),
|
walletsStores = action.walletStores,
|
||||||
walletsStores = action.reduxWalletStores,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is WalletAction.TotalFiatBalanceChanged -> {
|
is WalletAction.TotalFiatBalanceChanged -> {
|
||||||
|
|
@ -159,7 +124,7 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findSelectedCurrency(
|
fun findSelectedCurrency(
|
||||||
walletsStores: List<WalletStore>,
|
walletsStores: List<WalletStoreModel>,
|
||||||
currentSelectedCurrency: Currency?,
|
currentSelectedCurrency: Currency?,
|
||||||
isMultiWalletAllowed: Boolean,
|
isMultiWalletAllowed: Boolean,
|
||||||
): Currency? = if (isMultiWalletAllowed) {
|
): Currency? = if (isMultiWalletAllowed) {
|
||||||
|
|
@ -175,11 +140,11 @@ private fun CardDTO.findCardsCount(): Int? {
|
||||||
return (this.backupStatus as? CardDTO.BackupStatus.Active)?.cardCount?.inc()
|
return (this.backupStatus as? CardDTO.BackupStatus.Active)?.cardCount?.inc()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Wallet.createAddressesData(): List<AddressData> {
|
fun Wallet.createAddressesData(): List<WalletDataModel.AddressData> {
|
||||||
val listOfAddressData = mutableListOf<AddressData>()
|
val listOfAddressData = mutableListOf<WalletDataModel.AddressData>()
|
||||||
// put a defaultAddress at the first place
|
// put a defaultAddress at the first place
|
||||||
addresses.forEach {
|
addresses.forEach {
|
||||||
val addressData = AddressData(
|
val addressData = WalletDataModel.AddressData(
|
||||||
it.value,
|
it.value,
|
||||||
it.type,
|
it.type,
|
||||||
getShareUri(it.value),
|
getShareUri(it.value),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.tangem.tap.features.wallet.redux.utils
|
||||||
|
|
||||||
|
const val UNKNOWN_AMOUNT_SIGN = "—"
|
||||||
|
const val ROUGH_SIGN = "≈"
|
||||||
|
const val CAN_BE_LOWER_SIGN = "<"
|
||||||
|
|
@ -3,6 +3,10 @@ package com.tangem.tap.features.wallet.ui
|
||||||
import androidx.annotation.IdRes
|
import androidx.annotation.IdRes
|
||||||
import com.tangem.tap.common.extensions.hide
|
import com.tangem.tap.common.extensions.hide
|
||||||
import com.tangem.tap.common.extensions.show
|
import com.tangem.tap.common.extensions.show
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||||
|
import com.tangem.tap.store
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import com.tangem.wallet.databinding.CardBalanceBinding
|
import com.tangem.wallet.databinding.CardBalanceBinding
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
@ -36,36 +40,37 @@ data class BalanceWidgetData(
|
||||||
class BalanceWidget(
|
class BalanceWidget(
|
||||||
private val binding: CardBalanceBinding,
|
private val binding: CardBalanceBinding,
|
||||||
private val fragment: WalletFragment,
|
private val fragment: WalletFragment,
|
||||||
private val data: BalanceWidgetData,
|
private val blockchainWalletData: WalletDataModel,
|
||||||
private val token: BalanceWidgetData?,
|
private val tokenWalletData: WalletDataModel?,
|
||||||
private val isTwinCard: Boolean,
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@Suppress("LongMethod", "ComplexMethod")
|
@Suppress("LongMethod", "ComplexMethod")
|
||||||
fun setup() {
|
fun setup() {
|
||||||
when (data.status) {
|
when (blockchainWalletData.status) {
|
||||||
BalanceStatus.Loading -> {
|
is WalletDataModel.Loading -> {
|
||||||
with(binding) {
|
with(binding) {
|
||||||
lBalance.root.show()
|
lBalance.root.show()
|
||||||
lBalanceError.root.hide()
|
lBalanceError.root.hide()
|
||||||
lBalance.tvFiatAmount.hide()
|
lBalance.tvFiatAmount.hide()
|
||||||
|
|
||||||
lBalance.tvCurrency.text = data.currency
|
lBalance.tvCurrency.text = blockchainWalletData.currency.currencyName
|
||||||
lBalance.tvAmount.text = ""
|
lBalance.tvAmount.text = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
showStatus(R.id.tv_status_loading)
|
showStatus(R.id.tv_status_loading)
|
||||||
|
|
||||||
if (token != null) {
|
if (tokenWalletData != null) {
|
||||||
showBalanceWithToken(data, false)
|
showBalanceWithToken(blockchainWalletData, false)
|
||||||
} else {
|
} else {
|
||||||
showBalanceWithoutToken(data, false)
|
showBalanceWithoutToken(blockchainWalletData, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BalanceStatus.VerifiedOnline, BalanceStatus.TransactionInProgress -> with(binding.lBalance) {
|
is WalletDataModel.VerifiedOnline,
|
||||||
|
is WalletDataModel.TransactionInProgress,
|
||||||
|
-> with(binding.lBalance) {
|
||||||
root.show()
|
root.show()
|
||||||
binding.lBalanceError.root.hide()
|
binding.lBalanceError.root.hide()
|
||||||
val statusView = if (data.status == BalanceStatus.VerifiedOnline) {
|
val statusView = if (blockchainWalletData.status is WalletDataModel.VerifiedOnline) {
|
||||||
R.id.tv_status_verified
|
R.id.tv_status_verified
|
||||||
} else {
|
} else {
|
||||||
tvStatusError.text =
|
tvStatusError.text =
|
||||||
|
|
@ -75,61 +80,62 @@ class BalanceWidget(
|
||||||
showStatus(statusView)
|
showStatus(statusView)
|
||||||
tvStatusErrorMessage.hide()
|
tvStatusErrorMessage.hide()
|
||||||
|
|
||||||
if (token != null) {
|
if (tokenWalletData != null) {
|
||||||
showBalanceWithToken(data, true)
|
showBalanceWithToken(blockchainWalletData, true)
|
||||||
} else {
|
} else {
|
||||||
showBalanceWithoutToken(data, true)
|
showBalanceWithoutToken(blockchainWalletData, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BalanceStatus.Unreachable -> with(binding.lBalance) {
|
is WalletDataModel.Unreachable -> with(binding.lBalance) {
|
||||||
root.show()
|
root.show()
|
||||||
binding.lBalanceError.root.hide()
|
binding.lBalanceError.root.hide()
|
||||||
tvFiatAmount.hide()
|
tvFiatAmount.hide()
|
||||||
groupBaseCurrency.hide()
|
groupBaseCurrency.hide()
|
||||||
|
|
||||||
val currency = if (token != null) token.currencySymbol else data.currency
|
val currency = tokenWalletData?.currency?.currencySymbol
|
||||||
|
?: blockchainWalletData.currency.currencyName
|
||||||
tvCurrency.text = currency
|
tvCurrency.text = currency
|
||||||
tvAmount.text = ""
|
tvAmount.text = ""
|
||||||
|
|
||||||
tvStatusErrorMessage.text = data.errorMessage
|
tvStatusErrorMessage.text = blockchainWalletData.status.errorMessage
|
||||||
tvStatusError.text =
|
tvStatusError.text =
|
||||||
fragment.getString(R.string.wallet_balance_blockchain_unreachable)
|
fragment.getString(R.string.wallet_balance_blockchain_unreachable)
|
||||||
|
|
||||||
showStatus(R.id.group_error)
|
showStatus(R.id.group_error)
|
||||||
tvStatusErrorMessage.show(!data.errorMessage.isNullOrBlank())
|
tvStatusErrorMessage.show(!blockchainWalletData.status.errorMessage.isNullOrBlank())
|
||||||
}
|
}
|
||||||
BalanceStatus.EmptyCard -> with(binding.lBalanceError) {
|
// BalanceStatus.EmptyCard -> with(binding.lBalanceError) {
|
||||||
binding.lBalance.root.hide()
|
// binding.lBalance.root.hide()
|
||||||
binding.lBalanceError.root.show()
|
// binding.lBalanceError.root.show()
|
||||||
if (isTwinCard) {
|
// if (isTwinCard) {
|
||||||
tvErrorTitle.text = fragment.getText(R.string.wallet_error_empty_twin_card)
|
// tvErrorTitle.text = fragment.getText(R.string.wallet_error_empty_twin_card)
|
||||||
tvErrorDescriptions.text =
|
// tvErrorDescriptions.text =
|
||||||
fragment.getText(R.string.wallet_error_empty_twin_card_subtitle)
|
// fragment.getText(R.string.wallet_error_empty_twin_card_subtitle)
|
||||||
} else {
|
// } else {
|
||||||
tvErrorTitle.text = fragment.getText(R.string.wallet_error_empty_card)
|
// tvErrorTitle.text = fragment.getText(R.string.wallet_error_empty_card)
|
||||||
tvErrorDescriptions.text =
|
// tvErrorDescriptions.text =
|
||||||
fragment.getText(R.string.wallet_error_empty_card_subtitle)
|
// fragment.getText(R.string.wallet_error_empty_card_subtitle)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
BalanceStatus.NoAccount -> with(binding.lBalanceError) {
|
is WalletDataModel.NoAccount -> with(binding.lBalanceError) {
|
||||||
binding.lBalance.root.hide()
|
binding.lBalance.root.hide()
|
||||||
binding.lBalanceError.root.show()
|
binding.lBalanceError.root.show()
|
||||||
tvErrorTitle.text = fragment.getText(R.string.wallet_error_no_account)
|
tvErrorTitle.text = fragment.getText(R.string.wallet_error_no_account)
|
||||||
tvErrorDescriptions.text =
|
tvErrorDescriptions.text =
|
||||||
fragment.getString(
|
fragment.getString(
|
||||||
R.string.no_account_generic,
|
R.string.no_account_generic,
|
||||||
data.amountToCreateAccount,
|
blockchainWalletData.status.amountToCreateAccount,
|
||||||
data.currencySymbol,
|
blockchainWalletData.currency.currencySymbol,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
BalanceStatus.UnknownBlockchain -> with(binding.lBalanceError) {
|
// BalanceStatus.UnknownBlockchain -> with(binding.lBalanceError) {
|
||||||
binding.lBalance.root.hide()
|
// binding.lBalance.root.hide()
|
||||||
binding.lBalanceError.root.show()
|
// binding.lBalanceError.root.show()
|
||||||
tvErrorTitle.text =
|
// tvErrorTitle.text =
|
||||||
fragment.getText(R.string.wallet_error_unsupported_blockchain)
|
// fragment.getText(R.string.wallet_error_unsupported_blockchain)
|
||||||
tvErrorDescriptions.text =
|
// tvErrorDescriptions.text =
|
||||||
fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle)
|
// fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle)
|
||||||
}
|
// }
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -140,25 +146,25 @@ class BalanceWidget(
|
||||||
tvStatusVerified.show(viewRes == R.id.tv_status_verified)
|
tvStatusVerified.show(viewRes == R.id.tv_status_verified)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showBalanceWithToken(data: BalanceWidgetData, showAmount: Boolean) = with(binding.lBalance) {
|
private fun showBalanceWithToken(data: WalletDataModel, showAmount: Boolean) = with(binding.lBalance) {
|
||||||
groupBaseCurrency.show()
|
groupBaseCurrency.show()
|
||||||
tvCurrency.text = token?.currencySymbol
|
tvCurrency.text = tokenWalletData?.currency?.currencySymbol
|
||||||
tvBaseCurrency.text = data.currency
|
tvBaseCurrency.text = data.currency.currencyName
|
||||||
tvAmount.text = if (showAmount) token?.amountFormatted else ""
|
tvAmount.text = if (showAmount) tokenWalletData?.getFormattedAmount() else ""
|
||||||
tvBaseAmount.text = if (showAmount) data.amountFormatted else ""
|
tvBaseAmount.text = if (showAmount) data.getFormattedAmount() else ""
|
||||||
if (showAmount) {
|
if (showAmount) {
|
||||||
tvFiatAmount.show()
|
tvFiatAmount.show()
|
||||||
tvFiatAmount.text = token?.fiatAmountFormatted
|
tvFiatAmount.text = tokenWalletData?.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showBalanceWithoutToken(data: BalanceWidgetData, showAmount: Boolean) = with(binding.lBalance) {
|
private fun showBalanceWithoutToken(data: WalletDataModel, showAmount: Boolean) = with(binding.lBalance) {
|
||||||
groupBaseCurrency.hide()
|
groupBaseCurrency.hide()
|
||||||
tvCurrency.text = data.currency
|
tvCurrency.text = data.currency.currencyName
|
||||||
tvAmount.text = if (showAmount) data.amountFormatted else ""
|
tvAmount.text = if (showAmount) data.getFormattedAmount() else ""
|
||||||
if (showAmount) {
|
if (showAmount) {
|
||||||
tvFiatAmount.show()
|
tvFiatAmount.show()
|
||||||
tvFiatAmount.text = data.fiatAmountFormatted
|
tvFiatAmount.text = data.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -41,21 +41,29 @@ import com.tangem.tap.common.extensions.show
|
||||||
import com.tangem.tap.common.extensions.toQrCode
|
import com.tangem.tap.common.extensions.toQrCode
|
||||||
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
|
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
|
||||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
import com.tangem.tap.features.wallet.models.PendingTransaction
|
import com.tangem.tap.features.wallet.models.PendingTransaction
|
||||||
import com.tangem.tap.features.wallet.models.PendingTransactionType
|
import com.tangem.tap.features.wallet.models.PendingTransactionType
|
||||||
import com.tangem.tap.features.wallet.models.WalletWarning
|
import com.tangem.tap.features.wallet.models.WalletWarning
|
||||||
import com.tangem.tap.features.wallet.redux.AddressData
|
|
||||||
import com.tangem.tap.features.wallet.redux.ErrorType
|
import com.tangem.tap.features.wallet.redux.ErrorType
|
||||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.features.wallet.redux.WalletData
|
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState
|
import com.tangem.tap.features.wallet.redux.WalletState
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||||
import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter
|
import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter
|
||||||
import com.tangem.tap.features.wallet.ui.adapters.WalletDetailWarningMessagesAdapter
|
import com.tangem.tap.features.wallet.ui.adapters.WalletDetailWarningMessagesAdapter
|
||||||
import com.tangem.tap.features.wallet.ui.images.load
|
import com.tangem.tap.features.wallet.ui.images.load
|
||||||
import com.tangem.tap.features.wallet.ui.test.TestWallet
|
import com.tangem.tap.features.wallet.ui.test.TestWallet
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.assembleWarnings
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.getAvailableActions
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.isAvailableToBuy
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.isAvailableToSell
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.isAvailableToSwap
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.mainButton
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.shouldShowMultipleAddress
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import com.tangem.tap.userWalletsListManagerSafe
|
import com.tangem.tap.userWalletsListManagerSafe
|
||||||
import com.tangem.tap.walletCurrenciesManager
|
import com.tangem.tap.walletCurrenciesManager
|
||||||
|
|
@ -85,31 +93,19 @@ class WalletDetailsFragment :
|
||||||
|
|
||||||
private val binding: FragmentWalletDetailsBinding by viewBinding(FragmentWalletDetailsBinding::bind)
|
private val binding: FragmentWalletDetailsBinding by viewBinding(FragmentWalletDetailsBinding::bind)
|
||||||
|
|
||||||
private val walletDataWatcher: ModelWatcher<WalletData> = modelWatcher {
|
private val walletDataWatcher: ModelWatcher<WalletDataModel> = modelWatcher {
|
||||||
val addressCardStrategy: DiffStrategy<WalletData> = { old, new ->
|
val addressCardStrategy: DiffStrategy<WalletDataModel> = { old, new ->
|
||||||
old.currency != new.currency ||
|
old.currency != new.currency || old.walletAddresses != new.walletAddresses
|
||||||
old.walletAddresses?.selectedAddress != new.walletAddresses?.selectedAddress ||
|
|
||||||
old.shouldShowMultipleAddress() != new.shouldShowMultipleAddress()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WalletData::pendingTransactions {
|
WalletDataModel::currency {
|
||||||
showPendingTransactionsIfPresent(it)
|
|
||||||
}
|
|
||||||
WalletData::currency {
|
|
||||||
handleCurrencyIcon(it)
|
handleCurrencyIcon(it)
|
||||||
}
|
}
|
||||||
WalletData::currencyData {
|
WalletDataModel::walletAddresses { walletAddresses ->
|
||||||
setupBalanceData(it)
|
|
||||||
}
|
|
||||||
WalletData::walletAddresses { walletAddresses ->
|
|
||||||
setupCopyAndShareButtons(walletAddresses?.selectedAddress?.address)
|
setupCopyAndShareButtons(walletAddresses?.selectedAddress?.address)
|
||||||
}
|
}
|
||||||
WalletData::assembleWarnings { warnings ->
|
WalletDataModel::currency { currency ->
|
||||||
handleWarnings(warnings)
|
setupCurrency(currency)
|
||||||
}
|
|
||||||
(WalletData::currencyData or WalletData::currency) { walletData ->
|
|
||||||
setupCurrency(walletData.currencyData, walletData.currency)
|
|
||||||
setupSwipeRefresh(walletData.currencyData, walletData.currency)
|
|
||||||
}
|
}
|
||||||
watch({ it }, addressCardStrategy) { walletData ->
|
watch({ it }, addressCardStrategy) { walletData ->
|
||||||
setupAddressCard(
|
setupAddressCard(
|
||||||
|
|
@ -121,9 +117,28 @@ class WalletDetailsFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private val walletStateWatcher: ModelWatcher<WalletState> = modelWatcher {
|
private val walletStateWatcher: ModelWatcher<WalletState> = modelWatcher {
|
||||||
WalletState::selectedWalletData { selectedWallet ->
|
val walletDataStrategy: DiffStrategy<WalletState> = { old, new ->
|
||||||
|
new.walletsStores.isNotEmpty() &&
|
||||||
|
new.selectedCurrency != null &&
|
||||||
|
(old.selectedCurrency != new.selectedCurrency || old.walletsStores != new.walletsStores)
|
||||||
|
}
|
||||||
|
|
||||||
|
watch({ it }, walletDataStrategy) { state ->
|
||||||
|
val selectedWallet = state.selectedWalletData
|
||||||
if (selectedWallet != null) {
|
if (selectedWallet != null) {
|
||||||
|
setupBalanceData(selectedWallet)
|
||||||
|
setupSwipeRefresh(selectedWallet)
|
||||||
walletDataWatcher.invoke(selectedWallet)
|
walletDataWatcher.invoke(selectedWallet)
|
||||||
|
|
||||||
|
val walletStore = state.getWalletStore(state.selectedCurrency)
|
||||||
|
if (walletStore != null) {
|
||||||
|
handleWarnings(
|
||||||
|
selectedWallet.assembleWarnings(
|
||||||
|
blockchainAmount = walletStore.blockchainWalletData.status.amount,
|
||||||
|
blockchainWalletRent = walletStore.walletRent,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(WalletState::selectedWalletData or WalletState::isExchangeServiceFeatureOn) { state ->
|
(WalletState::selectedWalletData or WalletState::isExchangeServiceFeatureOn) { state ->
|
||||||
|
|
@ -234,8 +249,8 @@ class WalletDetailsFragment :
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupCurrency(currencyData: BalanceWidgetData, currency: Currency) = with(binding) {
|
private fun setupCurrency(currency: Currency) = with(binding) {
|
||||||
tvCurrencyTitle.text = currencyData.currency
|
tvCurrencyTitle.text = currency.currencyName
|
||||||
|
|
||||||
if (currency is Currency.Token) {
|
if (currency is Currency.Token) {
|
||||||
tvCurrencySubtitle.text = tvCurrencySubtitle.getString(
|
tvCurrencySubtitle.text = tvCurrencySubtitle.getString(
|
||||||
|
|
@ -248,16 +263,17 @@ class WalletDetailsFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupSwipeRefresh(currencyData: BalanceWidgetData, currency: Currency) {
|
private fun setupSwipeRefresh(walletData: WalletDataModel) {
|
||||||
binding.srlWalletDetails.setOnRefreshListener {
|
binding.srlWalletDetails.setOnRefreshListener {
|
||||||
if (currencyData.status != BalanceStatus.Loading && currencyData.status != BalanceStatus.Refreshing) {
|
if (walletData.status !is WalletDataModel.Loading) {
|
||||||
Analytics.send(Token.Refreshed())
|
Analytics.send(Token.Refreshed())
|
||||||
|
val selectedUserWallet = userWalletsListManagerSafe?.selectedUserWalletSync.guard {
|
||||||
|
Timber.e("Unable to refresh wallet details screen, no user wallet selected")
|
||||||
|
return@setOnRefreshListener
|
||||||
|
}
|
||||||
|
binding.srlWalletDetails.isRefreshing = true
|
||||||
lifecycleScope.launch(Dispatchers.Default) {
|
lifecycleScope.launch(Dispatchers.Default) {
|
||||||
val selectedUserWallet = userWalletsListManagerSafe?.selectedUserWalletSync.guard {
|
walletCurrenciesManager.update(selectedUserWallet, walletData.currency)
|
||||||
Timber.e("Unable to refresh wallet details screen, no user wallet selected")
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
walletCurrenciesManager.update(selectedUserWallet, currency)
|
|
||||||
.doOnResult {
|
.doOnResult {
|
||||||
withMainContext {
|
withMainContext {
|
||||||
binding.srlWalletDetails.isRefreshing = false
|
binding.srlWalletDetails.isRefreshing = false
|
||||||
|
|
@ -266,9 +282,6 @@ class WalletDetailsFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.srlWalletDetails.isRefreshing = currencyData.status == BalanceStatus.Loading ||
|
|
||||||
currencyData.status == BalanceStatus.Refreshing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupCopyAndShareButtons(walletAddress: String?) {
|
private fun setupCopyAndShareButtons(walletAddress: String?) {
|
||||||
|
|
@ -284,7 +297,7 @@ class WalletDetailsFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupButtonsRow(selectedWallet: WalletData, isExchangeServiceFeatureOn: Boolean) {
|
private fun setupButtonsRow(selectedWallet: WalletDataModel, isExchangeServiceFeatureOn: Boolean) {
|
||||||
val exchangeManager = store.state.globalState.exchangeManager
|
val exchangeManager = store.state.globalState.exchangeManager
|
||||||
binding.rowButtons.apply {
|
binding.rowButtons.apply {
|
||||||
onBuyClick = { store.dispatch(WalletAction.TradeCryptoAction.Buy()) }
|
onBuyClick = { store.dispatch(WalletAction.TradeCryptoAction.Buy()) }
|
||||||
|
|
@ -340,7 +353,7 @@ class WalletDetailsFragment :
|
||||||
|
|
||||||
private fun setupAddressCard(
|
private fun setupAddressCard(
|
||||||
shouldShowMultipleAddress: Boolean,
|
shouldShowMultipleAddress: Boolean,
|
||||||
selectedAddress: AddressData?,
|
selectedAddress: WalletDataModel.AddressData?,
|
||||||
currency: Currency,
|
currency: Currency,
|
||||||
) = with(binding.lWalletDetails) {
|
) = with(binding.lWalletDetails) {
|
||||||
if (selectedAddress == null) return@with
|
if (selectedAddress == null) return@with
|
||||||
|
|
@ -371,7 +384,7 @@ class WalletDetailsFragment :
|
||||||
|
|
||||||
private fun setupAddressTypeChips(
|
private fun setupAddressTypeChips(
|
||||||
shouldShowMultipleAddress: Boolean,
|
shouldShowMultipleAddress: Boolean,
|
||||||
selectedAddress: AddressData,
|
selectedAddress: WalletDataModel.AddressData,
|
||||||
currency: Currency,
|
currency: Currency,
|
||||||
) = with(binding.lWalletDetails) {
|
) = with(binding.lWalletDetails) {
|
||||||
if (shouldShowMultipleAddress && currency is Currency.Blockchain) {
|
if (shouldShowMultipleAddress && currency is Currency.Blockchain) {
|
||||||
|
|
@ -408,54 +421,58 @@ class WalletDetailsFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupBalanceData(data: BalanceWidgetData) = with(binding.lWalletDetails) {
|
private fun setupBalanceData(walletData: WalletDataModel) = with(binding.lWalletDetails) {
|
||||||
when (data.status) {
|
when (val status = walletData.status) {
|
||||||
BalanceStatus.Loading -> {
|
is WalletDataModel.Loading -> {
|
||||||
lBalanceError.root.hide()
|
lBalanceError.root.hide()
|
||||||
lBalance.root.show()
|
lBalance.root.show()
|
||||||
lBalance.groupBalance.show()
|
lBalance.groupBalance.show()
|
||||||
lBalance.tvError.hide()
|
lBalance.tvError.hide()
|
||||||
lBalance.tvAmount.text = data.amountFormatted
|
lBalance.tvAmount.text = walletData.getFormattedAmount()
|
||||||
lBalance.tvFiatAmount.text = data.fiatAmountFormatted ?: UNKNOWN_AMOUNT_SIGN
|
lBalance.tvFiatAmount.text = walletData.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||||
lBalance.tvStatus.setLoadingStatus(R.string.wallet_balance_loading)
|
lBalance.tvStatus.setLoadingStatus(R.string.wallet_balance_loading)
|
||||||
}
|
}
|
||||||
BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress,
|
is WalletDataModel.VerifiedOnline,
|
||||||
BalanceStatus.TransactionInProgress,
|
is WalletDataModel.SameCurrencyTransactionInProgress,
|
||||||
|
is WalletDataModel.TransactionInProgress,
|
||||||
-> {
|
-> {
|
||||||
lBalanceError.root.hide()
|
lBalanceError.root.hide()
|
||||||
lBalance.root.show()
|
lBalance.root.show()
|
||||||
lBalance.groupBalance.show()
|
lBalance.groupBalance.show()
|
||||||
lBalance.tvError.hide()
|
lBalance.tvError.hide()
|
||||||
lBalance.tvAmount.text = data.amountFormatted
|
lBalance.tvAmount.text = walletData.getFormattedAmount()
|
||||||
lBalance.tvFiatAmount.text = data.fiatAmountFormatted ?: UNKNOWN_AMOUNT_SIGN
|
lBalance.tvFiatAmount.text = walletData.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||||
when (data.status) {
|
when (status) {
|
||||||
BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress -> {
|
is WalletDataModel.VerifiedOnline,
|
||||||
|
is WalletDataModel.SameCurrencyTransactionInProgress,
|
||||||
|
-> {
|
||||||
lBalance.tvStatus.setVerifiedBalanceStatus(R.string.wallet_balance_verified)
|
lBalance.tvStatus.setVerifiedBalanceStatus(R.string.wallet_balance_verified)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
lBalance.tvStatus.setWarningStatus(R.string.wallet_balance_tx_in_progress)
|
lBalance.tvStatus.setWarningStatus(R.string.wallet_balance_tx_in_progress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
showPendingTransactionsIfPresent(status.pendingTransactions)
|
||||||
}
|
}
|
||||||
BalanceStatus.Unreachable -> {
|
is WalletDataModel.Unreachable -> {
|
||||||
lBalanceError.root.hide()
|
lBalanceError.root.hide()
|
||||||
lBalance.root.show()
|
lBalance.root.show()
|
||||||
lBalance.groupBalance.hide()
|
lBalance.groupBalance.hide()
|
||||||
lBalance.tvError.show()
|
lBalance.tvError.show()
|
||||||
lBalance.tvError.setWarningStatus(
|
lBalance.tvError.setWarningStatus(
|
||||||
R.string.wallet_balance_blockchain_unreachable,
|
R.string.wallet_balance_blockchain_unreachable,
|
||||||
data.errorMessage,
|
status.errorMessage,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
BalanceStatus.NoAccount -> {
|
is WalletDataModel.NoAccount -> {
|
||||||
lBalance.root.hide()
|
lBalance.root.hide()
|
||||||
lBalanceError.root.show()
|
lBalanceError.root.show()
|
||||||
lBalanceError.tvErrorTitle.text = getText(R.string.wallet_error_no_account)
|
lBalanceError.tvErrorTitle.text = getText(R.string.wallet_error_no_account)
|
||||||
lBalanceError.tvErrorDescriptions.text =
|
lBalanceError.tvErrorDescriptions.text =
|
||||||
getString(
|
getString(
|
||||||
R.string.no_account_generic,
|
R.string.no_account_generic,
|
||||||
data.amountToCreateAccount,
|
status.amountToCreateAccount,
|
||||||
data.currencySymbol,
|
walletData.currency.currencySymbol,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
||||||
|
|
||||||
private val totalBalanceWatcher = modelWatcher {
|
private val totalBalanceWatcher = modelWatcher {
|
||||||
(WalletState::totalBalance) { totalBalance ->
|
(WalletState::totalBalance) { totalBalance ->
|
||||||
totalBalance?.state?.let {
|
totalBalance?.let {
|
||||||
viewModel.onBalanceLoaded(totalBalance)
|
viewModel.onBalanceLoaded(totalBalance)
|
||||||
store.state.globalState.topUpController?.totalBalanceStateChanged(it)
|
store.state.globalState.topUpController?.totalBalanceStateChanged(it)
|
||||||
}
|
}
|
||||||
|
|
@ -159,8 +159,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
||||||
walletView = SaltPayWalletView()
|
walletView = SaltPayWalletView()
|
||||||
walletView.changeWalletView(this, binding)
|
walletView.changeWalletView(this, binding)
|
||||||
}
|
}
|
||||||
state.isMultiwalletAllowed && state.primaryWalletData?.currencyData?.status != BalanceStatus.EmptyCard &&
|
state.isMultiwalletAllowed && walletView !is MultiWalletView -> {
|
||||||
walletView !is MultiWalletView -> {
|
|
||||||
walletView.onViewDestroy()
|
walletView.onViewDestroy()
|
||||||
walletView = MultiWalletView()
|
walletView = MultiWalletView()
|
||||||
walletView.changeWalletView(this, binding)
|
walletView.changeWalletView(this, binding)
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
|
||||||
import com.tangem.tap.common.analytics.events.Basic
|
import com.tangem.tap.common.analytics.events.Basic
|
||||||
import com.tangem.tap.common.analytics.events.MainScreen
|
import com.tangem.tap.common.analytics.events.MainScreen
|
||||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||||
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
import com.tangem.tap.domain.userWalletList.UserWalletsListManager
|
import com.tangem.tap.domain.userWalletList.UserWalletsListManager
|
||||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.features.wallet.ui.analytics.WalletAnalyticsEventsMapper
|
import com.tangem.tap.features.wallet.ui.analytics.WalletAnalyticsEventsMapper
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
|
|
@ -88,7 +88,7 @@ internal class WalletViewModel @Inject constructor(
|
||||||
bootstrapShowSaveWalletIfNeeded()
|
bootstrapShowSaveWalletIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onBalanceLoaded(totalBalance: TotalBalance?) {
|
fun onBalanceLoaded(totalBalance: TotalFiatBalance?) {
|
||||||
if (totalBalance != null) {
|
if (totalBalance != null) {
|
||||||
walletAnalyticsEventsMapper.convert(totalBalance)?.let { balanceParam ->
|
walletAnalyticsEventsMapper.convert(totalBalance)?.let { balanceParam ->
|
||||||
analyticsEventHandler.send(
|
analyticsEventHandler.send(
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ class WalletWarningConverter(
|
||||||
is WalletWarning.Rent -> {
|
is WalletWarning.Rent -> {
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.solana_rent_warning,
|
R.string.solana_rent_warning,
|
||||||
message.walletRent.minRentValue,
|
message.walletRent.rent,
|
||||||
message.walletRent.rentExemptValue,
|
message.walletRent.exemptionAmount,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,20 @@ import com.tangem.tap.common.analytics.events.Portfolio
|
||||||
import com.tangem.tap.common.extensions.getString
|
import com.tangem.tap.common.extensions.getString
|
||||||
import com.tangem.tap.common.extensions.hide
|
import com.tangem.tap.common.extensions.hide
|
||||||
import com.tangem.tap.common.extensions.show
|
import com.tangem.tap.common.extensions.show
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.features.wallet.redux.WalletData
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
||||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatRate
|
||||||
import com.tangem.tap.features.wallet.ui.images.load
|
import com.tangem.tap.features.wallet.ui.images.load
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import com.tangem.wallet.databinding.ItemCurrencyWalletBinding
|
import com.tangem.wallet.databinding.ItemCurrencyWalletBinding
|
||||||
|
|
||||||
class WalletAdapter : ListAdapter<WalletData, WalletAdapter.WalletsViewHolder>(DiffUtilCallback) {
|
class WalletAdapter : ListAdapter<WalletDataModel, WalletAdapter.WalletsViewHolder>(DiffUtilCallback) {
|
||||||
|
|
||||||
override fun getItemId(position: Int): Long {
|
override fun getItemId(position: Int): Long {
|
||||||
return currentList[position].currencyData.currencySymbol?.hashCode()?.toLong() ?: 0
|
return currentList[position].currency.currencySymbol.hashCode().toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WalletsViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WalletsViewHolder {
|
||||||
|
|
@ -39,34 +41,33 @@ class WalletAdapter : ListAdapter<WalletData, WalletAdapter.WalletsViewHolder>(D
|
||||||
holder.bind(currentList[position])
|
holder.bind(currentList[position])
|
||||||
}
|
}
|
||||||
|
|
||||||
object DiffUtilCallback : DiffUtil.ItemCallback<WalletData>() {
|
object DiffUtilCallback : DiffUtil.ItemCallback<WalletDataModel>() {
|
||||||
override fun areContentsTheSame(oldItem: WalletData, newItem: WalletData) = oldItem == newItem
|
override fun areContentsTheSame(oldItem: WalletDataModel, newItem: WalletDataModel) = oldItem == newItem
|
||||||
|
|
||||||
override fun areItemsTheSame(oldItem: WalletData, newItem: WalletData) = oldItem == newItem
|
override fun areItemsTheSame(oldItem: WalletDataModel, newItem: WalletDataModel) = oldItem == newItem
|
||||||
}
|
}
|
||||||
|
|
||||||
class WalletsViewHolder(val binding: ItemCurrencyWalletBinding) :
|
class WalletsViewHolder(val binding: ItemCurrencyWalletBinding) :
|
||||||
RecyclerView.ViewHolder(binding.root) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
fun bind(wallet: WalletData) = with(binding) {
|
fun bind(wallet: WalletDataModel) = with(binding) {
|
||||||
val status = wallet.currencyData.status
|
val status = wallet.status
|
||||||
// Skip changes when on refreshing status
|
val fiatCurrency = store.state.globalState.appCurrency
|
||||||
if (status == BalanceStatus.Refreshing) return@with
|
|
||||||
|
|
||||||
val statusMessage = when (status) {
|
val statusMessage = when (status) {
|
||||||
BalanceStatus.TransactionInProgress -> {
|
is WalletDataModel.TransactionInProgress -> {
|
||||||
root.getString(R.string.wallet_balance_tx_in_progress)
|
root.getString(R.string.wallet_balance_tx_in_progress)
|
||||||
}
|
}
|
||||||
BalanceStatus.Unreachable -> {
|
is WalletDataModel.Unreachable -> {
|
||||||
root.getString(R.string.wallet_balance_blockchain_unreachable)
|
root.getString(R.string.wallet_balance_blockchain_unreachable)
|
||||||
}
|
}
|
||||||
BalanceStatus.MissedDerivation -> {
|
is WalletDataModel.MissedDerivation -> {
|
||||||
root.getString(R.string.wallet_balance_missing_derivation)
|
root.getString(R.string.wallet_balance_missing_derivation)
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == null || status == BalanceStatus.Loading) {
|
if (status is WalletDataModel.Loading) {
|
||||||
lContent.root.hide()
|
lContent.root.hide()
|
||||||
lShimmer.root.veil()
|
lShimmer.root.veil()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -82,24 +83,22 @@ class WalletAdapter : ListAdapter<WalletData, WalletAdapter.WalletsViewHolder>(D
|
||||||
?.derivationStyle,
|
?.derivationStyle,
|
||||||
)
|
)
|
||||||
|
|
||||||
lContent.tvCurrency.text = wallet.currencyData.currency
|
lContent.tvCurrency.text = wallet.currency.currencyName
|
||||||
lContent.tvAmountFiat.text = wallet.currencyData.fiatAmountFormatted ?: "—"
|
lContent.tvAmountFiat.text = wallet.getFormattedFiatAmount(fiatCurrency)
|
||||||
lContent.tvAmount.text = wallet.currencyData.amountFormatted ?: "—"
|
lContent.tvAmount.text = wallet.getFormattedAmount()
|
||||||
|
|
||||||
lContent.tvStatus.isVisible = statusMessage != null
|
lContent.tvStatus.isVisible = statusMessage != null
|
||||||
lContent.tvStatus.text = statusMessage
|
lContent.tvStatus.text = statusMessage
|
||||||
|
|
||||||
lContent.tvExchangeRate.isVisible = statusMessage == null
|
lContent.tvExchangeRate.isVisible = statusMessage == null
|
||||||
lContent.tvExchangeRate.text = wallet.fiatRateString
|
lContent.tvExchangeRate.text = wallet.getFormattedFiatRate(
|
||||||
?: root.getString(id = R.string.token_item_no_rate)
|
fiatCurrency = fiatCurrency,
|
||||||
|
noRateValue = root.getString(id = R.string.token_item_no_rate),
|
||||||
|
)
|
||||||
|
|
||||||
if (wallet.walletAddresses != null) {
|
cardWallet.setOnClickListener {
|
||||||
cardWallet.setOnClickListener {
|
Analytics.send(Portfolio.TokenTapped())
|
||||||
Analytics.send(Portfolio.TokenTapped())
|
store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet.currency))
|
||||||
store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet.currency))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cardWallet.setOnClickListener(null)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,16 @@ package com.tangem.tap.features.wallet.ui.analytics
|
||||||
|
|
||||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||||
import com.tangem.tap.common.extensions.isGreaterThan
|
import com.tangem.tap.common.extensions.isGreaterThan
|
||||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
|
||||||
import com.tangem.utils.converter.Converter
|
import com.tangem.utils.converter.Converter
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
class WalletAnalyticsEventsMapper : Converter<TotalBalance, AnalyticsParam.CardBalanceState?> {
|
class WalletAnalyticsEventsMapper : Converter<TotalFiatBalance, AnalyticsParam.CardBalanceState?> {
|
||||||
|
|
||||||
override fun convert(value: TotalBalance): AnalyticsParam.CardBalanceState? {
|
override fun convert(value: TotalFiatBalance): AnalyticsParam.CardBalanceState? {
|
||||||
return when (value.state) {
|
return when (value) {
|
||||||
ProgressState.Done -> if (value.fiatAmount?.isGreaterThan(BigDecimal.ZERO) == true) {
|
is TotalFiatBalance.Error -> {
|
||||||
AnalyticsParam.CardBalanceState.Full
|
if (value.amount == null) {
|
||||||
} else {
|
|
||||||
AnalyticsParam.CardBalanceState.Empty
|
|
||||||
}
|
|
||||||
ProgressState.Error -> {
|
|
||||||
if (value.fiatAmount == null) {
|
|
||||||
// if fiatAmount is null while ProgressState.Error it means error occurs when loading blockchain
|
// if fiatAmount is null while ProgressState.Error it means error occurs when loading blockchain
|
||||||
AnalyticsParam.CardBalanceState.BlockchainError
|
AnalyticsParam.CardBalanceState.BlockchainError
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -25,7 +19,14 @@ class WalletAnalyticsEventsMapper : Converter<TotalBalance, AnalyticsParam.CardB
|
||||||
AnalyticsParam.CardBalanceState.CustomToken
|
AnalyticsParam.CardBalanceState.CustomToken
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> null
|
is TotalFiatBalance.Loaded -> {
|
||||||
|
if (value.amount.isGreaterThan(BigDecimal.ZERO)) {
|
||||||
|
AnalyticsParam.CardBalanceState.Full
|
||||||
|
} else {
|
||||||
|
AnalyticsParam.CardBalanceState.Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is TotalFiatBalance.Loading -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
package com.tangem.tap.features.wallet.ui.utils
|
||||||
|
|
||||||
|
import com.tangem.blockchain.common.Blockchain
|
||||||
|
import com.tangem.common.extensions.isZero
|
||||||
|
import com.tangem.domain.common.extensions.toNetworkId
|
||||||
|
import com.tangem.feature.swap.api.SwapFeatureToggleManager
|
||||||
|
import com.tangem.feature.swap.domain.SwapInteractor
|
||||||
|
import com.tangem.tap.common.entities.FiatCurrency
|
||||||
|
import com.tangem.tap.common.extensions.toFiatRateString
|
||||||
|
import com.tangem.tap.common.extensions.toFiatValue
|
||||||
|
import com.tangem.tap.common.extensions.toFormattedCurrencyString
|
||||||
|
import com.tangem.tap.common.extensions.toFormattedFiatValue
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
|
import com.tangem.tap.features.wallet.models.WalletWarning
|
||||||
|
import com.tangem.tap.features.wallet.redux.WalletMainButton
|
||||||
|
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||||
|
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
internal val WalletDataModel.mainButton: WalletMainButton
|
||||||
|
get() = WalletMainButton.SendButton(
|
||||||
|
enabled = !status.amount.isZero() && status.pendingTransactions.isEmpty(),
|
||||||
|
)
|
||||||
|
|
||||||
|
internal fun WalletDataModel.getFormattedAmount(): String {
|
||||||
|
return status.amount.toFormattedCurrencyString(
|
||||||
|
decimals = currency.decimals,
|
||||||
|
currency = currency.currencySymbol,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun WalletDataModel.getFormattedFiatAmount(
|
||||||
|
fiatCurrency: FiatCurrency,
|
||||||
|
unknownAmountSign: String = UNKNOWN_AMOUNT_SIGN,
|
||||||
|
): String {
|
||||||
|
return this.fiatRate?.let { status.amount.toFiatValue(it) }
|
||||||
|
?.takeIf { !status.isErrorStatus }
|
||||||
|
?.toFormattedFiatValue(fiatCurrency.symbol)
|
||||||
|
?: unknownAmountSign
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun WalletDataModel.getFormattedFiatRate(fiatCurrency: FiatCurrency, noRateValue: String): String {
|
||||||
|
return fiatRate?.toFiatRateString(fiatCurrency.symbol)
|
||||||
|
?: noRateValue
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun WalletDataModel.isAvailableToBuy(exchangeManager: CurrencyExchangeManager): Boolean {
|
||||||
|
return exchangeManager.availableForBuy(currency)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun WalletDataModel.isAvailableToSell(exchangeManager: CurrencyExchangeManager): Boolean {
|
||||||
|
return exchangeManager.availableForSell(currency)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun WalletDataModel.isAvailableToSwap(
|
||||||
|
swapFeatureToggleManager: SwapFeatureToggleManager,
|
||||||
|
swapInteractor: SwapInteractor,
|
||||||
|
): Boolean {
|
||||||
|
if (currency.blockchain.id == Blockchain.Optimism.id && !swapFeatureToggleManager.isOptimismSwapEnabled) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return swapInteractor.isAvailableToSwap(currency.blockchain.toNetworkId()) &&
|
||||||
|
!currency.isCustomCurrency(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun WalletDataModel.getAvailableActions(
|
||||||
|
swapInteractor: SwapInteractor,
|
||||||
|
exchangeManager: CurrencyExchangeManager,
|
||||||
|
swapFeatureToggleManager: SwapFeatureToggleManager,
|
||||||
|
): Set<CurrencyAction> {
|
||||||
|
return setOfNotNull(
|
||||||
|
if (isAvailableToBuy(exchangeManager)) CurrencyAction.Buy else null,
|
||||||
|
if (isAvailableToSell(exchangeManager)) CurrencyAction.Sell else null,
|
||||||
|
if (isAvailableToSwap(swapFeatureToggleManager, swapInteractor)) CurrencyAction.Swap else null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun WalletDataModel.shouldShowMultipleAddress(): Boolean {
|
||||||
|
val listOfAddresses = walletAddresses?.list.orEmpty()
|
||||||
|
return listOfAddresses.size > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun WalletDataModel.assembleWarnings(
|
||||||
|
blockchainAmount: BigDecimal,
|
||||||
|
blockchainWalletRent: WalletStoreModel.WalletRent?,
|
||||||
|
): List<WalletWarning> {
|
||||||
|
val walletWarnings = mutableListOf<WalletWarning>()
|
||||||
|
assembleNonTypedWarnings(walletWarnings, blockchainWalletRent)
|
||||||
|
assembleBlockchainWarnings(walletWarnings)
|
||||||
|
assembleTokenWarnings(walletWarnings, blockchainAmount)
|
||||||
|
|
||||||
|
return walletWarnings.sortedBy { it.showingPosition }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun WalletDataModel.assembleNonTypedWarnings(
|
||||||
|
walletWarnings: MutableList<WalletWarning>,
|
||||||
|
walletRent: WalletStoreModel.WalletRent?,
|
||||||
|
) {
|
||||||
|
if (this.status is WalletDataModel.SameCurrencyTransactionInProgress) {
|
||||||
|
walletWarnings.add(WalletWarning.TransactionInProgress(currency.currencyName))
|
||||||
|
}
|
||||||
|
if (walletRent != null) {
|
||||||
|
walletWarnings.add(WalletWarning.Rent(walletRent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun WalletDataModel.assembleBlockchainWarnings(walletWarnings: MutableList<WalletWarning>) {
|
||||||
|
with(currency) {
|
||||||
|
if (!isBlockchain()) return
|
||||||
|
|
||||||
|
if (existentialDeposit != null) {
|
||||||
|
val warning = WalletWarning.ExistentialDeposit(
|
||||||
|
currencyName = currencyName,
|
||||||
|
edStringValueWithSymbol = "${existentialDeposit.toPlainString()} $currencySymbol",
|
||||||
|
)
|
||||||
|
walletWarnings.add(warning)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun WalletDataModel.assembleTokenWarnings(
|
||||||
|
walletWarnings: MutableList<WalletWarning>,
|
||||||
|
blockchainAmount: BigDecimal,
|
||||||
|
) {
|
||||||
|
if (!currency.isToken()) return
|
||||||
|
|
||||||
|
if (!this.isEmptyAmount && blockchainAmount.isZero()) {
|
||||||
|
walletWarnings.add(
|
||||||
|
WalletWarning.BalanceNotEnoughForFee(
|
||||||
|
currencyName = currency.currencyName,
|
||||||
|
blockchainFullName = currency.blockchain.fullName,
|
||||||
|
blockchainSymbol = currency.blockchain.currency,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val WalletDataModel.isEmptyAmount: Boolean
|
||||||
|
get() = this.status.amount.isZero()
|
||||||
|
|
||||||
|
enum class CurrencyAction {
|
||||||
|
Buy, Sell, Swap
|
||||||
|
}
|
||||||
|
|
@ -35,9 +35,8 @@ import com.tangem.core.ui.components.SpacerW4
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.tap.common.entities.FiatCurrency
|
import com.tangem.tap.common.entities.FiatCurrency
|
||||||
import com.tangem.tap.common.extensions.formatWithSpaces
|
import com.tangem.tap.common.extensions.formatWithSpaces
|
||||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import com.valentinilk.shimmer.shimmer
|
import com.valentinilk.shimmer.shimmer
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
@ -52,18 +51,25 @@ internal class TotalBalanceCard @JvmOverloads constructor(
|
||||||
) : AbstractComposeView(context, attrs, defStyleAttr) {
|
) : AbstractComposeView(context, attrs, defStyleAttr) {
|
||||||
private var state by mutableStateOf<TotalBalanceCardState>(TotalBalanceCardState.Empty)
|
private var state by mutableStateOf<TotalBalanceCardState>(TotalBalanceCardState.Empty)
|
||||||
|
|
||||||
var status: TotalBalance? = null
|
var status: TotalFiatBalance? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
if (field == value) return
|
if (field == value) return
|
||||||
field = value
|
field = value
|
||||||
updateState(value, onChangeFiatCurrencyClick)
|
updateState(value, fiatCurrency, onChangeFiatCurrencyClick)
|
||||||
}
|
}
|
||||||
|
|
||||||
var onChangeFiatCurrencyClick: () -> Unit = { /* no-op */ }
|
var onChangeFiatCurrencyClick: () -> Unit = { /* no-op */ }
|
||||||
set(value) {
|
set(value) {
|
||||||
if (field == value) return
|
if (field == value) return
|
||||||
field = value
|
field = value
|
||||||
updateState(status, value)
|
updateState(status, fiatCurrency, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
var fiatCurrency: FiatCurrency = FiatCurrency.Default
|
||||||
|
set(value) {
|
||||||
|
if (field == value) return
|
||||||
|
field = value
|
||||||
|
updateState(status, value, onChangeFiatCurrencyClick)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -77,23 +83,21 @@ internal class TotalBalanceCard @JvmOverloads constructor(
|
||||||
return javaClass.name
|
return javaClass.name
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateState(status: TotalBalance?, onChangeCurrencyClick: () -> Unit) {
|
private fun updateState(status: TotalFiatBalance?, fiatCurrency: FiatCurrency, onChangeCurrencyClick: () -> Unit) {
|
||||||
state = when (status?.state) {
|
state = when (status) {
|
||||||
null -> TotalBalanceCardState.Empty
|
null -> TotalBalanceCardState.Empty
|
||||||
ProgressState.Loading -> TotalBalanceCardState.Loading(
|
is TotalFiatBalance.Error -> TotalBalanceCardState.Failure(
|
||||||
fiatCurrency = status.fiatCurrency,
|
amount = status.amount,
|
||||||
|
fiatCurrency = fiatCurrency,
|
||||||
onChangeFiatCurrencyClick = onChangeCurrencyClick,
|
onChangeFiatCurrencyClick = onChangeCurrencyClick,
|
||||||
)
|
)
|
||||||
ProgressState.Error -> TotalBalanceCardState.Failure(
|
is TotalFiatBalance.Loading -> TotalBalanceCardState.Loading(
|
||||||
amount = status.fiatAmount,
|
fiatCurrency = fiatCurrency,
|
||||||
fiatCurrency = status.fiatCurrency,
|
|
||||||
onChangeFiatCurrencyClick = onChangeCurrencyClick,
|
onChangeFiatCurrencyClick = onChangeCurrencyClick,
|
||||||
)
|
)
|
||||||
ProgressState.Refreshing,
|
is TotalFiatBalance.Loaded -> TotalBalanceCardState.Success(
|
||||||
ProgressState.Done,
|
amount = status.amount,
|
||||||
-> TotalBalanceCardState.Success(
|
fiatCurrency = fiatCurrency,
|
||||||
amount = status.fiatAmount ?: BigDecimal.ZERO,
|
|
||||||
fiatCurrency = status.fiatCurrency,
|
|
||||||
onChangeFiatCurrencyClick = onChangeCurrencyClick,
|
onChangeFiatCurrencyClick = onChangeCurrencyClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import androidx.core.view.isVisible
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.tangem.tap.common.extensions.hide
|
import com.tangem.tap.common.extensions.hide
|
||||||
import com.tangem.tap.common.extensions.show
|
import com.tangem.tap.common.extensions.show
|
||||||
import com.tangem.tap.features.wallet.redux.CurrencyAction
|
import com.tangem.tap.features.wallet.ui.utils.CurrencyAction
|
||||||
import com.tangem.wallet.databinding.ViewWalletDetailsButtonsRowBinding
|
import com.tangem.wallet.databinding.ViewWalletDetailsButtonsRowBinding
|
||||||
|
|
||||||
internal class WalletDetailsButtonsRow @JvmOverloads constructor(
|
internal class WalletDetailsButtonsRow @JvmOverloads constructor(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.tangem.tap.features.wallet.ui.wallet
|
package com.tangem.tap.features.wallet.ui.wallet
|
||||||
|
|
||||||
import android.widget.Button
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.badoo.mvicore.modelWatcher
|
import com.badoo.mvicore.modelWatcher
|
||||||
|
|
@ -14,14 +13,13 @@ import com.tangem.tap.common.extensions.hide
|
||||||
import com.tangem.tap.common.extensions.show
|
import com.tangem.tap.common.extensions.show
|
||||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||||
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
import com.tangem.tap.features.tokens.redux.TokensAction
|
import com.tangem.tap.features.tokens.redux.TokensAction
|
||||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
import com.tangem.tap.features.wallet.redux.ErrorType
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState
|
import com.tangem.tap.features.wallet.redux.WalletState
|
||||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
|
||||||
import com.tangem.tap.features.wallet.ui.WalletFragment
|
import com.tangem.tap.features.wallet.ui.WalletFragment
|
||||||
import com.tangem.tap.features.wallet.ui.adapters.WalletAdapter
|
import com.tangem.tap.features.wallet.ui.adapters.WalletAdapter
|
||||||
import com.tangem.tap.features.wallet.ui.view.WalletDetailsButtonsRow
|
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import com.tangem.wallet.databinding.FragmentWalletBinding
|
import com.tangem.wallet.databinding.FragmentWalletBinding
|
||||||
|
|
@ -151,35 +149,29 @@ class MultiWalletView : WalletView() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleTotalBalance(binding: FragmentWalletBinding, totalBalance: TotalBalance?, walletsCount: Int) =
|
private fun handleTotalBalance(
|
||||||
with(binding.lCardTotalBalance) {
|
binding: FragmentWalletBinding,
|
||||||
isVisible = walletsCount > 0
|
totalBalance: TotalFiatBalance?,
|
||||||
|
walletsCount: Int,
|
||||||
|
) = with(binding.lCardTotalBalance) {
|
||||||
|
isVisible = walletsCount > 0
|
||||||
|
|
||||||
onChangeFiatCurrencyClick = {
|
onChangeFiatCurrencyClick = {
|
||||||
store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency)
|
store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency)
|
||||||
}
|
|
||||||
status = totalBalance
|
|
||||||
}
|
}
|
||||||
|
status = totalBalance
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleErrorStates(state: WalletState, binding: FragmentWalletBinding, fragment: WalletFragment) {
|
private fun handleErrorStates(state: WalletState, binding: FragmentWalletBinding, fragment: WalletFragment) {
|
||||||
when (state.primaryWalletData?.currencyData?.status) {
|
when (state.error) {
|
||||||
BalanceStatus.EmptyCard -> {
|
ErrorType.UnknownBlockchain -> {
|
||||||
showErrorState(
|
|
||||||
binding,
|
|
||||||
fragment.getText(R.string.wallet_error_empty_card),
|
|
||||||
fragment.getString(R.string.wallet_error_empty_card_subtitle),
|
|
||||||
)
|
|
||||||
configureButtonsForEmptyWalletState(binding)
|
|
||||||
}
|
|
||||||
BalanceStatus.UnknownBlockchain -> {
|
|
||||||
showErrorState(
|
showErrorState(
|
||||||
binding,
|
binding,
|
||||||
fragment.getText(R.string.wallet_error_unsupported_blockchain),
|
fragment.getText(R.string.wallet_error_unsupported_blockchain),
|
||||||
fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle),
|
fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> { /* no-op */
|
else -> { /* no-op */ }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,27 +191,8 @@ class MultiWalletView : WalletView() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun configureButtonsForEmptyWalletState(binding: FragmentWalletBinding) = with(binding) {
|
|
||||||
rowButtons.btnBuy.hide()
|
|
||||||
rowButtons.btnSell.hide()
|
|
||||||
rowButtons.btnTrade.hide()
|
|
||||||
rowButtons.show()
|
|
||||||
|
|
||||||
rowButtons.btnSend.text = fragment?.getText(R.string.wallet_button_create_wallet)
|
|
||||||
rowButtons.onSendClick = { store.dispatch(WalletAction.CreateWallet) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyFragment() {
|
override fun onDestroyFragment() {
|
||||||
super.onDestroyFragment()
|
super.onDestroyFragment()
|
||||||
watcher.clear()
|
watcher.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val WalletDetailsButtonsRow.btnBuy: Button
|
|
||||||
get() = this.findViewById(R.id.btn_buy)
|
|
||||||
private val WalletDetailsButtonsRow.btnSell: Button
|
|
||||||
get() = this.findViewById(R.id.btn_sell)
|
|
||||||
private val WalletDetailsButtonsRow.btnTrade: Button
|
|
||||||
get() = this.findViewById(R.id.btn_trade)
|
|
||||||
private val WalletDetailsButtonsRow.btnSend: Button
|
|
||||||
get() = this.findViewById(R.id.btn_send)
|
|
||||||
|
|
@ -11,14 +11,19 @@ import com.tangem.tap.common.extensions.getQuantityString
|
||||||
import com.tangem.tap.common.extensions.getString
|
import com.tangem.tap.common.extensions.getString
|
||||||
import com.tangem.tap.common.extensions.hide
|
import com.tangem.tap.common.extensions.hide
|
||||||
import com.tangem.tap.common.extensions.show
|
import com.tangem.tap.common.extensions.show
|
||||||
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
|
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
import com.tangem.tap.features.wallet.models.PendingTransaction
|
import com.tangem.tap.features.wallet.models.PendingTransaction
|
||||||
import com.tangem.tap.features.wallet.models.PendingTransactionType
|
import com.tangem.tap.features.wallet.models.PendingTransactionType
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.features.wallet.redux.WalletData
|
|
||||||
import com.tangem.tap.features.wallet.redux.WalletMainButton
|
import com.tangem.tap.features.wallet.redux.WalletMainButton
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState
|
import com.tangem.tap.features.wallet.redux.WalletState
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.getAvailableActions
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.isAvailableToBuy
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.isAvailableToSell
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.mainButton
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.shouldShowMultipleAddress
|
||||||
import com.tangem.tap.features.wallet.ui.BalanceWidget
|
import com.tangem.tap.features.wallet.ui.BalanceWidget
|
||||||
import com.tangem.tap.features.wallet.ui.MultipleAddressUiHelper
|
import com.tangem.tap.features.wallet.ui.MultipleAddressUiHelper
|
||||||
import com.tangem.tap.features.wallet.ui.WalletFragment
|
import com.tangem.tap.features.wallet.ui.WalletFragment
|
||||||
|
|
@ -71,7 +76,7 @@ class SingleWalletView : WalletView() {
|
||||||
setupTwinCards(state.twinCardsState, binding)
|
setupTwinCards(state.twinCardsState, binding)
|
||||||
setupButtons(primaryWalletData, binding, state.isExchangeServiceFeatureOn)
|
setupButtons(primaryWalletData, binding, state.isExchangeServiceFeatureOn)
|
||||||
setupAddressCard(state, binding)
|
setupAddressCard(state, binding)
|
||||||
showPendingTransactionsIfPresent(primaryWalletData.pendingTransactions)
|
showPendingTransactionsIfPresent(primaryWalletData.status.pendingTransactions)
|
||||||
setupBalance(state, primaryWalletData)
|
setupBalance(state, primaryWalletData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,32 +88,30 @@ class SingleWalletView : WalletView() {
|
||||||
binding?.rvPendingTransaction?.show(knownTransactions.isNotEmpty())
|
binding?.rvPendingTransaction?.show(knownTransactions.isNotEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupBalance(state: WalletState, primaryWallet: WalletData) {
|
private fun setupBalance(state: WalletState, primaryWallet: WalletDataModel) {
|
||||||
val fragment = fragment ?: return
|
val fragment = fragment ?: return
|
||||||
binding?.apply {
|
binding?.apply {
|
||||||
lCardBalance.lBalance.root.show()
|
lCardBalance.lBalance.root.show()
|
||||||
BalanceWidget(
|
BalanceWidget(
|
||||||
binding = this.lCardBalance,
|
binding = this.lCardBalance,
|
||||||
fragment = fragment,
|
fragment = fragment,
|
||||||
data = primaryWallet.currencyData,
|
blockchainWalletData = primaryWallet,
|
||||||
token = state.primaryTokenData?.currencyData,
|
tokenWalletData = state.primaryTokenData,
|
||||||
isTwinCard = state.isTangemTwins,
|
|
||||||
).setup()
|
).setup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupTwinCards(twinCardsState: TwinCardsState?, binding: FragmentWalletBinding) = with(binding) {
|
private fun setupTwinCards(twinCardsState: TwinCardsState?, binding: FragmentWalletBinding) = with(binding) {
|
||||||
twinCardsState?.cardNumber?.let { cardNumber ->
|
|
||||||
tvTwinCardNumber.show()
|
|
||||||
tvTwinCardNumber.text = tvTwinCardNumber.getQuantityString(R.plurals.card_label_card_count, 2)
|
|
||||||
}
|
|
||||||
if (twinCardsState?.cardNumber == null) {
|
if (twinCardsState?.cardNumber == null) {
|
||||||
tvTwinCardNumber.hide()
|
tvTwinCardNumber.hide()
|
||||||
|
} else {
|
||||||
|
tvTwinCardNumber.show()
|
||||||
|
tvTwinCardNumber.text = tvTwinCardNumber.getQuantityString(R.plurals.card_label_card_count, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupButtons(
|
private fun setupButtons(
|
||||||
walletData: WalletData,
|
walletData: WalletDataModel,
|
||||||
binding: FragmentWalletBinding,
|
binding: FragmentWalletBinding,
|
||||||
isExchangeServiceFeatureEnabled: Boolean,
|
isExchangeServiceFeatureEnabled: Boolean,
|
||||||
) = with(binding) {
|
) = with(binding) {
|
||||||
|
|
@ -134,7 +137,7 @@ class SingleWalletView : WalletView() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupRowButtons(
|
private fun setupRowButtons(
|
||||||
walletData: WalletData,
|
walletData: WalletDataModel,
|
||||||
rowButtons: WalletDetailsButtonsRow,
|
rowButtons: WalletDetailsButtonsRow,
|
||||||
isExchangeServiceFeatureEnabled: Boolean,
|
isExchangeServiceFeatureEnabled: Boolean,
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,15 @@ import com.tangem.tap.common.ShimmerData
|
||||||
import com.tangem.tap.common.ShimmerRecyclerAdapter
|
import com.tangem.tap.common.ShimmerRecyclerAdapter
|
||||||
import com.tangem.tap.common.analytics.events.MainScreen
|
import com.tangem.tap.common.analytics.events.MainScreen
|
||||||
import com.tangem.tap.common.extensions.animateVisibility
|
import com.tangem.tap.common.extensions.animateVisibility
|
||||||
import com.tangem.tap.common.extensions.formatAmountAsSpannedString
|
|
||||||
import com.tangem.tap.common.extensions.hide
|
import com.tangem.tap.common.extensions.hide
|
||||||
import com.tangem.tap.common.extensions.show
|
import com.tangem.tap.common.extensions.show
|
||||||
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
|
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
|
||||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState
|
import com.tangem.tap.features.wallet.redux.WalletState
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||||
|
import com.tangem.tap.features.wallet.ui.utils.isAvailableToBuy
|
||||||
import com.tangem.tap.features.wallet.ui.WalletFragment
|
import com.tangem.tap.features.wallet.ui.WalletFragment
|
||||||
import com.tangem.tap.features.wallet.ui.wallet.WalletView
|
import com.tangem.tap.features.wallet.ui.wallet.WalletView
|
||||||
import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.HistoryItemData
|
import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.HistoryItemData
|
||||||
|
|
@ -124,16 +126,14 @@ class SaltPayWalletView : WalletView() {
|
||||||
tvUnreachable.animateVisibility(show = mainProgressState == ProgressState.Error)
|
tvUnreachable.animateVisibility(show = mainProgressState == ProgressState.Error)
|
||||||
veilBalanceCrypto.animateVisibility(show = mainProgressState != ProgressState.Error)
|
veilBalanceCrypto.animateVisibility(show = mainProgressState != ProgressState.Error)
|
||||||
|
|
||||||
if (tokenData.currencyData.fiatAmount == null) {
|
if (tokenData.fiatRate == null) {
|
||||||
veilBalance.veil()
|
veilBalance.veil()
|
||||||
} else {
|
} else {
|
||||||
veilBalance.unVeil()
|
veilBalance.unVeil()
|
||||||
tvBalance.text = tokenData.currencyData.fiatAmount.formatAmountAsSpannedString(
|
tvBalance.text = tokenData.getFormattedFiatAmount(appCurrency)
|
||||||
currencySymbol = appCurrency.symbol,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tvBalanceCrypto.text = tokenData.currencyData.amountFormatted
|
tvBalanceCrypto.text = tokenData.getFormattedAmount()
|
||||||
|
|
||||||
tvCurrencyName.text = appCurrency.code
|
tvCurrencyName.text = appCurrency.code
|
||||||
tvCurrencyName.setOnClickListener {
|
tvCurrencyName.setOnClickListener {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package com.tangem.tap.features.walletSelector.ui
|
||||||
import com.tangem.tap.common.entities.FiatCurrency
|
import com.tangem.tap.common.entities.FiatCurrency
|
||||||
import com.tangem.tap.common.extensions.toFormattedFiatValue
|
import com.tangem.tap.common.extensions.toFormattedFiatValue
|
||||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||||
import com.tangem.tap.features.walletSelector.redux.UserWalletModel
|
import com.tangem.tap.features.walletSelector.redux.UserWalletModel
|
||||||
import com.tangem.tap.features.walletSelector.ui.model.MultiCurrencyUserWalletItem
|
import com.tangem.tap.features.walletSelector.ui.model.MultiCurrencyUserWalletItem
|
||||||
import com.tangem.tap.features.walletSelector.ui.model.SingleCurrencyUserWalletItem
|
import com.tangem.tap.features.walletSelector.ui.model.SingleCurrencyUserWalletItem
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue