Updated on 2026-08-14

This commit is contained in:
Tangem 2024-01-31 14:20:41 +03:00
commit 907e239a8a
32 changed files with 152 additions and 96 deletions

View file

@ -42,7 +42,6 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
globalState.copy(scanResponse = action.scanResponse)
}
is GlobalAction.ChangeAppCurrency -> {
appStateHolder.appFiatCurrency = action.appCurrency
globalState.copy(appCurrency = action.appCurrency)
}
is GlobalAction.RestoreAppCurrency.Success -> {

View file

@ -20,7 +20,7 @@ object FoundTokenConverter : Converter<CoinsResponse.Coin, FoundToken> {
network = value.networks.firstOrNull()?.let { network ->
FoundToken.Network(
id = network.networkId,
address = requireNotNull(network.contractAddress),
contractAddress = requireNotNull(network.contractAddress),
decimalCount = requireNotNull(network.decimalCount).toString(),
)
} ?: error("Found token networks is empty"),

View file

@ -22,9 +22,9 @@ data class FoundToken(
/**
* Found token network
*
* @property id id
* @property address address
* @property decimalCount decimal count
* @property id id
* @property contractAddress address
* @property decimalCount decimal count
*/
data class Network(val id: String, val address: String, val decimalCount: String)
data class Network(val id: String, val contractAddress: String, val decimalCount: String)
}

View file

@ -827,11 +827,13 @@ internal class AddCustomTokenViewModel @Inject constructor(
val currency = when (getCustomTokenType()) {
CustomTokenType.TOKEN -> {
val contractAddress = foundToken?.network?.contractAddress
?: uiState.form.contractAddressInputField.value
CustomCurrency.CustomToken(
token = Token(
name = uiState.form.tokenNameInputField.value,
symbol = uiState.form.tokenSymbolInputField.value,
contractAddress = uiState.form.contractAddressInputField.value,
contractAddress = contractAddress,
decimals = requireNotNull(uiState.form.decimalsInputField.value.toIntOrNull()),
id = foundToken?.id,
),

View file

@ -7,6 +7,7 @@ import com.tangem.common.core.TangemSdkError
import com.tangem.common.core.UserCodeRequestPolicy
import com.tangem.common.extensions.guard
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.Basic
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.extensions.TextReference
@ -22,8 +23,6 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.legacy.isLockedSync
import com.tangem.tap.*
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.core.analytics.models.AnalyticsParam as CoreAnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchOnMain
@ -48,6 +47,7 @@ import kotlinx.coroutines.withContext
import org.rekotlin.Action
import org.rekotlin.Middleware
import timber.log.Timber
import com.tangem.core.analytics.models.AnalyticsParam as CoreAnalyticsParam
class DetailsMiddleware {
private val eraseWalletMiddleware = EraseWalletMiddleware()
@ -522,7 +522,6 @@ class DetailsMiddleware {
onWalletNotCreated = {
// No need to rollback policy, continue with the policy set before the card scan
store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Success)
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet))
},
disclaimerWillShow = {
store.dispatchOnMain(NavigationAction.PopBackTo())

View file

@ -101,7 +101,17 @@ internal class SaveWalletMiddleware {
val isFirstSavedWallet = !userWalletsListManager.hasUserWallets
saveAccessCodeIfNeeded(state.backupInfo?.accessCode, userWallet.cardsInWallet)
.flatMap { userWalletsListManager.save(userWallet, canOverride = true) }
.flatMap {
// Save wallet only at first time (SaveWalletBottomSheet).
// Otherwise (Example, add new wallet in Details) userWalletsListManager.wallets subscribers will
// receive useless updates.
// See: OnboardingHelper.trySaveWalletAndNavigateToWalletScreen()
if (isFirstSavedWallet) {
userWalletsListManager.save(userWallet, canOverride = true)
} else {
CompletionResult.Success(Unit)
}
}
.doOnFailure { error ->
store.dispatchWithMain(SaveWalletAction.Save.Error(error))
}
@ -118,8 +128,8 @@ internal class SaveWalletMiddleware {
)
}
store.dispatchWithMain(SaveWalletAction.Save.Success)
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet))
store.dispatchOnMain(SaveWalletAction.Save.Success)
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
}
}
}

View file

@ -183,12 +183,14 @@ class ReceiptReducer : SendInternalReducer {
return ReceiptTokenCrypto("0", feeValue.stripZeroPlainString(), "0", symbols)
}
val tokensToSend = amountState.amountToSendCrypto
val amountType = amountState.typeOfAmount
val currencyConverter = when {
amountType is AmountType.Token && sendState.feeIsConvertible() -> sendState.tokenConverter
amountType is AmountType.Coin && sendState.feeIsConvertible() -> sendState.coinConverter
else -> null
}
return if (sendState.currencyIsConvertible() && sendState.feeIsConvertible()) {
val currencyConverter = when (amountState.typeOfAmount) {
is AmountType.Token -> sendState.tokenConverter!!
else -> sendState.coinConverter!!
}
return if (currencyConverter != null) {
val currencyFiat = currencyConverter.toFiatUnscaled(tokensToSend)
val feeFiat = sendState.customFeeConverter!!.toFiatUnscaled(feeValue)
val totalFiat = currencyFiat.plus(feeFiat)
@ -218,11 +220,14 @@ class ReceiptReducer : SendInternalReducer {
val tokensToSend = amountState.amountToSendCrypto
return if (sendState.currencyIsConvertible() && sendState.feeIsConvertible()) {
val currencyConverter = when (amountState.typeOfAmount) {
is AmountType.Token -> sendState.tokenConverter!!
else -> sendState.coinConverter!!
}
val amountType = amountState.typeOfAmount
val currencyConverter = when {
amountType is AmountType.Token && sendState.feeIsConvertible() -> sendState.tokenConverter
amountType is AmountType.Coin && sendState.feeIsConvertible() -> sendState.coinConverter
else -> null
}
return if (currencyConverter != null) {
val feeFiat = sendState.customFeeConverter!!.toFiatUnscaled(feeCoin)
val amountFiat = currencyConverter.toFiatUnscaled(tokensToSend)
val totalFiat = amountFiat.plus(feeFiat)

View file

@ -102,8 +102,6 @@ data class SendState(
fun coinIsConvertible(): Boolean = coinConverter != null
fun tokenIsConvertible(): Boolean = tokenConverter != null
fun currencyIsConvertible(): Boolean = coinConverter != null || tokenConverter != null
fun feeIsConvertible(): Boolean = customFeeConverter != null
fun mainCurrencyCanBeSwitched(): Boolean {

View file

@ -25,7 +25,12 @@ internal object CoinsResponseConverter : Converter<CoinsResponse, List<Token>> {
networks = token.networks.mapNotNull { network ->
val blockchain = Blockchain.fromNetworkId(network.networkId) ?: return@mapNotNull null
if (!blockchain.canHandleTokens()) return@mapNotNull null
// filter tokens, if contractAddress != null, assume that it is a token
if (network.contractAddress != null &&
!blockchain.canHandleTokens()
) {
return@mapNotNull null
}
Token.Network(
id = network.networkId,

View file

@ -3,7 +3,6 @@ package com.tangem.tap.proxy
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.navigation.ReduxNavController
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.redux.ReduxStateHolder
@ -43,7 +42,6 @@ class AppStateHolder @Inject constructor() : WalletsStateHolder, ReduxNavControl
var scanResponse: ScanResponse? = null
var mainStore: Store<AppState>? = null
var tangemSdkManager: TangemSdkManager? = null
var appFiatCurrency: AppCurrency = AppCurrency.Default
var exchangeService: ExchangeService? = null
fun getActualCard(): CardDTO? {

View file

@ -16,13 +16,11 @@ import com.tangem.lib.crypto.models.Currency
import com.tangem.lib.crypto.models.Currency.NativeToken
import com.tangem.lib.crypto.models.Currency.NonNativeToken
import com.tangem.lib.crypto.models.ProxyAmount
import com.tangem.lib.crypto.models.ProxyFiatCurrency
import com.tangem.tap.userWalletsListManager
import timber.log.Timber
import java.math.BigDecimal
class UserWalletManagerImpl(
private val appStateHolder: AppStateHolder,
private val walletManagersFacade: WalletManagersFacade,
private val currenciesRepository: CurrenciesRepository,
private val userWalletsStore: UserWalletsStore,
@ -171,15 +169,6 @@ class UserWalletManagerImpl(
return blockchain.currency
}
override fun getUserAppCurrency(): ProxyFiatCurrency {
val appCurrency = appStateHolder.appFiatCurrency
return ProxyFiatCurrency(
code = appCurrency.code,
name = appCurrency.name,
symbol = appCurrency.symbol,
)
}
@Throws(IllegalArgumentException::class)
private suspend fun getActualWalletManager(blockchain: Blockchain, derivationPath: String?): WalletManager {
val selectedUserWallet = requireNotNull(

View file

@ -30,13 +30,11 @@ internal object ProxyModule {
@Provides
@Singleton
fun provideUserWalletManager(
appStateHolder: AppStateHolder,
walletManagersFacade: WalletManagersFacade,
currenciesRepository: CurrenciesRepository,
userWalletsStore: UserWalletsStore,
): UserWalletManager {
return UserWalletManagerImpl(
appStateHolder = appStateHolder,
walletManagersFacade = walletManagersFacade,
currenciesRepository = currenciesRepository,
userWalletsStore = userWalletsStore,