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

@ -405,7 +405,7 @@
{
"id" : "vechain",
"symbol" : "VET",
"name" : "Vechain",
"name" : "VeChain",
"networks" : [
{
"networkId" : "vechain/test"
@ -419,7 +419,7 @@
"networks": [
{
"networkId": "vechain/test",
"contractAddress": "0x0000000000000000000000000000456E65726779",
"contractAddress": "0x0000000000000000000000000000456e65726779",
"decimalCount": 18
}
]

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,

View file

@ -52,7 +52,7 @@ internal class NetworkStatusFactory {
amounts.firstOrNull { amount ->
amount is CryptoCurrencyAmount.Token &&
currency.id.rawCurrencyId == amount.tokenId &&
currency.contractAddress == amount.tokenContractAddress
currency.contractAddress.equals(amount.tokenContractAddress, ignoreCase = true)
}
}
}

View file

@ -0,0 +1,16 @@
package com.tangem.domain.appcurrency.extenstions
import arrow.core.getOrElse
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
suspend fun GetSelectedAppCurrencyUseCase.unwrap(): AppCurrency {
return this()
.map { maybeAppCurrency ->
maybeAppCurrency.getOrElse { AppCurrency.Default }
}
.firstOrNull()
?: AppCurrency.Default
}

View file

@ -76,8 +76,8 @@ fun Blockchain.Companion.fromNetworkId(networkId: String): Blockchain? {
"decimal/test" -> Blockchain.DecimalTestnet
"xdc-network" -> Blockchain.XDC
"xdc-network/test" -> Blockchain.XDCTestnet
"vechain" -> Blockchain.Vechain
"vechain/test" -> Blockchain.VechainTestnet
"vechain" -> Blockchain.VeChain
"vechain/test" -> Blockchain.VeChainTestnet
"aptos" -> Blockchain.Aptos
"aptos/test" -> Blockchain.AptosTestnet
else -> null
@ -157,8 +157,8 @@ fun Blockchain.toNetworkId(): String {
Blockchain.DecimalTestnet -> "decimal/test"
Blockchain.XDC -> "xdc-network"
Blockchain.XDCTestnet -> "xdc-network/test"
Blockchain.Vechain -> "vechain"
Blockchain.VechainTestnet -> "vechain/test"
Blockchain.VeChain -> "vechain"
Blockchain.VeChainTestnet -> "vechain/test"
Blockchain.Aptos -> "aptos"
Blockchain.AptosTestnet -> "aptos/test"
}
@ -209,7 +209,7 @@ fun Blockchain.toCoinId(): String {
Blockchain.NearTestnet -> "near/test"
Blockchain.Decimal, Blockchain.DecimalTestnet -> "decimal"
Blockchain.XDC, Blockchain.XDCTestnet -> "xdce-crowd-sale"
Blockchain.Vechain, Blockchain.VechainTestnet -> "vechain"
Blockchain.VeChain, Blockchain.VeChainTestnet -> "vechain"
Blockchain.Aptos -> "aptos"
Blockchain.AptosTestnet -> "aptos/test"
Blockchain.Unknown -> "unknown"

View file

@ -552,6 +552,7 @@ class DefaultWalletManagersFacade(
blockchain = blockchain,
derivationPath = derivationPath,
)
val feePaidCurrency = blockchain.feePaidCurrency()
if (walletManager == null) {
Timber.e("Unable to get a wallet manager for blockchain: $blockchain")
@ -560,6 +561,7 @@ class DefaultWalletManagersFacade(
val transactionDataConverter = TransactionDataToTxHistoryItemConverter(
walletAddresses = SdkAddressToAddressConverter.convertList(walletManager.wallet.addresses).toSet(),
feePaidCurrency = feePaidCurrency,
)
return walletManager.wallet.recentTransactions.mapNotNull(transactionDataConverter::convert)

View file

@ -1,8 +1,6 @@
package com.tangem.domain.walletmanager.utils
import com.tangem.blockchain.common.Amount
import com.tangem.blockchain.common.TransactionData
import com.tangem.blockchain.common.TransactionStatus
import com.tangem.blockchain.common.*
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.walletmanager.model.Address
import com.tangem.utils.converter.Converter
@ -18,6 +16,7 @@ import java.math.BigDecimal
*/
internal class TransactionDataToTxHistoryItemConverter(
private val walletAddresses: Set<Address>,
private val feePaidCurrency: FeePaidCurrency,
) : Converter<TransactionData, TxHistoryItem?> {
override fun convert(value: TransactionData): TxHistoryItem? {
@ -48,12 +47,30 @@ internal class TransactionDataToTxHistoryItemConverter(
private fun getTransactionAmountValue(amount: Amount, feeAmount: Amount?): BigDecimal? {
val feeValue = feeAmount?.value ?: BigDecimal.ZERO
val value = amount.value?.plus(feeValue)
val value = amount.value
if (value == null) {
Timber.w("Transaction amount must not be null: ${amount.currencySymbol}")
}
return value
return when (feePaidCurrency) {
FeePaidCurrency.SameCurrency -> value?.plus(feeValue)
FeePaidCurrency.Coin -> {
if (amount.type is AmountType.Coin) value?.plus(feeValue) else value
}
is FeePaidCurrency.Token -> {
val token = (amount.type as? AmountType.Token)?.token ?: return value
if (isSameToken(token, feePaidCurrency.token)) {
value?.plus(feeValue)
} else {
value
}
}
}
}
private fun isSameToken(amountToken: Token, feeToken: Token): Boolean {
return amountToken.contractAddress.equals(feeToken.contractAddress, ignoreCase = true) &&
amountToken.symbol.equals(feeToken.symbol, ignoreCase = true)
}
}

View file

@ -15,24 +15,28 @@ internal class UpdateWalletManagerResultFactory {
fun getResult(walletManager: WalletManager): UpdateWalletManagerResult.Verified {
val wallet = walletManager.wallet
val addresses = getAvailableAddresses(wallet.addresses)
val feePaidCurrency = wallet.blockchain.feePaidCurrency()
val txHistoryItemConverter = TransactionDataToTxHistoryItemConverter(addresses, feePaidCurrency)
return UpdateWalletManagerResult.Verified(
selectedAddress = wallet.address,
addresses = addresses,
currenciesAmounts = getTokensAmounts(wallet.amounts.values.toSet()),
currentTransactions = getCurrentTransactions(addresses, wallet.recentTransactions.toSet()),
currentTransactions = getCurrentTransactions(txHistoryItemConverter, wallet.recentTransactions.toSet()),
)
}
fun getDemoResult(walletManager: WalletManager, demoAmount: Amount): UpdateWalletManagerResult.Verified {
val wallet = walletManager.wallet
val addresses = getAvailableAddresses(wallet.addresses)
val feePaidCurrency = wallet.blockchain.feePaidCurrency()
val txHistoryItemConverter = TransactionDataToTxHistoryItemConverter(addresses, feePaidCurrency)
return UpdateWalletManagerResult.Verified(
selectedAddress = wallet.address,
addresses = addresses,
currenciesAmounts = getDemoTokensAmounts(demoAmount, walletManager.cardTokens),
currentTransactions = getCurrentTransactions(addresses, wallet.recentTransactions.toSet()),
currentTransactions = getCurrentTransactions(txHistoryItemConverter, wallet.recentTransactions.toSet()),
)
}
@ -81,14 +85,19 @@ internal class UpdateWalletManagerResultFactory {
}
private fun getCurrentTransactions(
walletAddresses: Set<Address>,
txHistoryItemConverter: TransactionDataToTxHistoryItemConverter,
recentTransactions: Set<TransactionData>,
): Set<CryptoCurrencyTransaction> {
val unconfirmedTransactions = recentTransactions.filter {
it.status == TransactionStatus.Unconfirmed
}
return unconfirmedTransactions.mapNotNullTo(hashSetOf()) { createCurrencyTransaction(walletAddresses, it) }
return unconfirmedTransactions.mapNotNullTo(hashSetOf()) {
createCurrencyTransaction(
txHistoryItemConverter = txHistoryItemConverter,
data = it,
)
}
}
private fun createCurrencyAmount(amount: Amount): CryptoCurrencyAmount? {
@ -106,10 +115,9 @@ internal class UpdateWalletManagerResultFactory {
}
private fun createCurrencyTransaction(
walletAddresses: Set<Address>,
txHistoryItemConverter: TransactionDataToTxHistoryItemConverter,
data: TransactionData,
): CryptoCurrencyTransaction? {
val txHistoryItemConverter = TransactionDataToTxHistoryItemConverter(walletAddresses)
return when (val type = data.amount.type) {
is AmountType.Coin -> {
val txHistoryItem = txHistoryItemConverter.convert(data) ?: return null

View file

@ -81,7 +81,18 @@ class AddCryptoCurrenciesUseCase(
.filter { hasCoinForToken(existingCurrencies, it) }
.mapTo(hashSetOf(), CryptoCurrency.Token::network)
catch({ networksRepository.getNetworkStatusesSync(userWalletId, networksToUpdate, refresh = true) }) {
val networkToUpdate = currenciesToAdd.map { it.network }
.subtract(existingCurrencies.map { it.network }.toSet())
catch(
{
networksRepository.getNetworkStatusesSync(
userWalletId = userWalletId,
networks = networksToUpdate + networkToUpdate,
refresh = true,
)
},
) {
raise(AddCurrencyError.DataError(it))
}
}

View file

@ -200,7 +200,8 @@ class GetCurrencyWarningsUseCase(
}
feePaidCurrency is FeePaidCurrency.Token -> {
val feePaidTokenBalance = feePaidCurrency.balance
if (!tokenStatus.value.amount.isZero() && feePaidTokenBalance.isZero()) {
val amount = tokenStatus.value.amount ?: return null
if (!amount.isZero() && feePaidTokenBalance.isZero()) {
constructTokenBalanceNotEnoughWarning(
userWalletId = userWalletId,
tokenStatus = tokenStatus,
@ -222,7 +223,9 @@ class GetCurrencyWarningsUseCase(
val token = currenciesRepository
.getMultiCurrencyWalletCurrenciesSync(userWalletId)
.find {
it is CryptoCurrency.Token && it.contractAddress.equals(feePaidToken.contractAddress, ignoreCase = true)
it is CryptoCurrency.Token &&
it.contractAddress.equals(feePaidToken.contractAddress, ignoreCase = true) &&
it.network.derivationPath == tokenStatus.currency.network.derivationPath
}
return if (token != null) {
CryptoCurrencyWarning.CustomTokenNotEnoughForFee(

View file

@ -19,6 +19,7 @@ dependencies {
kapt(deps.hilt.kapt)
/** Domain */
implementation(projects.domain.appCurrency)
implementation(projects.domain.models)
implementation(projects.domain.tokens)
implementation(projects.domain.tokens.models)

View file

@ -7,6 +7,9 @@ import com.tangem.blockchain.common.AmountType
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.extenstions.unwrap
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.domain.tokens.GetCryptoCurrencyStatusesSyncUseCase
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
@ -55,6 +58,7 @@ internal class SwapInteractorImpl @Inject constructor(
private val quotesRepository: QuotesRepository,
private val dispatcher: CoroutineDispatcherProvider,
private val swapTransactionRepository: SwapTransactionRepository,
private val appCurrencyRepository: AppCurrencyRepository,
private val initialToCurrencyResolver: InitialToCurrencyResolver,
) : SwapInteractor {
@ -62,6 +66,10 @@ internal class SwapInteractorImpl @Inject constructor(
EstimateFeeUseCase(walletManagersFacade, dispatcher)
}
private val getSelectedAppCurrencyUseCase by lazy(LazyThreadSafetyMode.NONE) {
GetSelectedAppCurrencyUseCase(appCurrencyRepository)
}
private val swapCurrencyConverter = SwapCurrencyConverter()
private val amountFormatter = AmountFormatter()
private val hundredPercent = BigInteger("100")
@ -638,8 +646,8 @@ internal class SwapInteractorImpl @Inject constructor(
type = AmountType.Coin,
)
return when (blockchain) {
Blockchain.Ethereum -> {
return when {
blockchain.isEvm() -> {
val feeAmountWithDecimals = feeAmountValue.movePointRight(fee.decimals)
Fee.Ethereum(
amount = feeAmount,
@ -647,11 +655,12 @@ internal class SwapInteractorImpl @Inject constructor(
gasPrice = (feeAmountWithDecimals / fee.gasLimit.toBigDecimal()).toBigInteger(),
)
}
Blockchain.Vechain -> Fee.Vechain(
blockchain == Blockchain.VeChain -> Fee.VeChain(
amount = feeAmount,
gasPriceCoef = fee.gasLimit,
gasPriceCoef = Fee.VeChain.getGasPriceCoef(fee.gasLimit.toLong(), fee.feeValue),
gasLimit = fee.gasLimit.toLong(),
)
Blockchain.Aptos -> {
blockchain == Blockchain.Aptos -> {
Fee.Aptos(
amount = feeAmount,
gasUnitPrice = fee.feeValue.toLong() / fee.gasLimit,
@ -754,8 +763,8 @@ internal class SwapInteractorImpl @Inject constructor(
)
}
private fun createEmptyAmountState(): SwapState {
val appCurrency = userWalletManager.getUserAppCurrency()
private suspend fun createEmptyAmountState(): SwapState {
val appCurrency = getSelectedAppCurrencyUseCase.unwrap()
return SwapState.EmptyAmountState(
zeroAmountEquivalent = BigDecimal.ZERO.toFiatString(
rateValue = BigDecimal.ONE,
@ -947,7 +956,7 @@ internal class SwapInteractorImpl @Inject constructor(
}
private suspend fun getFormattedFiatFees(networkId: String, vararg fees: BigDecimal): List<String> {
val appCurrency = userWalletManager.getUserAppCurrency()
val appCurrency = getSelectedAppCurrencyUseCase.unwrap()
val nativeToken = repository.getNativeTokenForNetwork(networkId)
val rates = getQuotes(nativeToken.id)
return rates[nativeToken.id]?.fiatRate?.let { rate ->
@ -1345,7 +1354,7 @@ internal class SwapInteractorImpl @Inject constructor(
return when (this) {
is Fee.Common -> 0
is Fee.Ethereum -> gasLimit.toInt()
is Fee.Vechain -> gasPriceCoef
is Fee.VeChain -> gasLimit.toInt()
is Fee.Aptos -> amount.longValue?.div(gasUnitPrice)?.toInt() ?: 0
}
}

View file

@ -1,5 +1,6 @@
package com.tangem.feature.swap.domain.di
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.demo.IsDemoCardUseCase
@ -40,6 +41,7 @@ class SwapDomainModule {
@SwapScope sendTransactionUseCase: SendTransactionUseCase,
quotesRepository: QuotesRepository,
swapTransactionRepository: SwapTransactionRepository,
appCurrencyRepository: AppCurrencyRepository,
walletManagersFacade: WalletManagersFacade,
coroutineDispatcherProvider: CoroutineDispatcherProvider,
initialToCurrencyResolver: InitialToCurrencyResolver,
@ -56,6 +58,7 @@ class SwapDomainModule {
walletManagersFacade = walletManagersFacade,
dispatcher = coroutineDispatcherProvider,
swapTransactionRepository = swapTransactionRepository,
appCurrencyRepository = appCurrencyRepository,
initialToCurrencyResolver = initialToCurrencyResolver,
)
}

View file

@ -55,7 +55,7 @@ internal class TokenDetailsSwapTransactionsStateConverter(
val toAmount = transaction.toCryptoAmount
val fromAmount = transaction.fromCryptoAmount
val toFiatAmount = quotes.firstOrNull {
it.rawCurrencyId == swapCurrency.fromCryptoCurrency.id.rawCurrencyId
it.rawCurrencyId == swapCurrency.toCryptoCurrency.id.rawCurrencyId
}?.fiatRate?.multiply(toAmount)
val fromFiatAmount = quotes.firstOrNull {
it.rawCurrencyId == swapCurrency.fromCryptoCurrency.id.rawCurrencyId

View file

@ -83,7 +83,7 @@ sealed class WalletScreenAnalyticsEvent {
object BackupYourWallet : MainScreen(event = "Notice - Backup Your Wallet")
object UnlockAllWithFaceID : MainScreen(event = "Button - Unlock All With Face ID")
object UnlockAllWithBiometrics : MainScreen(event = "Button - Unlock All With Biometrics")
object UnlockWithCardScan : MainScreen(event = "Button - Unlock With Card Scan")

View file

@ -1,9 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.domain
import arrow.core.Either
import arrow.core.getOrElse
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase
import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
@ -38,15 +35,6 @@ internal suspend fun GetPrimaryCurrencyStatusUpdatesUseCase.unwrap(userWalletId:
)
}
internal suspend fun GetSelectedAppCurrencyUseCase.unwrap(): AppCurrency {
return this()
.map { maybeAppCurrency ->
maybeAppCurrency.getOrElse { AppCurrency.Default }
}
.firstOrNull()
?: AppCurrency.Default
}
internal suspend fun GetPrimaryCurrencyStatusUpdatesUseCase.collectLatest(
userWalletId: UserWalletId,
onRight: suspend (CryptoCurrencyStatus) -> Unit,

View file

@ -211,7 +211,7 @@ internal class WalletsUpdateActionResolverV2 @Inject constructor(
override fun toString(): String {
return """
Initialize(
InitializeWallets(
selectedWalletIndex = $selectedWalletIndex,
selectedWallet = ${selectedWallet.walletId},
wallets = ${wallets.joinToString { it.walletId.toString() }}

View file

@ -10,6 +10,7 @@ import com.tangem.core.ui.components.bottomsheets.tokenreceive.mapToAddressModel
import com.tangem.core.ui.extensions.WrappedList
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.extenstions.unwrap
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.redux.ReduxStateHolder

View file

@ -231,7 +231,7 @@ internal class WalletWarningsClickIntentsImplementer @Inject constructor(
}
override fun onUnlockWalletClick() {
analyticsEventHandler.send(MainScreen.UnlockAllWithFaceID)
analyticsEventHandler.send(MainScreen.UnlockAllWithBiometrics)
viewModelScope.launch(dispatchers.main) {
unlockWalletsUseCase(throwIfNotAllWalletsUnlocked = true)

View file

@ -85,9 +85,9 @@ spr-client = "3.6.2"
# endregion Other libraries
# region Tangem
tangemBlockchainSdk = "develop-467"
tangemBlockchainSdk = "develop-470"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "develop-319"
tangemCardSdk = "develop-324"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
# endregion Tangem

View file

@ -2,7 +2,6 @@ package com.tangem.lib.crypto
import com.tangem.lib.crypto.models.Currency
import com.tangem.lib.crypto.models.ProxyAmount
import com.tangem.lib.crypto.models.ProxyFiatCurrency
/**
* Provider for user tokens data
@ -67,11 +66,6 @@ interface UserWalletManager {
@Throws(IllegalStateException::class)
fun getNetworkCurrency(networkId: String): String
/**
* Returns selected app currency
*/
fun getUserAppCurrency(): ProxyFiatCurrency
@Throws(IllegalStateException::class)
suspend fun getLastTransactionHash(networkId: String, derivationPath: String?): String?
}