Updated on 2026-08-14
This commit is contained in:
parent
f46e75a676
commit
db391edfe8
6 changed files with 100 additions and 86 deletions
|
|
@ -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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
)
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
ext.versions = [
|
||||
kotlin : '1.5.0',
|
||||
kotlin : '1.5.10',
|
||||
build_gradle: '4.2.1',
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue