Updated on 2026-08-14

This commit is contained in:
Tangem 2022-03-23 20:49:07 +03:00
parent 0835b34e97
commit de03cc28b6
3 changed files with 77 additions and 29 deletions

View file

@ -34,6 +34,7 @@ data class WalletState(
val mainWarningsList: List<WarningMessage> = mutableListOf(),
val wallets: List<WalletData> = emptyList(),
val walletManagers: List<WalletManager> = emptyList(),
val walletManagersThrottling: MutableMap<Blockchain, Long> = mutableMapOf(),
val isMultiwalletAllowed: Boolean = false,
val cardCurrency: CryptoCurrencyName? = null,
val selectedWallet: Currency? = null,
@ -54,8 +55,8 @@ data class WalletState(
val primaryWallet = if (wallets.isNotEmpty()) wallets[0] else null
val shouldShowDetails: Boolean =
primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard &&
primaryWallet?.currencyData?.status != BalanceStatus.UnknownBlockchain
primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard &&
primaryWallet?.currencyData?.status != BalanceStatus.UnknownBlockchain
val blockchains: List<Blockchain>
get() = walletManagers.map { it.wallet.blockchain }
@ -63,6 +64,8 @@ data class WalletState(
val currencies: List<Currency>
get() = wallets.mapNotNull { it.currency }
val throttlingDuration = 10000L
fun getWalletManager(token: Token?): WalletManager? {
if (token == null) return null
return walletManagers.find { it.wallet.blockchain == token.blockchain }
@ -101,10 +104,10 @@ data class WalletState(
if (!isPrimaryCurrency(walletData)) {
val walletManager = getWalletManager(walletData.currency)
?: return true
?: return true
if (walletData.currency is Currency.Blockchain &&
walletManager.cardTokens.isNotEmpty()
walletManager.cardTokens.isNotEmpty()
) {
return false
}
@ -113,22 +116,22 @@ data class WalletState(
if (walletData.currency is Currency.Blockchain) {
return wallet.recentTransactions.toPendingTransactions(wallet.address).isEmpty() &&
wallet.amounts.toSendableAmounts().isEmpty()
wallet.amounts.toSendableAmounts().isEmpty()
} else if (walletData.currency is Currency.Token) (
return wallet.recentTransactions.toPendingTransactionsForToken(
walletData.currency.token, wallet.address).isEmpty()
&& wallet.amounts[AmountType.Token(token = walletData.currency.token)]
?.isAboveZero() != true
)
return wallet.recentTransactions.toPendingTransactionsForToken(
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)
walletData.currency.blockchain == store.state.walletState.primaryBlockchain)
|| (walletData.currency is Currency.Token &&
walletData.currency.token == store.state.walletState.primaryToken)
}
fun replaceWalletInWallets(walletData: WalletData?): List<WalletData> {
@ -149,7 +152,7 @@ data class WalletState(
val remainingWallets: MutableList<WalletData> = newWallets.toMutableList()
val updatedWallets = wallets.map { wallet ->
val newWallet = newWallets
.firstOrNull { wallet.currency == it.currency }
.firstOrNull { wallet.currency == it.currency }
if (newWallet == null) {
wallet
} else {
@ -176,9 +179,15 @@ data class WalletState(
fun addWalletManagers(newWalletManagers: List<WalletManager>): WalletState {
val updatedWalletManagers = this.walletManagers +
newWalletManagers.filterNot { this.blockchains.contains(it.wallet.blockchain) }
newWalletManagers.filterNot { this.blockchains.contains(it.wallet.blockchain) }
return copy(walletManagers = updatedWalletManagers)
}
fun isThrottling(walletManager: WalletManager): Boolean {
val inThrottlingUpTo = walletManagersThrottling[walletManager.wallet.blockchain] ?: return false
val diff = System.currentTimeMillis() - inThrottlingUpTo
return diff < 0
}
}
sealed class WalletDialog : StateDialog {

View file

@ -29,9 +29,7 @@ import com.tangem.tap.network.NetworkStateChanged
import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.tap.tangemSdkManager
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.*
import org.rekotlin.Action
import org.rekotlin.DispatchFunction
import org.rekotlin.Middleware
@ -61,14 +59,32 @@ class WalletMiddleware {
is WalletAction.Warnings -> warningsMiddleware.handle(action, globalState)
is WalletAction.MultiWallet -> multiWalletMiddleware.handle(action, walletState, globalState)
is WalletAction.LoadWallet -> {
scope.launch {
if (action.blockchain == null) {
walletState.walletManagers.map { walletManager ->
async { globalState.tapWalletManager.loadWalletData(walletManager) }
}.awaitAll()
} else {
val walletManager = walletState.getWalletManager(action.blockchain)
walletManager?.let { globalState.tapWalletManager.loadWalletData(it) }
if (action.blockchain == null) {
val throttledWalletManagers = walletState.walletManagers.filter { walletState.isThrottling(it) }
val freeWalletManagers = walletState.walletManagers.filter { !walletState.isThrottling(it) }
scope.launch {
freeWalletManagers.map { walletManager ->
async { globalState.tapWalletManager.loadWalletData(walletManager) }
}.awaitAll()
delay(500)
launch(Dispatchers.Main) {
throttledWalletManagers.forEach { store.dispatch(WalletAction.LoadWallet.Success(it.wallet)) }
}
}
} else {
val walletManager = walletState.getWalletManager(action.blockchain) ?: return
scope.launch {
if (walletState.isThrottling(walletManager)) {
delay(500)
launch(Dispatchers.Main) {
store.dispatch(WalletAction.LoadWallet.Success(walletManager.wallet))
}
} else {
globalState.tapWalletManager.loadWalletData(walletManager)
}
}
}
}
@ -230,12 +246,12 @@ class WalletMiddleware {
when (currency) {
is Currency.Blockchain -> {
val amountToSend = amounts?.find { it.currencySymbol == currency.blockchain.currency }
?: return WalletAction.Send.ChooseCurrency(amounts)
?: 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)
?: return WalletAction.Send.ChooseCurrency(amounts)
prepareSendActionForToken(amountToSend, state, selectedWalletData, wallet, walletManager)
}
}

View file

@ -94,8 +94,20 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
}
is WalletAction.LoadWallet -> {
if (action.blockchain == null) {
val wallets = newState.wallets.map { wallet ->
// update throttling
val updatedThrottling = newState.walletManagersThrottling
newState.walletManagers.forEach {
val now = System.currentTimeMillis()
val currentThrottling = newState.walletManagersThrottling[it.wallet.blockchain] ?: 0L
if (currentThrottling == 0L || currentThrottling < now) {
val newThrottlingUpTo = now + newState.throttlingDuration
updatedThrottling[it.wallet.blockchain] = newThrottlingUpTo
}
}
newState = newState.copy(walletManagersThrottling = updatedThrottling)
val wallets = newState.wallets.map { wallet ->
wallet.copy(
currencyData = wallet.currencyData.copy(
status = BalanceStatus.Loading,
@ -113,6 +125,17 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
} else {
val walletManager = newState.getWalletManager(action.blockchain) ?: return newState
val blockchain = walletManager.wallet.blockchain
// update throttling
val now = System.currentTimeMillis()
val currentThrottling = newState.walletManagersThrottling[blockchain] ?: 0L
if (currentThrottling == 0L || currentThrottling < now) {
val newThrottlingUpTo = now + newState.throttlingDuration
val newMap = newState.walletManagersThrottling.toMutableMap()
newMap[blockchain] = newThrottlingUpTo
newState = newState.copy(walletManagersThrottling = newMap)
}
val currencies = listOf(Currency.Blockchain(blockchain)) +
walletManager.cardTokens.map { Currency.Token(it) }
val newWallets = newState.wallets.filter { currencies.contains(it.currency) }