Updated on 2026-08-14

This commit is contained in:
Tangem 2021-04-12 06:23:27 +00:00
commit 7e7c274dcc
7 changed files with 94 additions and 63 deletions

View file

@ -1,7 +1,7 @@
package com.tangem.tap.domain
import com.tangem.blockchain.common.*
import com.tangem.blockchain.extensions.getBlockchain
import com.tangem.commands.common.card.Card
import com.tangem.commands.common.card.CardStatus
import com.tangem.commands.common.network.Result
import com.tangem.tap.common.analytics.AnalyticsEvent
@ -14,6 +14,7 @@ import com.tangem.tap.domain.configurable.config.ConfigManager
import com.tangem.tap.domain.extensions.amountToCreateAccount
import com.tangem.tap.domain.extensions.isNoAccountError
import com.tangem.tap.domain.tasks.ScanNoteResponse
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
@ -32,7 +33,7 @@ class TapWalletManager {
private val blockchainSdkConfig by lazy {
store.state.globalState.configManager?.config?.blockchainSdkConfig ?: BlockchainSdkConfig()
}
private val walletManagerFactory: WalletManagerFactory
val walletManagerFactory: WalletManagerFactory
by lazy { WalletManagerFactory(blockchainSdkConfig) }
suspend fun loadWalletData(walletManager: WalletManager) {
@ -131,36 +132,20 @@ class TapWalletManager {
val config = store.state.globalState.configManager?.config ?: return@withContext
val primaryWalletManager = data.walletManager
val primaryBlockchain = listOf(data.walletManager.wallet.blockchain)
val primaryBlockchain = data.walletManager.wallet.blockchain
val primaryTokenSymbol = data.card.cardData?.tokenSymbol
val primaryToken = primaryWalletManager.presetTokens.toList()
.firstOrNull { it.symbol == primaryTokenSymbol }
store.dispatch(WalletAction.MultiWallet.SetPrimaryBlockchain(primaryBlockchain[0]))
store.dispatch(WalletAction.MultiWallet.SetPrimaryBlockchain(primaryBlockchain))
if (primaryToken != null) {
store.dispatch(WalletAction.MultiWallet.SetPrimaryToken(primaryToken))
}
if (data.card.isMultiwalletAllowed) {
val savedCurrencies = currenciesRepository.loadCardCurrencies(data.card.cardId)
val walletManagers = listOf(primaryWalletManager) +
currenciesRepository.getBlockchains()
.filterNot { it == primaryWalletManager.wallet.blockchain }
.mapNotNull { walletManagerFactory.makeWalletManager(data.card, it) }
val otherBlockhains = savedCurrencies.blockchains
val presetTokens = walletManagers.first { it.wallet.blockchain == data.card.getBlockchain() }
.presetTokens.toList()
val tokens = presetTokens + savedCurrencies.tokens
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManagers))
store.dispatch(WalletAction.MultiWallet.AddBlockchains(primaryBlockchain + otherBlockhains))
store.dispatch(WalletAction.MultiWallet.AddTokens(tokens))
store.dispatch(WalletAction.MultiWallet.FindTokensInUse)
loadMultiWalletData(data.card, primaryBlockchain, primaryWalletManager)
} else {
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(listOf(primaryWalletManager)))
store.dispatch(WalletAction.MultiWallet.AddBlockchains(primaryBlockchain))
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(primaryWalletManager))
store.dispatch(WalletAction.MultiWallet.AddBlockchains(listOf(primaryBlockchain)))
}
store.dispatch(WalletAction.SetArtworkId(data.verifyResponse?.artworkInfo?.id))
store.dispatch(WalletAction.LoadWallet(config.isTopUpEnabled))
@ -177,6 +162,34 @@ class TapWalletManager {
}
}
private fun loadMultiWalletData(
card: Card, primaryBlockchain: Blockchain, primaryWalletManager: WalletManager
) {
val presetTokens = primaryWalletManager.presetTokens.toList()
val savedCurrencies = currenciesRepository.loadCardCurrencies(card.cardId)
if (savedCurrencies == null) {
store.dispatch(WalletAction.MultiWallet.SaveCurrencies(
CardCurrencies(
blockchains = listOf(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.FindBlockchainsInUse(card, walletManagerFactory))
store.dispatch(WalletAction.MultiWallet.FindTokensInUse)
} else {
val blockchains = listOf(primaryBlockchain) + savedCurrencies.blockchains
val walletManagers = walletManagerFactory.makeWalletManagers(card, blockchains)
val tokens = presetTokens + savedCurrencies.tokens
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManagers))
store.dispatch(WalletAction.MultiWallet.AddBlockchains(blockchains))
store.dispatch(WalletAction.MultiWallet.AddTokens(tokens))
store.dispatch(WalletAction.MultiWallet.FindTokensInUse)
}
}
suspend fun reloadData(data: ScanNoteResponse) {
withContext(Dispatchers.Main) {
if (data.walletManager != null) {

View file

@ -19,8 +19,11 @@ class CurrenciesRepository(val context: Application) {
Types.newParameterizedType(List::class.java, Blockchain::class.java)
)
fun loadCardCurrencies(cardId: String): CardCurrencies {
return CardCurrencies(loadSavedTokens(cardId), loadSavedBlockchains(cardId))
fun loadCardCurrencies(cardId: String): CardCurrencies? {
val blockchains = loadSavedBlockchains(cardId)
if (blockchains.isEmpty()) return null
return CardCurrencies(loadSavedTokens(cardId), blockchains)
}
fun saveCardCurrencies(cardId: String, currencies: CardCurrencies) {

View file

@ -9,6 +9,7 @@ import com.tangem.tap.common.redux.NotificationAction
import com.tangem.tap.common.redux.global.CryptoCurrencyName
import com.tangem.tap.domain.TapError
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
import com.tangem.tap.domain.tokens.CardCurrencies
import com.tangem.tap.domain.twins.TwinCardNumber
import com.tangem.wallet.R
import org.rekotlin.Action
@ -32,29 +33,18 @@ sealed class WalletAction : Action {
data class SetArtworkId(val artworkId: String?) : WalletAction()
// sealed class ProcessWallet : WalletAction() {
// data class LoadWallet(val artworkId: String?, val allowTopUp: Boolean
// ) : ProcessWallet() {
// data class Success(val wallet: Wallet) : ProcessWallet()
// data class NoAccount(val wallet: Wallet, val amountToCreateAccount: String) : ProcessWallet()
// data class Failure(val wallet: Wallet, val errorMessage: String? = null) : ProcessWallet()
// }
//
// data class UpdateWallet(val currency: CryptoCurrencyName? = null) : ProcessWallet() {
// object ScheduleUpdatingWallet : ProcessWallet()
// data class Success(val wallet: Wallet) : ProcessWallet()
// data class Failure(val errorMessage: String? = null) : ProcessWallet()
// }
// }
sealed class MultiWallet : WalletAction() {
data class SetIsMultiwalletAllowed(val isMultiwalletAllowed: Boolean) : MultiWallet()
data class AddWalletManagers(val walletManagers: List<WalletManager>) : MultiWallet()
data class AddWalletManagers(val walletManagers: List<WalletManager>) : MultiWallet() {
constructor(walletManager: WalletManager) : this(listOf(walletManager))
}
data class AddBlockchain(val blockchain: Blockchain) : MultiWallet()
data class AddBlockchains(val blockchains: List<Blockchain>) : MultiWallet()
data class AddTokens(val tokens: List<Token>) : MultiWallet()
data class AddToken(val token: Token) : MultiWallet()
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 SelectWallet(val walletData: WalletData?) : MultiWallet()
data class RemoveWallet(val walletData: WalletData) : MultiWallet()

View file

@ -60,7 +60,7 @@ data class WalletState(
if (primaryWalletManager?.presetTokens?.find { it.symbol == currencyName } != null) {
primaryWalletManager
} else {
null
ethereumWalletManager
}
}
}

View file

@ -1,9 +1,11 @@
package com.tangem.tap.features.wallet.redux.middlewares
import com.tangem.blockchain.common.AmountType
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.TokenFinder
import com.tangem.blockchain.extensions.Result
import com.tangem.common.extensions.isZero
import com.tangem.tap.common.redux.global.GlobalState
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
@ -13,6 +15,7 @@ import com.tangem.tap.features.wallet.redux.WalletState
import com.tangem.tap.scope
import com.tangem.tap.store
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -40,12 +43,20 @@ class MultiWalletMiddleware {
action.tokens.map { addToken(it, walletState) }
}
is WalletAction.MultiWallet.AddBlockchain -> {
globalState?.scanNoteResponse?.card?.cardId?.let {
currenciesRepository.saveAddedBlockchain(it, action.blockchain)
globalState?.scanNoteResponse?.card?.let { card ->
currenciesRepository.saveAddedBlockchain(card.cardId, action.blockchain)
globalState.tapWalletManager.walletManagerFactory
.makeWalletManager(card, action.blockchain)?.let {
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(it))
}
}
store.dispatch(WalletAction.LoadFiatRate(currency = action.blockchain.currency))
store.dispatch(WalletAction.LoadWallet(currency = action.blockchain.currency))
}
is WalletAction.MultiWallet.SaveCurrencies -> {
val cardId = globalState?.scanNoteResponse?.card?.cardId
cardId?.let { currenciesRepository.saveCardCurrencies(it, action.cardCurrencies) }
}
is WalletAction.MultiWallet.RemoveWallet -> {
val cardId = globalState?.scanNoteResponse?.card?.cardId
if (action.walletData.token != null) {
@ -54,6 +65,36 @@ class MultiWalletMiddleware {
cardId?.let { currenciesRepository.removeBlockchain(it, action.walletData.blockchain) }
}
}
is WalletAction.MultiWallet.FindBlockchainsInUse -> {
val blockchains = currenciesRepository.getBlockchains()
.filterNot { walletState?.blockchains?.contains(it) == true }
val walletManagers = action.factory.makeWalletManagers(action.card, blockchains)
scope.launch {
walletManagers.map { walletManager ->
async(Dispatchers.IO) {
try {
walletManager.update()
val wallet = walletManager.wallet
val coinAmount = wallet.amounts[AmountType.Coin]?.value
if (coinAmount != null && !coinAmount.isZero()) {
if (walletState?.getWalletData(wallet.blockchain.currency) == null) {
scope.launch(Dispatchers.Main) {
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(
listOfNotNull(walletManager)))
store.dispatch(WalletAction.MultiWallet.AddBlockchain(
wallet.blockchain
))
store.dispatch(WalletAction.LoadWallet.Success(wallet))
}
}
}
} catch (exception: Exception) {
}
}
}
}
}
is WalletAction.MultiWallet.FindTokensInUse -> {
val walletManager = walletState?.getWalletManager(Blockchain.Ethereum.currency)
?: return

View file

@ -18,7 +18,7 @@ class MultiWalletReducer {
return when (action) {
is WalletAction.MultiWallet.AddWalletManagers -> {
state.copy(
walletManagers = action.walletManagers
walletManagers = state.walletManagers + action.walletManagers
)
}
is WalletAction.MultiWallet.AddBlockchains -> {
@ -160,6 +160,8 @@ class MultiWalletReducer {
is WalletAction.MultiWallet.SetPrimaryToken ->
state.copy(primaryToken = action.token)
is WalletAction.MultiWallet.FindTokensInUse -> state
is WalletAction.MultiWallet.FindBlockchainsInUse -> state
is WalletAction.MultiWallet.SaveCurrencies -> state
}
}
}

View file

@ -125,14 +125,11 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
val wallets = newState.replaceSomeWallets(newWallets)
newState = newState.copy(wallets = wallets)
}
}
is WalletAction.LoadWallet.Success -> newState = onWalletLoadedReducer.reduce(action.wallet, newState)
is WalletAction.UpdateWallet.Success -> {
newState = onWalletLoadedReducer.reduce(action.wallet, newState)
// newState = newState.copy(updatingWallet = newState.pendingTransactions.isNotEmpty())
}
is WalletAction.LoadWallet.NoAccount -> {
val walletData = newState.getWalletData(action.wallet.blockchain.currency)?.copy(
currencyData = BalanceWidgetData(
@ -193,21 +190,6 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
newState = newState.copy(cardImage = cardImage)
}
// is WalletAction.UpdateWallet -> {
// if (store.state.walletState.state == ProgressState.Done) {
// newState = newState.copy(updatingWallet = true)
// }
// }
// is WalletAction.UpdateWallet.ScheduleUpdatingWallet ->
// newState = newState.copy(updatingWallet = true)
// is WalletAction.UpdateWallet.Failure -> newState = newState.copy(updatingWallet = false)
// is WalletAction.LoadFiatRate -> {
// newState.copy(currencyData = newState.currencyData.copy(
// fiatAmount = null,
// token = newState.currencyData.token?.copy(fiatAmount = null))
// )
// }
is WalletAction.LoadFiatRate.Success ->
newState = setNewFiatRate(action.fiatRate, state.globalState.appCurrency, newState)
is WalletAction.LoadArtwork -> {