Updated on 2026-08-14
This commit is contained in:
commit
907e239a8a
32 changed files with 152 additions and 96 deletions
|
|
@ -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
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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 -> {
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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? {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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() }}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue