From 293c932422ecac74dc3cb1bda00b2c6efbd65b91 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 May 2021 10:27:46 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/tap/common/extensions/Specific.kt | 11 ++- .../com/tangem/tap/domain/TapWalletManager.kt | 26 +++-- .../com/tangem/tap/domain/extensions/Card.kt | 5 +- .../send/redux/middlewares/SendMiddleware.kt | 4 +- .../features/tokens/redux/TokensReducer.kt | 15 ++- .../tap/features/tokens/redux/TokensState.kt | 3 +- .../tokens/ui/adapters/CurrenciesAdapter.kt | 66 ++++++++----- .../tap/features/wallet/redux/WalletAction.kt | 10 +- .../tap/features/wallet/redux/WalletState.kt | 99 +++++++++++++------ .../middlewares/MultiWalletMiddleware.kt | 47 ++++++--- .../redux/middlewares/WalletMiddleware.kt | 68 ++++++------- .../redux/reducers/MultiWalletReducer.kt | 60 ++++++----- .../redux/reducers/OnWalletLoadedReducer.kt | 27 ++--- .../wallet/redux/reducers/WalletReducer.kt | 79 +++++++-------- .../tap/features/wallet/ui/BalanceWidget.kt | 20 ++-- .../wallet/ui/WalletDetailsFragment.kt | 28 +++--- .../tap/features/wallet/ui/WalletFragment.kt | 1 + .../wallet/ui/adapters/WalletAdapter.kt | 23 ++--- .../wallet/ui/wallet/SingleWalletView.kt | 4 +- build.gradle | 1 - dependencies.gradle | 2 +- 21 files changed, 357 insertions(+), 242 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt index 8ed277a345..f97a4cd062 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt @@ -26,12 +26,21 @@ fun BigDecimal.toFormattedCurrencyString(decimals: Int, currency: String): Strin return "${this.toFormattedString(decimals)} $currency" } -fun BigDecimal.toFiatString(rateValue: BigDecimal, fiatCurrencyName: FiatCurrencyName): String? { +fun BigDecimal.toFiatString(rateValue: BigDecimal, fiatCurrencyName: FiatCurrencyName): String { var fiatValue = rateValue.multiply(this) fiatValue = fiatValue.setScale(2, RoundingMode.DOWN) return "≈ ${fiatCurrencyName}  $fiatValue" } +fun BigDecimal.toFiatValue(rateValue: BigDecimal): BigDecimal { + val fiatValue = rateValue.multiply(this) + return fiatValue.setScale(2, RoundingMode.DOWN) +} + +fun BigDecimal.toFormattedFiatValue(fiatCurrencyName: FiatCurrencyName): String { + return "≈ ${fiatCurrencyName}  $this" +} + fun FiatCurrency.toFormattedString(): String = "${this.name} (${this.symbol}) - ${this.sign}" fun BigDecimal.stripZeroPlainString(): String = this.stripTrailingZeros().toPlainString() diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index f939f5aaa9..4e7d1f84b4 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -17,12 +17,14 @@ import com.tangem.tap.domain.tokens.CardCurrencies import com.tangem.tap.domain.twins.TwinsHelper import com.tangem.tap.domain.twins.isTwinCard import com.tangem.tap.features.tokens.redux.TokensAction +import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.network.NetworkConnectivity import com.tangem.tap.network.coinmarketcap.CoinMarketCapService import com.tangem.tap.store import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import timber.log.Timber import java.math.BigDecimal @@ -64,19 +66,23 @@ class TapWalletManager { } suspend fun loadFiatRate(fiatCurrency: FiatCurrencyName, wallet: Wallet) { - val currencyList = wallet.getTokens().map { it.symbol }.toMutableList() - currencyList.add(wallet.blockchain.currency) - loadFiatRate(fiatCurrency, currencyList) + Timber.d(wallet.getTokens().toString()) + val currencies = wallet.getTokens() + .map { Currency.Token(it, wallet.blockchain) } + .plus(Currency.Blockchain(wallet.blockchain)) + loadFiatRate(fiatCurrency, currencies) } - suspend fun loadFiatRate(fiatCurrency: FiatCurrencyName, cryptoCurrencyName: CryptoCurrencyName) { - val currencyList = listOf(cryptoCurrencyName) - loadFiatRate(fiatCurrency, currencyList) + suspend fun loadFiatRate(fiatCurrency: FiatCurrencyName, currency: Currency) { + val currencies = listOf(currency) + loadFiatRate(fiatCurrency, currencies) } - private suspend fun loadFiatRate(fiatCurrency: FiatCurrencyName, currencyList: List) { - val results = mutableListOf?>>() - currencyList.forEach { results.add(it to coinMarketCapService.getRate(it, fiatCurrency)) } + suspend fun loadFiatRate(fiatCurrency: FiatCurrencyName, currencies: List) { + val results = mutableListOf?>>() + currencies.forEach { + results.add(it to coinMarketCapService.getRate(it.currencySymbol, fiatCurrency)) + } handleFiatRatesResult(results) } @@ -268,7 +274,7 @@ class TapWalletManager { } } - private suspend fun handleFiatRatesResult(results: List?>>) { + private suspend fun handleFiatRatesResult(results: List?>>) { withContext(Dispatchers.Main) { results.map { when (it.second) { diff --git a/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt b/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt index eb60189b4f..99e2cba747 100644 --- a/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt +++ b/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt @@ -44,4 +44,7 @@ fun Card.signedHashesCount(): Int { } val Card.remainingSignatures: Int? - get() = this.getSingleWallet()?.remainingSignatures \ No newline at end of file + get() = this.getSingleWallet()?.remainingSignatures + +val Card.isWalletDataSupported: Boolean + get() = this.firmwareVersion.major >= 4 \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt index 495209fb5b..6ad9802785 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt @@ -134,11 +134,11 @@ private fun sendTransaction( dispatch(NavigationAction.PopBackTo()) scope.launch(Dispatchers.IO) { withContext(Dispatchers.Main) { - dispatch(WalletAction.UpdateWallet(walletManager.wallet.blockchain.currency)) + dispatch(WalletAction.UpdateWallet(walletManager.wallet.blockchain)) } delay(10000) withContext(Dispatchers.Main) { - dispatch(WalletAction.UpdateWallet(walletManager.wallet.blockchain.currency)) + dispatch(WalletAction.UpdateWallet(walletManager.wallet.blockchain)) } } } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt index e0c5600ad1..be4a64b61e 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt @@ -1,6 +1,9 @@ package com.tangem.tap.features.tokens.redux import com.tangem.tap.common.redux.AppState +import com.tangem.tap.domain.tokens.CardCurrencies +import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.redux.WalletData import org.rekotlin.Action class TokensReducer { @@ -18,13 +21,21 @@ private fun internalReduce(action: Action, state: AppState): TokensState { tokensState.copy(currencies = action.currencies) } is TokensAction.SetAddedCurrencies -> { - tokensState.copy(addedCurrencies = action.wallets.mapNotNull { it.currencyData.currencySymbol }) + + + tokensState.copy(addedCurrencies = action.wallets.toCardCurrencies()) } is TokensAction.LoadCardTokens.Success -> { tokensState.copy(addedTokens = LinkedHashSet( - action.tokens.map { TokenWithAmount(it, null) } + action.tokens.map { TokenWithAmount(it, null) } )) } else -> tokensState } +} + +private fun List.toCardCurrencies(): CardCurrencies { + val tokens = mapNotNull { (it.currency as? Currency.Token)?.token } + val blockchains = mapNotNull { (it.currency as? Currency.Blockchain)?.blockchain } + return CardCurrencies(tokens = tokens, blockchains = blockchains) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt index 5169e63b96..b3d528fe5f 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt @@ -3,12 +3,13 @@ package com.tangem.tap.features.tokens.redux import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.Token import com.tangem.tap.common.redux.global.CryptoCurrencyName +import com.tangem.tap.domain.tokens.CardCurrencies import com.tangem.tap.features.tokens.ui.adapters.CurrencyListItem import org.rekotlin.StateType data class TokensState( val addedTokens: LinkedHashSet = LinkedHashSet(), - val addedCurrencies: List = emptyList(), + val addedCurrencies: CardCurrencies? = null, val currencies: List = emptyList(), ) : StateType diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt index 0047481627..1905ae9d96 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt @@ -14,6 +14,7 @@ import com.tangem.blockchain.common.IconsUtil import com.tangem.blockchain.common.Token import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.global.CryptoCurrencyName +import com.tangem.tap.domain.tokens.CardCurrencies import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.store import com.tangem.wallet.R @@ -24,7 +25,7 @@ import java.util.* class CurrenciesAdapter : ListAdapter(DiffUtilCallback) { - var addedCurrencies: List = emptyList() + var addedCurrencies: CardCurrencies? = null private var unfilteredList = listOf() @@ -42,12 +43,18 @@ class CurrenciesAdapter : ListAdapter override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { - 0 -> TitleViewHolder(LayoutInflater.from(parent.context) - .inflate(R.layout.item_currency_subtitle, parent, false)) - 1 -> CurrenciesViewHolder(LayoutInflater.from(parent.context) - .inflate(R.layout.item_popular_token, parent, false)) - else -> CurrenciesViewHolder(LayoutInflater.from(parent.context) - .inflate(R.layout.item_popular_token, parent, false)) + 0 -> TitleViewHolder( + LayoutInflater.from(parent.context) + .inflate(R.layout.item_currency_subtitle, parent, false) + ) + 1 -> CurrenciesViewHolder( + LayoutInflater.from(parent.context) + .inflate(R.layout.item_popular_token, parent, false) + ) + else -> CurrenciesViewHolder( + LayoutInflater.from(parent.context) + .inflate(R.layout.item_popular_token, parent, false) + ) } } @@ -62,11 +69,11 @@ class CurrenciesAdapter : ListAdapter object DiffUtilCallback : DiffUtil.ItemCallback() { override fun areContentsTheSame( - oldItem: CurrencyListItem, newItem: CurrencyListItem + oldItem: CurrencyListItem, newItem: CurrencyListItem ) = oldItem == newItem override fun areItemsTheSame( - oldItem: CurrencyListItem, newItem: CurrencyListItem + oldItem: CurrencyListItem, newItem: CurrencyListItem ) = oldItem == newItem } @@ -76,20 +83,23 @@ class CurrenciesAdapter : ListAdapter if (!query.isNullOrEmpty()) { val queryNormalized = query.toString().toLowerCase(Locale.US) list.addAll( - unfilteredList.filter { element -> - when (element) { - is CurrencyListItem.BlockchainListItem -> { - element.blockchain.currency.toLowerCase(Locale.US).contains(queryNormalized) - || element.blockchain.fullName.toLowerCase(Locale.US).contains(queryNormalized) + unfilteredList.filter { element -> + when (element) { + is CurrencyListItem.BlockchainListItem -> { + element.blockchain.currency.toLowerCase(Locale.US) + .contains(queryNormalized) + || element.blockchain.fullName.toLowerCase(Locale.US) + .contains(queryNormalized) - } - is CurrencyListItem.TokenListItem -> { - element.token.name.toLowerCase(Locale.US).contains(queryNormalized) - || element.token.symbol.toLowerCase(Locale.US).contains(queryNormalized) - } - else -> false } - }) + is CurrencyListItem.TokenListItem -> { + element.token.name.toLowerCase(Locale.US).contains(queryNormalized) + || element.token.symbol.toLowerCase(Locale.US) + .contains(queryNormalized) + } + else -> false + } + }) } else { list.addAll(unfilteredList) } @@ -97,14 +107,14 @@ class CurrenciesAdapter : ListAdapter } class CurrenciesViewHolder(val view: View) : - RecyclerView.ViewHolder(view) { - fun bind(currency: CurrencyListItem, addedCurrencies: List) { + RecyclerView.ViewHolder(view) { + fun bind(currency: CurrencyListItem, addedCurrencies: CardCurrencies?) { when (currency) { is CurrencyListItem.BlockchainListItem -> { val blockchain = currency.blockchain view.tv_currency_name.text = blockchain.fullName view.tv_currency_symbol.text = blockchain.currency - val isAdded = addedCurrencies.any { it == blockchain.currency } + val isAdded = addedCurrencies?.blockchains?.contains(blockchain) == true view.btn_add_token.show(!isAdded) view.btn_token_added.show(isAdded) @@ -125,7 +135,11 @@ class CurrenciesAdapter : ListAdapter view.tv_currency_name.text = token.name view.tv_currency_symbol.text = token.symbol - val isAdded = addedCurrencies.any { it == token.symbol } + val isAdded = addedCurrencies?.tokens + ?.any { + it.symbol == token.symbol && it.contractAddress == token.contractAddress + } == true + view.btn_add_token.show(!isAdded) view.btn_token_added.show(isAdded) @@ -145,7 +159,7 @@ class CurrenciesAdapter : ListAdapter } class TitleViewHolder(val view: View) : - RecyclerView.ViewHolder(view) { + RecyclerView.ViewHolder(view) { fun bind(title: CurrencyListItem.TitleListItem) { view.tv_subtitle.text = view.getString(title.titleResId).toUpperCase(Locale.US) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index 405e96be66..ebfadb5df3 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -24,7 +24,7 @@ sealed class WalletAction : Action { } - data class LoadWallet(val allowTopUp: Boolean? = null, val currency: CryptoCurrencyName? = null) : WalletAction() { + data class LoadWallet(val allowTopUp: Boolean? = null, val blockchain: Blockchain? = null) : WalletAction() { data class Success(val wallet: Wallet) : WalletAction() data class NoAccount(val wallet: Wallet, val amountToCreateAccount: String) : WalletAction() data class Failure(val wallet: Wallet, val errorMessage: String? = null) : WalletAction() @@ -45,7 +45,7 @@ sealed class WalletAction : Action { data class SaveCurrencies(val cardCurrencies: CardCurrencies) : MultiWallet() object FindTokensInUse : MultiWallet() data class FindBlockchainsInUse(val card: Card, val factory: WalletManagerFactory) : MultiWallet() - data class TokenLoaded(val amount: Amount) : MultiWallet() + data class TokenLoaded(val amount: Amount, val token: Token) : MultiWallet() data class SelectWallet(val walletData: WalletData?) : MultiWallet() data class RemoveWallet(val walletData: WalletData) : MultiWallet() data class SetPrimaryBlockchain(val blockchain: Blockchain) : MultiWallet() @@ -71,16 +71,16 @@ sealed class WalletAction : Action { class CheckRemainingSignatures(val remainingSignatures: Int?) : Warnings() } - data class UpdateWallet(val currency: CryptoCurrencyName? = null) : WalletAction() { + data class UpdateWallet(val blockchain: Blockchain? = null) : WalletAction() { object ScheduleUpdatingWallet : WalletAction() data class Success(val wallet: Wallet) : WalletAction() data class Failure(val errorMessage: String? = null) : WalletAction() } data class LoadFiatRate( - val wallet: Wallet? = null, val currency: CryptoCurrencyName? = null + val wallet: Wallet? = null, val currency: Currency? = null ) : WalletAction() { - data class Success(val fiatRate: Pair) : WalletAction() + data class Success(val fiatRate: Pair) : WalletAction() object Failure : WalletAction() } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 62de9a0a68..1b2a1aa4b0 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -30,13 +30,12 @@ data class WalletState( val walletManagers: List = emptyList(), val isMultiwalletAllowed: Boolean = false, val cardCurrency: CryptoCurrencyName? = null, - val selectedWallet: CryptoCurrencyName? = null, + val selectedWallet: Currency? = null, val primaryBlockchain: Blockchain? = null, val primaryToken: Token? = null ) : StateType { val primaryWallet = if (wallets.isNotEmpty()) wallets[0] else null -// val primaryWalletManager = if (walletManagers.isNotEmpty()) walletManagers[0] else null val shouldShowDetails: Boolean = primaryWallet?.currencyData?.status != com.tangem.tap.features.wallet.ui.BalanceStatus.EmptyCard && @@ -45,19 +44,14 @@ data class WalletState( val blockchains: List get() = walletManagers.map { it.wallet.blockchain } - fun getWalletManager(currencyName: CryptoCurrencyName?): WalletManager? { - if (currencyName == null) return null - val walletManager = walletManagers.find { it.wallet.blockchain.currency == currencyName } - return walletManager ?: getWalletManagerForToken(currencyName) - } - - fun getWalletManagerForToken(currencyName: CryptoCurrencyName?): WalletManager? { + fun getWalletManager(token: Token?): WalletManager? { + if (token == null) return null val ethereumWalletManager = walletManagers.find { it.wallet.blockchain == Blockchain.Ethereum } - return if (ethereumWalletManager?.presetTokens?.find { it.symbol == currencyName } != null) { + return if (ethereumWalletManager?.presetTokens?.find { it == token } != null) { ethereumWalletManager } else { val primaryWalletManager = walletManagers.find { it.wallet.blockchain == primaryBlockchain } - if (primaryWalletManager?.presetTokens?.find { it.symbol == currencyName } != null) { + if (primaryWalletManager?.presetTokens?.find { it == token } != null) { primaryWalletManager } else { ethereumWalletManager @@ -65,38 +59,69 @@ data class WalletState( } } - fun getWalletData(currencyName: CryptoCurrencyName?): WalletData? { - if (currencyName == null) return null - return wallets.find { it.currencyData.currencySymbol == currencyName } + fun getWalletManager(currency: Currency?) : WalletManager? { + if (currency?.blockchain == null) return null + return walletManagers.find { it.wallet.blockchain == currency.blockchain } + } + + fun getWalletManager(blockchain: Blockchain) : WalletManager? { + return walletManagers.find { it.wallet.blockchain == blockchain } + } + + fun getWalletData(currency: Currency?) : WalletData? { + if (currency == null) return null + return wallets.find { it.currency == currency } + } + + fun getWalletData(blockchain: Blockchain?): WalletData? { + if (blockchain == null) return null + return wallets.find { (it.currency as? Currency.Blockchain)?.blockchain == blockchain } + } + + fun getWalletData(token: Token?): WalletData? { + if (token == null) return null + return wallets.find { (it.currency as? Currency.Token)?.token == token } } fun getSelectedWalletData(): WalletData? { - return wallets.find { it.currencyData.currencySymbol == selectedWallet } + return wallets.find { it.currency == selectedWallet } } fun canBeRemoved(walletData: WalletData?): Boolean { if (walletData == null) return false - if (walletData.blockchain != store.state.walletState.primaryBlockchain - && (walletData.token == null || walletData.token != store.state.walletState.primaryToken)) { - val walletManager = getWalletManager(walletData.currencyData.currencySymbol) + if (!isPrimaryCurrency(walletData)) { + val walletManager = getWalletManager(walletData.currency) ?: return true - if (walletData.token == null && walletManager.presetTokens.isNotEmpty()) return false + if (walletData.currency is Currency.Blockchain && + walletManager.presetTokens.isNotEmpty() + ) { + return false + } val wallet = walletManager.wallet - if (walletData.blockchain != null) { + + if (walletData.currency is Currency.Blockchain) { return wallet.recentTransactions.toPendingTransactions(wallet.address).isEmpty() && wallet.amounts.toSendableAmounts().isEmpty() - } else if (walletData.token != null) ( + } else if (walletData.currency is Currency.Token) ( return wallet.recentTransactions.toPendingTransactionsForToken( - walletData.token, wallet.address).isEmpty() - && wallet.amounts[AmountType.Token(token = walletData.token)]?.isAboveZero() != true + walletData.currency.token, wallet.address).isEmpty() + && wallet.amounts[AmountType.Token(token = walletData.currency.token)] + ?.isAboveZero() != true ) } return false } + private fun isPrimaryCurrency(walletData: WalletData): Boolean { + return (walletData.currency is Currency.Blockchain && + walletData.currency.blockchain == store.state.walletState.primaryBlockchain) + || (walletData.currency is Currency.Token && + walletData.currency.token == store.state.walletState.primaryToken) + } + fun replaceWalletInWallets(walletData: WalletData?): List { if (walletData == null) return wallets return wallets.filter { it.currencyData.currency != walletData.currencyData.currency } + walletData @@ -180,14 +205,32 @@ data class WalletData( val fiatRateString: String? = null, val fiatRate: BigDecimal? = null, val mainButton: WalletMainButton = WalletMainButton.SendButton(false), - val token: Token? = null, - val blockchain: Blockchain? = null, + val currency: Currency? = null ) { fun shouldShowMultipleAddress(): Boolean { val listOfAddresses = walletAddresses?.list ?: return false - return (currencyData.currencySymbol == Blockchain.Bitcoin.currency || - currencyData.currencySymbol == Blockchain.BitcoinTestnet.currency || - currencyData.currencySymbol == Blockchain.CardanoShelley.currency) && + return (currency?.blockchain == Blockchain.Bitcoin || + currency?.blockchain == Blockchain.BitcoinTestnet || + currency?.blockchain == Blockchain.CardanoShelley) && listOfAddresses.size > 1 } +} + +sealed interface Currency { + + val blockchain: com.tangem.blockchain.common.Blockchain + val currencySymbol: CryptoCurrencyName + + data class Token( + val token: com.tangem.blockchain.common.Token, + override val blockchain: com.tangem.blockchain.common.Blockchain + ) : Currency { + override val currencySymbol: CryptoCurrencyName = token.symbol + } + + data class Blockchain( + override val blockchain: com.tangem.blockchain.common.Blockchain + ) : Currency { + override val currencySymbol: CryptoCurrencyName = blockchain.currency + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index 01190d3b5e..55d93ffecd 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -12,6 +12,7 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.currenciesRepository import com.tangem.tap.domain.extensions.makeWalletManagerForApp import com.tangem.tap.domain.extensions.makeWalletManagersForApp +import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.scope @@ -52,8 +53,8 @@ class MultiWalletMiddleware { store.dispatch(WalletAction.MultiWallet.AddWalletManagers(it)) } } - store.dispatch(WalletAction.LoadFiatRate(currency = action.blockchain.currency)) - store.dispatch(WalletAction.LoadWallet(currency = action.blockchain.currency)) + store.dispatch(WalletAction.LoadFiatRate(currency = Currency.Blockchain(action.blockchain))) + store.dispatch(WalletAction.LoadWallet(blockchain = action.blockchain)) } is WalletAction.MultiWallet.SaveCurrencies -> { val cardId = globalState?.scanNoteResponse?.card?.cardId @@ -61,12 +62,15 @@ class MultiWalletMiddleware { } is WalletAction.MultiWallet.RemoveWallet -> { val cardId = globalState?.scanNoteResponse?.card?.cardId - if (action.walletData.token != null) { - walletState?.getWalletManagerForToken(action.walletData.token.symbol) - ?.removeToken(action.walletData.token) - cardId?.let { currenciesRepository.removeToken(it, action.walletData.token) } - } else if (action.walletData.blockchain != null) { - cardId?.let { currenciesRepository.removeBlockchain(it, action.walletData.blockchain) } + when (val currency = action.walletData.currency) { + is Currency.Blockchain -> { + cardId?.let { currenciesRepository.removeBlockchain(it, currency.blockchain) } + } + is Currency.Token -> { + walletState?.getWalletManager(currency.token) + ?.removeToken(currency.token) + cardId?.let { currenciesRepository.removeToken(it, currency.token) } + } } } is WalletAction.MultiWallet.FindBlockchainsInUse -> { @@ -83,7 +87,7 @@ class MultiWalletMiddleware { val wallet = walletManager.wallet val coinAmount = wallet.amounts[AmountType.Coin]?.value if (coinAmount != null && !coinAmount.isZero()) { - if (walletState?.getWalletData(wallet.blockchain.currency) == null) { + if (walletState?.getWalletData(wallet.blockchain) == null) { scope.launch(Dispatchers.Main) { store.dispatch(WalletAction.MultiWallet.AddWalletManagers( listOfNotNull(walletManager))) @@ -101,7 +105,7 @@ class MultiWalletMiddleware { } } is WalletAction.MultiWallet.FindTokensInUse -> { - val walletManager = walletState?.getWalletManager(Blockchain.Ethereum.currency) + val walletManager = walletState?.getWalletManager(Blockchain.Ethereum) ?: return val tokenFinder = walletManager as TokenFinder scope.launch { @@ -124,21 +128,34 @@ class MultiWalletMiddleware { private fun addToken(token: Token, walletState: WalletState?, globalState: GlobalState?) { val card = globalState?.scanNoteResponse?.card ?: return - val walletManager = walletState?.getWalletManager(token.symbol) ?: - globalState.tapWalletManager.walletManagerFactory.makeWalletManagerForApp( + val walletManager = walletState?.getWalletManager(token) + ?: globalState.tapWalletManager.walletManagerFactory.makeWalletManagerForApp( card = card, blockchain = Blockchain.Ethereum - )?.also { walletManager -> + )?.also { walletManager -> store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManager)) store.dispatch(WalletAction.MultiWallet.AddBlockchain(walletManager.wallet.blockchain)) } + + store.dispatch( + WalletAction.LoadFiatRate( + currency = Currency.Token( + token = token, + blockchain = walletManager?.wallet?.blockchain ?: Blockchain.Ethereum + ) + ) + ) + scope.launch { val result = walletManager?.addToken(token) withContext(Dispatchers.Main) { when (result) { is Result.Success -> { - store.dispatch(WalletAction.LoadFiatRate(currency = token.symbol)) - store.dispatch(WalletAction.MultiWallet.TokenLoaded(result.data)) + store.dispatch( + WalletAction.MultiWallet.TokenLoaded( + amount = result.data, token = token + ) + ) } } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index e11a577a51..183d55ddda 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -19,10 +19,7 @@ import com.tangem.tap.domain.twins.TwinsHelper import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.twins.CreateTwinWallet import com.tangem.tap.features.send.redux.PrepareSendScreen -import com.tangem.tap.features.wallet.redux.ProgressState -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.* import com.tangem.tap.network.NetworkStateChanged import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -49,12 +46,12 @@ class WalletMiddleware { is WalletAction.LoadWallet -> { scope.launch { - if (action.currency == null) { + if (action.blockchain == null) { walletState?.walletManagers?.map { walletManager -> globalState?.tapWalletManager?.loadWalletData(walletManager) } } else { - val walletManager = walletState?.getWalletManager(action.currency) + val walletManager = walletState?.getWalletManager(action.blockchain) walletManager?.let { globalState?.tapWalletManager?.loadWalletData(it) } } } @@ -62,7 +59,7 @@ class WalletMiddleware { is WalletAction.LoadWallet.Success -> { val coinAmount = action.wallet.amounts[AmountType.Coin]?.value if (coinAmount != null && !coinAmount.isZero()) { - if (walletState?.getWalletData(action.wallet.blockchain.currency) == null) { + if (walletState?.getWalletData(action.wallet.blockchain) == null) { store.dispatch(WalletAction.MultiWallet.AddBlockchain(action.wallet.blockchain)) store.dispatch(WalletAction.LoadWallet.Success(action.wallet)) } @@ -72,24 +69,24 @@ class WalletMiddleware { } is WalletAction.LoadFiatRate -> { scope.launch { - if (action.wallet != null) { - globalState?.tapWalletManager?.loadFiatRate( + when { + action.wallet != null -> { + globalState?.tapWalletManager?.loadFiatRate( globalState.appCurrency, action.wallet - ) - } else if (action.currency != null) { - globalState?.tapWalletManager?.loadFiatRate( + ) + } + action.currency != null -> { + globalState?.tapWalletManager?.loadFiatRate( globalState.appCurrency, action.currency - ) - } else { - walletState?.wallets?.filter { it.blockchain != null } - ?.map { walletState.getWalletManager(it.blockchain?.currency) } - ?.mapNotNull { walletManager -> - walletManager?.let { - globalState?.tapWalletManager?.loadFiatRate( - globalState.appCurrency, walletManager.wallet - ) - } - } + ) + } + else -> { + globalState?.tapWalletManager?.loadFiatRate( + fiatCurrency = globalState.appCurrency, + currencies = walletState?.wallets?.mapNotNull { it.currency } + ?: emptyList() + ) + } } } } @@ -119,9 +116,9 @@ class WalletMiddleware { } } is WalletAction.UpdateWallet -> { - if (action.currency != null) { + if (action.blockchain != null) { scope.launch { - val walletManager = walletState?.getWalletManager(action.currency) + val walletManager = walletState?.getWalletManager(action.blockchain) walletManager?.let { globalState?.tapWalletManager?.updateWallet(it) } } } else { @@ -195,7 +192,7 @@ class WalletMiddleware { private fun prepareSendAction(amount: Amount?, state: WalletState?): Action { val selectedWalletData = state?.getSelectedWalletData() - val currency = selectedWalletData?.currencyData?.currencySymbol + val currency = selectedWalletData?.currency val walletManager = state?.getWalletManager(currency) val wallet = walletManager?.wallet @@ -208,12 +205,17 @@ class WalletMiddleware { } else { val amounts = wallet?.amounts?.toSendableAmounts() if (currency != null && state.isMultiwalletAllowed) { - val amountToSend = amounts?.find { it.currencySymbol == currency } - ?: return WalletAction.Send.ChooseCurrency(amounts) - if (amountToSend.type is AmountType.Token) { - prepareSendActionForToken(amountToSend, state, selectedWalletData, wallet, walletManager) - } else { - PrepareSendScreen(amountToSend, selectedWalletData.fiatRate, walletManager) + when (currency) { + is Currency.Blockchain -> { + val amountToSend = amounts?.find { it.currencySymbol == currency.blockchain.currency } + ?: return WalletAction.Send.ChooseCurrency(amounts) + PrepareSendScreen(amountToSend, selectedWalletData.fiatRate, walletManager) + } + is Currency.Token -> { + val amountToSend = amounts?.find { it.currencySymbol == currency.token.symbol } + ?: return WalletAction.Send.ChooseCurrency(amounts) + prepareSendActionForToken(amountToSend, state, selectedWalletData, wallet, walletManager) + } } } else { if (amounts?.size ?: 0 > 1) { @@ -230,7 +232,7 @@ class WalletMiddleware { amount: Amount, state: WalletState?, selectedWalletData: WalletData?, wallet: Wallet?, walletManager: WalletManager? ): PrepareSendScreen { - val coinRate = state?.getWalletData(wallet?.blockchain?.currency)?.fiatRate + val coinRate = state?.getWalletData(wallet?.blockchain)?.fiatRate val tokenRate = if (state?.isMultiwalletAllowed == true) { selectedWalletData?.fiatRate } else { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt index 158d7e61ff..8c45a9b8c3 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.wallet.redux.reducers import com.tangem.blockchain.common.AmountType +import com.tangem.blockchain.common.Blockchain import com.tangem.common.extensions.isZero import com.tangem.tap.common.extensions.toFiatString import com.tangem.tap.common.extensions.toFormattedCurrencyString @@ -18,12 +19,12 @@ class MultiWalletReducer { return when (action) { is WalletAction.MultiWallet.AddWalletManagers -> { state.copy( - walletManagers = state.walletManagers + action.walletManagers + walletManagers = state.walletManagers + action.walletManagers ) } is WalletAction.MultiWallet.AddBlockchains -> { val wallets = action.blockchains.map { blockchain -> - val wallet = state.getWalletManager(blockchain.currency)?.wallet + val wallet = state.getWalletManager(blockchain)?.wallet val cardToken = if (!state.isMultiwalletAllowed) { wallet?.getFirstToken()?.symbol?.let { TokenData("", tokenSymbol = it) } } else { @@ -39,12 +40,12 @@ class MultiWalletReducer { walletAddresses = createAddressList(wallet), mainButton = WalletMainButton.SendButton(false), topUpState = TopUpState(allowed = false), - blockchain = blockchain + currency = Currency.Blockchain(blockchain) ) } val selectedWallet = if (!state.isMultiwalletAllowed) { - wallets[0].currencyData.currencySymbol + wallets[0].currency } else { state.selectedWallet } @@ -54,7 +55,7 @@ class MultiWalletReducer { ) } is WalletAction.MultiWallet.AddBlockchain -> { - val wallet = state.getWalletManager(action.blockchain.currency)?.wallet + val wallet = state.getWalletManager(action.blockchain)?.wallet val walletData = WalletData( currencyData = BalanceWidgetData( BalanceStatus.Loading, @@ -64,7 +65,7 @@ class MultiWalletReducer { walletAddresses = createAddressList(wallet), mainButton = WalletMainButton.SendButton(false), topUpState = TopUpState(allowed = false), - blockchain = action.blockchain + currency = Currency.Blockchain(action.blockchain) ) val newState = state.copy(wallets = state.replaceWalletInWallets(walletData)) if (wallet != null && wallet.amounts[AmountType.Coin]?.value != null) { @@ -76,29 +77,29 @@ class MultiWalletReducer { is WalletAction.MultiWallet.AddTokens -> { if (!state.isMultiwalletAllowed) return state val wallets = action.tokens.map { token -> + val walletManager = state.getWalletManager(token)?.wallet WalletData( currencyData = BalanceWidgetData( BalanceStatus.Loading, currency = token.name, currencySymbol = token.symbol ), - walletAddresses = createAddressList( - state.getWalletManagerForToken(token.symbol)?.wallet - ), + walletAddresses = createAddressList(walletManager), mainButton = WalletMainButton.SendButton(false), topUpState = TopUpState(allowed = false), - token = token + currency = Currency.Token( + token = token, + blockchain = walletManager?.blockchain ?: Blockchain.Ethereum + ) ) } state.copy(wallets = state.replaceSomeWallets(wallets)) } is WalletAction.MultiWallet.AddToken -> { if (!state.isMultiwalletAllowed) return state + val walletManager = state.getWalletManager(action.token)?.wallet + val walletAddresses = createAddressList(walletManager) - val walletAddresses = createAddressList( - state.getWalletManagerForToken(action.token.symbol)?.wallet - - ) val wallet = WalletData( currencyData = BalanceWidgetData( BalanceStatus.Loading, @@ -108,13 +109,16 @@ class MultiWalletReducer { walletAddresses = walletAddresses, mainButton = WalletMainButton.SendButton(false), topUpState = TopUpState(allowed = false), - token = action.token + currency = Currency.Token( + token = action.token, + blockchain = walletManager?.blockchain ?: Blockchain.Ethereum + ) ) val wallets = state.replaceWalletInWallets(wallet) state.copy(wallets = wallets) } is WalletAction.MultiWallet.TokenLoaded -> { - val pendingTransactions = state.getWalletManagerForToken(action.amount.currencySymbol) + val pendingTransactions = state.getWalletManager(action.token) ?.wallet?.let { wallet -> wallet.recentTransactions.toPendingTransactions(wallet.address) } ?: emptyList() @@ -127,14 +131,14 @@ class MultiWalletReducer { pendingTransactions.isNotEmpty() -> BalanceStatus.SameCurrencyTransactionInProgress else -> BalanceStatus.VerifiedOnline } - val tokenWalletData = state.getWalletData(action.amount.currencySymbol) + val tokenWalletData = state.getWalletData(action.token) val newTokenWalletData = tokenWalletData?.copy( currencyData = tokenWalletData.currencyData.copy( status = tokenBalanceStatus, amount = action.amount.value?.toFormattedCurrencyString( action.amount.decimals, action.amount.currencySymbol ), - fiatAmount = tokenWalletData.fiatRate?.let { + fiatAmountFormatted = tokenWalletData.fiatRate?.let { action.amount.value ?.toFiatString(it, store.state.globalState.appCurrency) } @@ -149,12 +153,24 @@ class MultiWalletReducer { state.copy(isMultiwalletAllowed = action.isMultiwalletAllowed) is WalletAction.MultiWallet.SelectWallet -> - state.copy(selectedWallet = action.walletData?.currencyData?.currencySymbol) + state.copy(selectedWallet = action.walletData?.currency) is WalletAction.MultiWallet.RemoveWallet -> { - state.copy(wallets = state.wallets.filterNot { - it.currencyData.currencySymbol == action.walletData.currencyData.currencySymbol - }) + val wallets = state.wallets.filterNot { + it.currency == action.walletData.currency + } + if (action.walletData.currency is Currency.Blockchain) { + state.copy( + wallets = wallets, + walletManagers = state.walletManagers.filterNot { + it.wallet.blockchain == action.walletData.currency.blockchain + } + ) + } else { + state.copy(wallets = wallets) + } + + } is WalletAction.MultiWallet.SetPrimaryBlockchain -> state.copy(primaryBlockchain = action.blockchain) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt index d76c7aae32..fc3e7a49b3 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt @@ -3,9 +3,7 @@ package com.tangem.tap.features.wallet.redux.reducers import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.Wallet import com.tangem.common.extensions.isZero -import com.tangem.tap.common.extensions.toFiatString -import com.tangem.tap.common.extensions.toFormattedCurrencyString -import com.tangem.tap.common.extensions.toFormattedString +import com.tangem.tap.common.extensions.* import com.tangem.tap.domain.getFirstToken import com.tangem.tap.features.wallet.models.removeUnknownTransactions import com.tangem.tap.features.wallet.models.toPendingTransactions @@ -34,7 +32,7 @@ class OnWalletLoadedReducer { ): WalletState { val fiatCurrencySymbol = store.state.globalState.appCurrency val amount = wallet.amounts[AmountType.Coin]?.value - if (walletState.getWalletData(wallet.blockchain.currency) == null) { + if (walletState.getWalletData(wallet.blockchain) == null) { return walletState } val formattedAmount = amount?.toFormattedCurrencyString( @@ -50,37 +48,40 @@ class OnWalletLoadedReducer { } else { BalanceStatus.VerifiedOnline } - val walletData = walletState.getWalletData(wallet.blockchain.currency) + val walletData = walletState.getWalletData(wallet.blockchain) ?: WalletData() + val fiatAmount = walletData.fiatRate?.let { amount?.toFiatValue(it) } val newWalletData = walletData.copy( currencyData = walletData.currencyData.copy( status = balanceStatus, currency = wallet.blockchain.fullName, currencySymbol = wallet.blockchain.currency, amount = formattedAmount, - fiatAmount = walletData.fiatRate?.let { amount?.toFiatString(it, fiatCurrencySymbol) } + fiatAmount = fiatAmount, + fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrencySymbol) ), pendingTransactions = pendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(sendButtonEnabled) ) val tokens = wallet.getTokens().mapNotNull { token -> - val tokenWalletData = walletState.getWalletData(token.symbol) + val tokenWalletData = walletState.getWalletData(token) val tokenPendingTransactions = pendingTransactions.filter { it.currency == token.symbol } val tokenBalanceStatus = when { tokenPendingTransactions.isNotEmpty() -> BalanceStatus.TransactionInProgress pendingTransactions.isNotEmpty() -> BalanceStatus.SameCurrencyTransactionInProgress else -> BalanceStatus.VerifiedOnline } + val tokenFiatAmount = tokenWalletData?.fiatRate?.let { rate -> + wallet.getTokenAmount(token)?.value?.toFiatValue(rate) + } tokenWalletData?.copy( currencyData = tokenWalletData.currencyData.copy( status = tokenBalanceStatus, amount = wallet.getTokenAmount(token)?.value?.toFormattedCurrencyString( token.decimals, token.symbol ), - fiatAmount = tokenWalletData.fiatRate?.let { - wallet.getTokenAmount(token)?.value - ?.toFiatString(it, fiatCurrencySymbol) - } + fiatAmount = tokenFiatAmount, + fiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrencySymbol) ), pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(sendButtonEnabled) @@ -145,8 +146,8 @@ class OnWalletLoadedReducer { currencySymbol = wallet.blockchain.currency, formattedAmount, token = tokenData, - fiatAmount = fiatAmount, - fiatAmountRaw = fiatAmountRaw + fiatAmountFormatted = fiatAmount, + fiatAmount = fiatAmountRaw ), pendingTransactions = pendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(sendButtonEnabled) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index 06f40d4d68..d69a984733 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -1,15 +1,11 @@ package com.tangem.tap.features.wallet.redux.reducers import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Wallet import com.tangem.commands.common.network.TangemService import com.tangem.common.extensions.toHexString -import com.tangem.tap.common.extensions.toFiatString -import com.tangem.tap.common.extensions.toFormattedCurrencyString -import com.tangem.tap.common.extensions.toQrCode +import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.AppState -import com.tangem.tap.common.redux.global.CryptoCurrencyName import com.tangem.tap.common.redux.global.FiatCurrencyName import com.tangem.tap.domain.TapError import com.tangem.tap.domain.getFirstToken @@ -88,7 +84,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { ) } is WalletAction.LoadWallet -> { - if (action.currency == null) { + if (action.blockchain == null) { val wallets = newState.wallets.map { wallet -> wallet.copy( currencyData = wallet.currencyData.copy( @@ -106,9 +102,12 @@ private fun internalReduce(action: Action, state: AppState): WalletState { wallets = wallets ) } else { - val walletManager = newState.getWalletManager(action.currency) ?: return newState - val currencies = listOf(walletManager.wallet.blockchain.currency) + walletManager.presetTokens.map { it.symbol } - val newWallets = newState.wallets.filter { currencies.contains(it.currencyData.currencySymbol) } + val walletManager = newState.getWalletManager(action.blockchain) ?: return newState + val blockchain = walletManager.wallet.blockchain + val currencies = listOf(Currency.Blockchain(blockchain)) + walletManager.presetTokens.map { + Currency.Token(token = it, blockchain = blockchain) + } + val newWallets = newState.wallets.filter { currencies.contains(it.currency) } .map { wallet -> wallet.copy( currencyData = wallet.currencyData.copy( @@ -131,7 +130,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { newState = onWalletLoadedReducer.reduce(action.wallet, newState) } is WalletAction.LoadWallet.NoAccount -> { - val walletData = newState.getWalletData(action.wallet.blockchain.currency)?.copy( + val walletData = newState.getWalletData(action.wallet.blockchain)?.copy( currencyData = BalanceWidgetData( BalanceStatus.NoAccount, action.wallet.blockchain.fullName, currencySymbol = action.wallet.blockchain.currency, @@ -155,7 +154,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { } else { action.errorMessage } - val walletData = newState.getWalletData(action.wallet.blockchain.currency) + val walletData = newState.getWalletData(action.wallet.blockchain) val newWalletData = walletData?.copy( currencyData = walletData.currencyData.copy( status = BalanceStatus.Unreachable, @@ -164,7 +163,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { topUpState = TopUpState(false) ) val tokenWallets = action.wallet.getTokens() - .mapNotNull { newState.getWalletData(it.symbol) } + .mapNotNull { newState.getWalletData(it) } .map { it.copy(currencyData = it.currencyData.copy( status = BalanceStatus.Unreachable, errorMessage = message @@ -241,7 +240,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { is WalletAction.ChangeSelectedAddress -> { val selectedWalletData = newState.getWalletData(newState.selectedWallet) - val walletAddresses = newState.getWalletData(selectedWalletData?.currencyData?.currencySymbol)?.walletAddresses + val walletAddresses = newState.getWalletData(selectedWalletData?.currency)?.walletAddresses ?: return newState val address = walletAddresses.list.firstOrNull { it.type == action.type } ?: return newState @@ -288,64 +287,60 @@ private fun handleCheckSignedHashesActions(action: WalletAction.Warnings, state: private fun setNewFiatRate( - fiatRate: Pair, + fiatRate: Pair, appCurrency: FiatCurrencyName, state: WalletState ): WalletState { val rate = fiatRate.second ?: return state val rateFormatted = rate.toFormattedCurrencyString(2, appCurrency) val currency = fiatRate.first - if (!state.isMultiwalletAllowed) { - return setSingeWalletFiatRate(rate, rateFormatted, currency, appCurrency, state) + return if (!state.isMultiwalletAllowed) { + setSingeWalletFiatRate(rate, rateFormatted, currency, appCurrency, state) } else { - return setMultiWalletFiatRate(rate, rateFormatted, currency, appCurrency, state) + setMultiWalletFiatRate(rate, rateFormatted, currency, appCurrency, state) } } private fun setMultiWalletFiatRate( - rate: BigDecimal, rateFormatted: String, currency: CryptoCurrencyName, - appCurrency: FiatCurrencyName, state: WalletState + rate: BigDecimal, rateFormatted: String, currency: Currency, + appCurrency: FiatCurrencyName, state: WalletState ): WalletState { val walletData = state.getWalletData(currency) ?: return state - val wallet = state.walletManagers.find { it.wallet.blockchain.currency == currency }?.wallet - if (wallet != null) { - val newWalletData = state.getWalletData(currency)?.copy( - currencyData = walletData.currencyData.copy( - fiatAmount = wallet.amounts[AmountType.Coin]?.value - ?.toFiatString(rate, appCurrency)), - fiatRate = rate, fiatRateString = rateFormatted - ) - return state.copy(wallets = state.replaceWalletInWallets(newWalletData)) - } else { - val ethereumWallet = state.walletManagers.find { it.wallet.blockchain == Blockchain.Ethereum }?.wallet - val token = ethereumWallet?.getTokens()?.find { it.symbol == currency } ?: return state - val tokenFiatAmount = ethereumWallet.getTokenAmount(token)?.value?.toFiatString(rate, appCurrency) - val newWalletData = state.getWalletData(currency)?.copy( - currencyData = walletData.currencyData.copy( - fiatAmount = tokenFiatAmount), - fiatRate = rate, fiatRateString = rateFormatted - ) - return state.copy(wallets = state.replaceWalletInWallets(newWalletData)) + val wallet = state.getWalletManager(currency)?.wallet + val fiatAmount = when (currency) { + is Currency.Blockchain -> + wallet?.amounts?.get(AmountType.Coin)?.value?.toFiatValue(rate) + is Currency.Token -> + wallet?.getTokenAmount(currency.token)?.value?.toFiatValue(rate) } + val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(appCurrency) + val newWalletData = state.getWalletData(currency)?.copy( + currencyData = walletData.currencyData.copy( + fiatAmountFormatted = fiatAmountFormatted, + fiatAmount = fiatAmount + ), + fiatRate = rate, fiatRateString = rateFormatted + ) + return state.copy(wallets = state.replaceWalletInWallets(newWalletData)) } private fun setSingeWalletFiatRate( - rate: BigDecimal, rateFormatted: String, currency: CryptoCurrencyName, + rate: BigDecimal, rateFormatted: String, currency: Currency, appCurrency: FiatCurrencyName, state: WalletState ): WalletState { val wallet = state.walletManagers[0].wallet val token = wallet.getFirstToken() - if (currency == state.primaryWallet?.currencyData?.currencySymbol) { + if (currency == state.primaryWallet?.currency) { val fiatAmount = wallet.amounts[AmountType.Coin]?.value ?.toFiatString(rate, appCurrency) val walletData = state.primaryWallet.copy( - currencyData = state.primaryWallet.currencyData.copy(fiatAmount = fiatAmount), + currencyData = state.primaryWallet.currencyData.copy(fiatAmountFormatted = fiatAmount), fiatRate = rate, fiatRateString = rateFormatted ) return state.copy(wallets = listOf(walletData)) - } else if (currency == token?.symbol) { + } else if (currency is Currency.Token && currency.token == token) { val tokenFiatAmount = wallet.getTokenAmount(token)?.value?.toFiatString(rate, appCurrency) val tokenData = state.primaryWallet?.currencyData?.token?.copy( fiatAmount = tokenFiatAmount, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt index 508a62b08c..2992b2d543 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt @@ -22,15 +22,15 @@ enum class BalanceStatus { } data class BalanceWidgetData( - val status: BalanceStatus? = null, - val currency: String? = null, - val currencySymbol: String? = null, - val amount: String? = null, - val fiatAmount: String? = null, - val fiatAmountRaw: BigDecimal? = null, - val token: TokenData? = null, - val amountToCreateAccount: String? = null, - val errorMessage: String? = null + val status: BalanceStatus? = null, + val currency: String? = null, + val currencySymbol: String? = null, + val amount: String? = null, + val fiatAmountFormatted: String? = null, + val fiatAmount: BigDecimal? = null, + val token: TokenData? = null, + val amountToCreateAccount: String? = null, + val errorMessage: String? = null ) data class TokenData( @@ -158,7 +158,7 @@ class BalanceWidget( fragment.tv_amount.text = if (showAmount) data.amount else "" if (showAmount) { fragment.tv_fiat_amount.show() - fragment.tv_fiat_amount.text = data.fiatAmount + fragment.tv_fiat_amount.text = data.fiatAmountFormatted } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index 5b59b03015..340238f2de 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -9,6 +9,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.transition.TransitionInflater +import com.squareup.picasso.Picasso import com.tangem.blockchain.common.Blockchain import com.tangem.tap.MainActivity import com.tangem.tap.common.extensions.* @@ -24,6 +25,9 @@ import kotlinx.android.synthetic.main.fragment_details_twin_cards.* import kotlinx.android.synthetic.main.fragment_wallet_details.* import kotlinx.android.synthetic.main.fragment_wallet_details.toolbar import kotlinx.android.synthetic.main.item_currency_wallet.view.* +import kotlinx.android.synthetic.main.item_currency_wallet.view.iv_currency +import kotlinx.android.synthetic.main.item_currency_wallet.view.tv_token_letter +import kotlinx.android.synthetic.main.item_popular_token.view.* import kotlinx.android.synthetic.main.layout_balance_error.* import kotlinx.android.synthetic.main.layout_balance_wallet_details.* import kotlinx.android.synthetic.main.layout_wallet_details.* @@ -123,7 +127,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS if (selectedWallet.currencyData.status != BalanceStatus.Loading) { store.dispatch(WalletAction.LoadWallet( selectedWallet.topUpState.allowed, - selectedWallet.currencyData.currencySymbol + selectedWallet.currency?.blockchain )) } } @@ -134,16 +138,12 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS } private fun handleCurrencyIcon(wallet: WalletData) { - val blockchain = wallet.currencyData.currencySymbol?.let { Blockchain.fromCurrency(it) } - if (blockchain != null && blockchain != Blockchain.Unknown) { - tv_token_letter.text = null - iv_currency.colorFilter = null - iv_currency.setImageResource(blockchain.getIconRes()) - } else { - tv_token_letter.text = wallet.currencyData.currencySymbol?.take(1) - wallet.token?.getColor()?.let { iv_currency.setColorFilter(it) } - iv_currency.setImageResource(R.drawable.shape_circle) - } + Picasso.get().loadCurrenciesIcon( + imageView = iv_currency, + textView = tv_token_letter, + blockchain = wallet.currency?.blockchain, + token = (wallet.currency as? Currency.Token)?.token + ) } @@ -154,7 +154,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS private fun setupAddressCard(state: WalletData) { if (state.walletAddresses != null) { - if (state.shouldShowMultipleAddress() && state.blockchain != null) { + if (state.shouldShowMultipleAddress() && state.currency is Currency.Blockchain) { (card_balance as? ViewGroup)?.beginDelayedTransition() chip_group_address_type.show() chip_group_address_type.fitChipsByGroupWidth() @@ -164,7 +164,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS chip_group_address_type.setOnCheckedChangeListener { group, checkedId -> if (checkedId == -1) return@setOnCheckedChangeListener - val type = MultipleAddressUiHelper.idToType(checkedId, state.blockchain) + val type = MultipleAddressUiHelper.idToType(checkedId, state.currency.blockchain) type?.let { store.dispatch(WalletAction.ChangeSelectedAddress(type)) } } } else { @@ -260,7 +260,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS tv_amount.text = if (showAmount) data.amount else "" if (showAmount) { tv_fiat_amount.show() - tv_fiat_amount.text = data.fiatAmount + tv_fiat_amount.text = data.fiatAmountFormatted } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index 7c3c669075..8aa058881c 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -8,6 +8,7 @@ import android.view.MenuItem import android.view.View import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.get import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt index c82c47f25f..6c0328c7ce 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt @@ -6,15 +6,12 @@ import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView -import com.squareup.picasso.Callback import com.squareup.picasso.Picasso import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.IconsUtil import com.tangem.blockchain.common.Token -import com.tangem.tap.common.extensions.getColor -import com.tangem.tap.common.extensions.getIconRes import com.tangem.tap.common.extensions.loadCurrenciesIcon import com.tangem.tap.common.extensions.show +import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletData import com.tangem.tap.features.wallet.ui.BalanceStatus @@ -24,8 +21,6 @@ import kotlinx.android.synthetic.main.item_currency_wallet.view.* import kotlinx.android.synthetic.main.item_currency_wallet.view.iv_currency import kotlinx.android.synthetic.main.item_currency_wallet.view.tv_currency_symbol import kotlinx.android.synthetic.main.item_currency_wallet.view.tv_token_letter -import kotlinx.android.synthetic.main.item_popular_token.view.* -import java.lang.Exception import java.math.BigDecimal class WalletAdapter @@ -38,7 +33,9 @@ class WalletAdapter fun submitList(list: List, primaryBlockchain: Blockchain?, primaryToken: Token? = null) { val listModified = list.toMutableList() val primaryBlockchainWallet = when ( - val index = listModified.indexOfFirst { it.blockchain == primaryBlockchain } + val index = listModified.indexOfFirst { + (it.currency as? Currency.Blockchain)?.blockchain == primaryBlockchain + } ) { -1 -> null else -> listModified.removeAt(index) @@ -46,20 +43,20 @@ class WalletAdapter val primaryTokenWallet = if (primaryToken == null) null else when ( - val index = listModified.indexOfFirst { it.token == primaryToken } + val index = listModified.indexOfFirst { (it.currency as? Currency.Token)?.token == primaryToken } ) { -1 -> null else -> listModified.removeAt(index) } - if (list.all { it.currencyData.fiatAmount == null }) { + if (list.all { it.currencyData.fiatAmountFormatted == null }) { val sortedList = listOfNotNull(primaryBlockchainWallet, primaryTokenWallet) + listModified super.submitList(sortedList) return } val sorted = listModified.sortedWith( - compareByDescending { it.currencyData.fiatAmountRaw ?: BigDecimal.ZERO } + compareByDescending { it.currencyData.fiatAmount ?: BigDecimal.ZERO } .thenBy { it.currencyData.currencySymbol } ) val sortedList = listOfNotNull(primaryBlockchainWallet, primaryTokenWallet) + sorted @@ -93,13 +90,13 @@ class WalletAdapter view.tv_currency.text = wallet.currencyData.currency view.tv_amount.text = wallet.currencyData.amount?.takeWhile { !it.isWhitespace() } view.tv_currency_symbol.text = wallet.currencyData.amount?.takeLastWhile { !it.isWhitespace() } - view.tv_amount_fiat.text = wallet.currencyData.fiatAmount + view.tv_amount_fiat.text = wallet.currencyData.fiatAmountFormatted view.tv_exchange_rate.text = wallet.fiatRateString view.card_wallet.setOnClickListener { store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet)) } - val blockchain = wallet.blockchain - val token = wallet.token + val blockchain = wallet.currency?.blockchain + val token = (wallet.currency as? Currency.Token)?.token Picasso.get().loadCurrenciesIcon( imageView = view.iv_currency, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt index 56eba3612c..ce0623ac86 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt @@ -190,7 +190,7 @@ class SingleWalletView : WalletView { private fun setupAddressCard(state: WalletData, fragment: WalletFragment) = with(fragment) { - if (state.walletAddresses != null && state.blockchain != null) { + if (state.walletAddresses != null && state.currency is Currency.Blockchain) { l_address?.show() if (state.shouldShowMultipleAddress()) { (l_address as? ViewGroup)?.beginDelayedTransition() @@ -202,7 +202,7 @@ class SingleWalletView : WalletView { chip_group_address_type.setOnCheckedChangeListener { group, checkedId -> if (checkedId == -1) return@setOnCheckedChangeListener - val type = MultipleAddressUiHelper.idToType(checkedId, state.blockchain) + val type = MultipleAddressUiHelper.idToType(checkedId, state.currency.blockchain) type?.let { store.dispatch(WalletAction.ChangeSelectedAddress(type)) } } } else { diff --git a/build.gradle b/build.gradle index 3b07b1a1ac..576034574e 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,6 @@ buildscript { allprojects { repositories { google() - jcenter() maven { url 'https://jitpack.io' } def nexusUser = "viewer" def nexusPass = "smartcash124" diff --git a/dependencies.gradle b/dependencies.gradle index 22dc84c906..b28e81e8b9 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,4 +1,4 @@ ext.versions = [ kotlin : '1.5.0', - build_gradle: '4.2.0', + build_gradle: '4.2.1', ]