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 360c6f1b07..357db63124 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -184,23 +184,32 @@ class TapWalletManager { private fun loadMultiWalletData( card: Card, primaryBlockchain: Blockchain?, primaryWalletManager: WalletManager? ) { - val presetTokens = primaryWalletManager?.presetTokens?.toList() ?: emptyList() + val presetTokens = primaryWalletManager?.presetTokens ?: emptySet() val savedCurrencies = currenciesRepository.loadCardCurrencies(card.cardId) if (savedCurrencies == null) { if (primaryBlockchain != null && primaryWalletManager != null) { store.dispatch(WalletAction.MultiWallet.SaveCurrencies( CardCurrencies( - blockchains = listOf(primaryBlockchain), tokens = presetTokens + blockchains = setOf(primaryBlockchain), tokens = presetTokens ))) store.dispatch(WalletAction.MultiWallet.AddWalletManagers(primaryWalletManager)) store.dispatch(WalletAction.MultiWallet.AddBlockchains(listOf(primaryBlockchain))) - store.dispatch(WalletAction.MultiWallet.AddTokens(presetTokens)) + store.dispatch(WalletAction.MultiWallet.AddTokens(presetTokens.toList())) + } else { + val blockchains = setOf(Blockchain.Bitcoin, Blockchain.Ethereum) + store.dispatch(WalletAction.MultiWallet.SaveCurrencies( + CardCurrencies(blockchains = blockchains, tokens = emptySet()) + )) + val walletManagers = + walletManagerFactory.makeWalletManagersForApp(card, blockchains.toList()) + store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManagers)) + store.dispatch(WalletAction.MultiWallet.AddBlockchains(blockchains.toList())) } store.dispatch(WalletAction.MultiWallet.FindBlockchainsInUse(card, walletManagerFactory)) store.dispatch(WalletAction.MultiWallet.FindTokensInUse) } else { - val blockchains = savedCurrencies.blockchains + val blockchains = savedCurrencies.blockchains.toList() val walletManagers = if ( presetTokens.isNotEmpty() && primaryWalletManager != null && primaryBlockchain != null @@ -214,8 +223,7 @@ class TapWalletManager { store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManagers)) store.dispatch(WalletAction.MultiWallet.AddBlockchains(blockchains)) - store.dispatch(WalletAction.MultiWallet.AddTokens(savedCurrencies.tokens)) - store.dispatch(WalletAction.MultiWallet.FindTokensInUse) + store.dispatch(WalletAction.MultiWallet.AddTokens(savedCurrencies.tokens.toList())) } } diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt index 78afe93215..417c3cb79e 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt @@ -13,11 +13,11 @@ import com.tangem.tap.network.createMoshi class CurrenciesRepository(val context: Application) { private val moshi = createMoshi() - private val tokensAdapter: JsonAdapter> = moshi.adapter( - Types.newParameterizedType(List::class.java, TokenDao::class.java) + private val tokensAdapter: JsonAdapter> = moshi.adapter( + Types.newParameterizedType(Set::class.java, TokenDao::class.java) ) - private val blockchainsAdapter: JsonAdapter> = moshi.adapter( - Types.newParameterizedType(List::class.java, Blockchain::class.java) + private val blockchainsAdapter: JsonAdapter> = moshi.adapter( + Types.newParameterizedType(Set::class.java, Blockchain::class.java) ) fun loadCardCurrencies(cardId: String): CardCurrencies? { @@ -43,45 +43,45 @@ class CurrenciesRepository(val context: Application) { } fun removeToken(cardId: String, token: Token) { - val tokens = loadSavedTokens(cardId).filterNot { it == token } + val tokens = loadSavedTokens(cardId).filterNot { it == token }.toSet() saveTokens(cardId, tokens) } fun removeBlockchain(cardId: String, blockchain: Blockchain) { - val blockchains = loadSavedBlockchains(cardId).filterNot { it == blockchain } + val blockchains = loadSavedBlockchains(cardId).filterNot { it == blockchain }.toSet() saveBlockchains(cardId, blockchains) } - private fun loadSavedTokens(cardId: String): List { + private fun loadSavedTokens(cardId: String): Set { return try { val json = context.readFileText(getFileNameForTokens(cardId)) - tokensAdapter.fromJson(json)!!.map { it.toToken() } + tokensAdapter.fromJson(json)!!.map { it.toToken() }.toSet() } catch (exception: Exception) { - emptyList() + emptySet() } } - private fun saveTokens(cardId: String, tokens: List) { - val json = tokensAdapter.toJson(tokens.map { TokenDao.fromToken(it) }) + private fun saveTokens(cardId: String, tokens: Set) { + val json = tokensAdapter.toJson(tokens.map { TokenDao.fromToken(it) }.toSet()) context.rewriteFile(json, getFileNameForTokens(cardId)) } - private fun loadSavedBlockchains(cardId: String): List { + private fun loadSavedBlockchains(cardId: String): Set { return try { val json = context.readFileText(getFileNameForBlockchains(cardId)) - blockchainsAdapter.fromJson(json) ?: emptyList() + blockchainsAdapter.fromJson(json) ?: emptySet() } catch (exception: Exception) { - emptyList() + emptySet() } } - private fun saveBlockchains(cardId: String, blockchains: List) { + private fun saveBlockchains(cardId: String, blockchains: Set) { val json = blockchainsAdapter.toJson(blockchains) context.rewriteFile(json, getFileNameForBlockchains(cardId)) } private fun Context.readFileText(fileName: String): String = - this.openFileInput(fileName).bufferedReader().readText() + this.openFileInput(fileName).bufferedReader().readText() private fun Context.rewriteFile(content: String, fileName: String) { this.openFileOutput(fileName, Context.MODE_PRIVATE).use { @@ -108,12 +108,13 @@ class CurrenciesRepository(val context: Application) { private const val FILE_NAME_PREFIX_BLOCKCHAINS = "blockchains" fun getFileNameForTokens(cardId: String): String = "${FILE_NAME_PREFIX_TOKENS}_$cardId" - fun getFileNameForBlockchains(cardId: String): String = "${FILE_NAME_PREFIX_BLOCKCHAINS}_$cardId" + fun getFileNameForBlockchains(cardId: String): String = + "${FILE_NAME_PREFIX_BLOCKCHAINS}_$cardId" private val secp256k1Blochcains = listOf( - Blockchain.Bitcoin, Blockchain.BitcoinCash, Blockchain.Binance, Blockchain.Litecoin, - Blockchain.XRP, Blockchain.Tezos, - Blockchain.Ethereum, Blockchain.RSK) + Blockchain.Bitcoin, Blockchain.BitcoinCash, Blockchain.Binance, Blockchain.Litecoin, + Blockchain.XRP, Blockchain.Tezos, + Blockchain.Ethereum, Blockchain.RSK) private val ed25519Blockchains = listOf(Blockchain.CardanoShelley, Blockchain.Stellar) } } @@ -121,18 +122,24 @@ class CurrenciesRepository(val context: Application) { @JsonClass(generateAdapter = true) data class TokenDao( - val name: String, - val symbol: String, - val contractAddress: String, - val decimalCount: Int + val name: String, + val symbol: String, + val contractAddress: String, + val decimalCount: Int, ) { fun toToken(): Token { - return Token(name = name, symbol = symbol, contractAddress = contractAddress, decimals = decimalCount) + return Token(name = name, + symbol = symbol, + contractAddress = contractAddress, + decimals = decimalCount) } companion object { fun fromToken(token: Token): TokenDao { - return TokenDao(name = token.name, symbol = token.symbol, contractAddress = token.contractAddress, decimalCount = token.decimals) + return TokenDao(name = token.name, + symbol = token.symbol, + contractAddress = token.contractAddress, + decimalCount = token.decimals) } } @@ -140,21 +147,25 @@ data class TokenDao( @JsonClass(generateAdapter = true) data class CardCurrenciesDao( - val tokens: List, - val blockchains: List + val tokens: Set, + val blockchains: Set, ) { fun toCardCurrencies(): CardCurrencies { - return CardCurrencies(tokens = tokens.map { it.toToken() }, blockchains = blockchains) + return CardCurrencies(tokens = tokens.map { it.toToken() }.toSet(), + blockchains = blockchains) } companion object { fun fromCardCurrencies(cardCurrencies: CardCurrencies): CardCurrenciesDao { - return CardCurrenciesDao(tokens = cardCurrencies.tokens.map { TokenDao.fromToken(it) }, blockchains = cardCurrencies.blockchains) + return CardCurrenciesDao( + tokens = cardCurrencies.tokens.map { TokenDao.fromToken(it) }.toSet(), + blockchains = cardCurrencies.blockchains + ) } } } data class CardCurrencies( - val tokens: List, - val blockchains: List + val tokens: Set, + val blockchains: Set, ) \ No newline at end of file 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 be4a64b61e..66a7dd928b 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 @@ -21,8 +21,6 @@ private fun internalReduce(action: Action, state: AppState): TokensState { tokensState.copy(currencies = action.currencies) } is TokensAction.SetAddedCurrencies -> { - - tokensState.copy(addedCurrencies = action.wallets.toCardCurrencies()) } is TokensAction.LoadCardTokens.Success -> { @@ -35,7 +33,7 @@ private fun internalReduce(action: Action, state: AppState): TokensState { } private fun List.toCardCurrencies(): CardCurrencies { - val tokens = mapNotNull { (it.currency as? Currency.Token)?.token } - val blockchains = mapNotNull { (it.currency as? Currency.Blockchain)?.blockchain } + val tokens = mapNotNull { (it.currency as? Currency.Token)?.token }.toSet() + val blockchains = mapNotNull { (it.currency as? Currency.Blockchain)?.blockchain }.toSet() return CardCurrencies(tokens = tokens, blockchains = blockchains) } \ No newline at end of file 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 1b2a1aa4b0..35b301fd50 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 @@ -44,14 +44,17 @@ data class WalletState( val blockchains: List get() = walletManagers.map { it.wallet.blockchain } + val currencies: List + get() = wallets.mapNotNull { it.currency } + 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 == token } != null) { + return if (ethereumWalletManager?.presetTokens?.contains(token) == true) { ethereumWalletManager } else { val primaryWalletManager = walletManagers.find { it.wallet.blockchain == primaryBlockchain } - if (primaryWalletManager?.presetTokens?.find { it == token } != null) { + if (primaryWalletManager?.presetTokens?.contains(token) == true) { primaryWalletManager } else { ethereumWalletManager @@ -132,6 +135,11 @@ data class WalletState( return wallets.filter { !currencies.contains(it.currencyData.currency) } + newWallets } + fun addWalletManagers(newWalletManagers: List): WalletState { + val updatedWalletManagers = this.walletManagers + + newWalletManagers.filterNot { this.blockchains.contains(it.wallet.blockchain) } + return copy(walletManagers = updatedWalletManagers) + } } sealed class WalletDialog: StateDialog { 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 8c45a9b8c3..2f90f29e0f 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 @@ -2,6 +2,7 @@ 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.Token import com.tangem.common.extensions.isZero import com.tangem.tap.common.extensions.toFiatString import com.tangem.tap.common.extensions.toFormattedCurrencyString @@ -18,9 +19,7 @@ class MultiWalletReducer { fun reduce(action: WalletAction.MultiWallet, state: WalletState): WalletState { return when (action) { is WalletAction.MultiWallet.AddWalletManagers -> { - state.copy( - walletManagers = state.walletManagers + action.walletManagers - ) + state.addWalletManagers(action.walletManagers) } is WalletAction.MultiWallet.AddBlockchains -> { val wallets = action.blockchains.map { blockchain -> @@ -75,47 +74,12 @@ 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(walletManager), - mainButton = WalletMainButton.SendButton(false), - topUpState = TopUpState(allowed = false), - currency = Currency.Token( - token = token, - blockchain = walletManager?.blockchain ?: Blockchain.Ethereum - ) - ) - } + val wallets = action.tokens.mapNotNull { token -> token.toWallet(state) } 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 wallet = WalletData( - currencyData = BalanceWidgetData( - BalanceStatus.Loading, - currency = action.token.name, - currencySymbol = action.token.symbol - ), - walletAddresses = walletAddresses, - mainButton = WalletMainButton.SendButton(false), - topUpState = TopUpState(allowed = false), - currency = Currency.Token( - token = action.token, - blockchain = walletManager?.blockchain ?: Blockchain.Ethereum - ) - ) - val wallets = state.replaceWalletInWallets(wallet) - state.copy(wallets = wallets) + val walletData = action.token.toWallet(state) ?: return state + state.copy(wallets = state.replaceWalletInWallets(walletData)) } is WalletAction.MultiWallet.TokenLoaded -> { val pendingTransactions = state.getWalletManager(action.token) @@ -182,4 +146,29 @@ class MultiWalletReducer { is WalletAction.MultiWallet.SaveCurrencies -> state } } +} + +fun Token.toWallet(state: WalletState): WalletData? { + if (!state.isMultiwalletAllowed) return null + if (state.currencies.any { it is Currency.Token && it.token == this }) { + return null + } + + val walletManager = state.getWalletManager(this)?.wallet + val walletAddresses = createAddressList(walletManager) + + return WalletData( + currencyData = BalanceWidgetData( + BalanceStatus.Loading, + currency = this.name, + currencySymbol = this.symbol + ), + walletAddresses = walletAddresses, + mainButton = WalletMainButton.SendButton(false), + topUpState = TopUpState(allowed = false), + currency = Currency.Token( + token = this, + blockchain = walletManager?.blockchain ?: Blockchain.Ethereum + ) + ) } \ No newline at end of file diff --git a/dependencies.gradle b/dependencies.gradle index b28e81e8b9..32b0ea5280 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,4 +1,4 @@ ext.versions = [ - kotlin : '1.5.0', + kotlin : '1.5.10', build_gradle: '4.2.1', ]