Updated on 2026-08-14

This commit is contained in:
Tangem 2021-06-10 16:54:33 +03:00
parent f46e75a676
commit db391edfe8
6 changed files with 100 additions and 86 deletions

View file

@ -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()))
}
}

View file

@ -13,11 +13,11 @@ import com.tangem.tap.network.createMoshi
class CurrenciesRepository(val context: Application) {
private val moshi = createMoshi()
private val tokensAdapter: JsonAdapter<List<TokenDao>> = moshi.adapter(
Types.newParameterizedType(List::class.java, TokenDao::class.java)
private val tokensAdapter: JsonAdapter<Set<TokenDao>> = moshi.adapter(
Types.newParameterizedType(Set::class.java, TokenDao::class.java)
)
private val blockchainsAdapter: JsonAdapter<List<Blockchain>> = moshi.adapter(
Types.newParameterizedType(List::class.java, Blockchain::class.java)
private val blockchainsAdapter: JsonAdapter<Set<Blockchain>> = 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<Token> {
private fun loadSavedTokens(cardId: String): Set<Token> {
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<Token>) {
val json = tokensAdapter.toJson(tokens.map { TokenDao.fromToken(it) })
private fun saveTokens(cardId: String, tokens: Set<Token>) {
val json = tokensAdapter.toJson(tokens.map { TokenDao.fromToken(it) }.toSet())
context.rewriteFile(json, getFileNameForTokens(cardId))
}
private fun loadSavedBlockchains(cardId: String): List<Blockchain> {
private fun loadSavedBlockchains(cardId: String): Set<Blockchain> {
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<Blockchain>) {
private fun saveBlockchains(cardId: String, blockchains: Set<Blockchain>) {
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<TokenDao>,
val blockchains: List<Blockchain>
val tokens: Set<TokenDao>,
val blockchains: Set<Blockchain>,
) {
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<Token>,
val blockchains: List<Blockchain>
val tokens: Set<Token>,
val blockchains: Set<Blockchain>,
)

View file

@ -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<WalletData>.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)
}

View file

@ -44,14 +44,17 @@ data class WalletState(
val blockchains: List<Blockchain>
get() = walletManagers.map { it.wallet.blockchain }
val currencies: List<Currency>
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<WalletManager>): WalletState {
val updatedWalletManagers = this.walletManagers +
newWalletManagers.filterNot { this.blockchains.contains(it.wallet.blockchain) }
return copy(walletManagers = updatedWalletManagers)
}
}
sealed class WalletDialog: StateDialog {

View file

@ -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
)
)
}

View file

@ -1,4 +1,4 @@
ext.versions = [
kotlin : '1.5.0',
kotlin : '1.5.10',
build_gradle: '4.2.1',
]