Updated on 2026-08-14
This commit is contained in:
parent
5db8900311
commit
bba00924d4
18 changed files with 110 additions and 314 deletions
|
|
@ -1,79 +0,0 @@
|
|||
package com.tangem.tap.proxy
|
||||
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import com.tangem.lib.crypto.models.ProxyAmount
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
||||
class UserWalletManagerImpl(
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val getSelectedWalletUseCase: GetSelectedWalletUseCase,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : UserWalletManager {
|
||||
|
||||
override fun getWalletId(): String {
|
||||
val selectedUserWallet = requireNotNull(
|
||||
getSelectedWalletUseCase.sync().getOrNull(),
|
||||
) { "selectedUserWallet shouldn't be null" }
|
||||
return selectedUserWallet.walletId.stringValue
|
||||
}
|
||||
|
||||
override suspend fun hideAllTokens() {
|
||||
// FIXME: Used only in Tester Actions
|
||||
Timber.w("Not implemented")
|
||||
}
|
||||
|
||||
override suspend fun getWalletAddress(networkId: String, derivationPath: String?): String {
|
||||
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
|
||||
val walletManager = getActualWalletManager(blockchain, derivationPath)
|
||||
return walletManager.wallet.address
|
||||
}
|
||||
|
||||
override suspend fun getLastTransactionHash(networkId: String, derivationPath: String?): String? {
|
||||
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
|
||||
val walletManager = getActualWalletManager(blockchain, derivationPath)
|
||||
return walletManager.wallet.recentTransactions
|
||||
.lastOrNull { it.hash?.isNotEmpty() == true }
|
||||
?.hash
|
||||
}
|
||||
|
||||
override suspend fun getNativeTokenBalance(networkId: String, derivationPath: String?): ProxyAmount? {
|
||||
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
|
||||
val walletManager = getActualWalletManager(blockchain, derivationPath)
|
||||
return walletManager.wallet.amounts.firstNotNullOfOrNull { amountEntry ->
|
||||
amountEntry.takeIf { amountEntry.key is AmountType.Coin }
|
||||
}?.value?.let { amount ->
|
||||
ProxyAmount(
|
||||
amount.currencySymbol,
|
||||
amount.value ?: BigDecimal.ZERO,
|
||||
amount.decimals,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IllegalArgumentException::class)
|
||||
private suspend fun getActualWalletManager(blockchain: Blockchain, derivationPath: String?): WalletManager {
|
||||
val selectedUserWallet = requireNotNull(
|
||||
getSelectedWalletUseCase.sync().getOrNull(),
|
||||
) { "userWallet or userWalletsListManager is null" }
|
||||
val walletManager = withContext(dispatchers.io) {
|
||||
walletManagersFacade.getOrCreateWalletManager(
|
||||
selectedUserWallet.walletId,
|
||||
blockchain,
|
||||
derivationPath,
|
||||
)
|
||||
}
|
||||
|
||||
return requireNotNull(walletManager) {
|
||||
"No wallet manager found"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,6 @@
|
|||
package com.tangem.tap.proxy.di
|
||||
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import com.tangem.tap.proxy.UserWalletManagerImpl
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -21,18 +16,4 @@ internal object ProxyModule {
|
|||
fun provideAppStateHolder(): AppStateHolder {
|
||||
return AppStateHolder()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideUserWalletManager(
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
getSelectedWalletUseCase: GetSelectedWalletUseCase,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): UserWalletManager {
|
||||
return UserWalletManagerImpl(
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
getSelectedWalletUseCase = getSelectedWalletUseCase,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -87,6 +87,15 @@ internal class DefaultWalletAccountsFetcher @Inject constructor(
|
|||
store.updateData { response }
|
||||
}
|
||||
|
||||
override suspend fun update(
|
||||
userWalletId: UserWalletId,
|
||||
transform: (GetWalletAccountsResponse?) -> GetWalletAccountsResponse?,
|
||||
) {
|
||||
val store = getAccountsResponseStore(userWalletId = userWalletId)
|
||||
|
||||
store.updateData { transform(it) }
|
||||
}
|
||||
|
||||
override suspend fun push(
|
||||
userWalletId: UserWalletId,
|
||||
accounts: List<WalletAccountDTO>,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ interface WalletAccountsSaver {
|
|||
/** Store wallet accounts [response] by [userWalletId] */
|
||||
suspend fun store(userWalletId: UserWalletId, response: GetWalletAccountsResponse)
|
||||
|
||||
suspend fun update(
|
||||
userWalletId: UserWalletId,
|
||||
transform: (GetWalletAccountsResponse?) -> GetWalletAccountsResponse?,
|
||||
)
|
||||
|
||||
/** Push wallet accounts [body] by [userWalletId] */
|
||||
@Throws
|
||||
suspend fun push(userWalletId: UserWalletId, body: SaveWalletAccountsResponse): GetWalletAccountsResponse?
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.tangem.blockchain.transactionhistory.models.TransactionHistoryRequest
|
|||
import com.tangem.blockchain.yieldsupply.YieldSupplyContractCallDataProviderFactory
|
||||
import com.tangem.blockchainsdk.BlockchainSDKFactory
|
||||
import com.tangem.blockchainsdk.models.UpdateWalletManagerResult
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.blockchainsdk.utils.toNetworkId
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
|
|
@ -623,6 +624,22 @@ internal class DefaultWalletManagersFacade @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun getNativeTokenBalance(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: String,
|
||||
derivationPath: String?,
|
||||
): BigDecimal {
|
||||
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
|
||||
val walletManager = getOrCreateWalletManager(userWalletId, blockchain, derivationPath)
|
||||
|
||||
return walletManager?.wallet?.amounts
|
||||
?.firstNotNullOfOrNull { amountEntry ->
|
||||
amountEntry.takeIf { amountEntry.key is AmountType.Coin }
|
||||
}
|
||||
?.value?.value
|
||||
?: BigDecimal.ZERO
|
||||
}
|
||||
|
||||
override suspend fun getAssetRequirements(
|
||||
userWalletId: UserWalletId,
|
||||
currency: CryptoCurrency,
|
||||
|
|
|
|||
|
|
@ -228,6 +228,13 @@ interface WalletManagersFacade {
|
|||
id: String? = null,
|
||||
): BigDecimal
|
||||
|
||||
@Throws(IllegalStateException::class)
|
||||
suspend fun getNativeTokenBalance(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: String,
|
||||
derivationPath: String?,
|
||||
): BigDecimal
|
||||
|
||||
/**
|
||||
* Get requirements for asset(currency)
|
||||
* @return null if there's no requirement, otherwise [AssetRequirementsCondition].
|
||||
|
|
|
|||
|
|
@ -10,23 +10,23 @@ import com.tangem.domain.models.account.DerivationIndex
|
|||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.feature.referral.domain.errors.ReferralError
|
||||
import com.tangem.feature.referral.domain.models.ReferralData
|
||||
import com.tangem.feature.referral.domain.models.TokenData
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class ReferralInteractorImpl(
|
||||
private val repository: ReferralRepository,
|
||||
private val userWalletManager: UserWalletManager,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val singleAccountSupplier: SingleAccountSupplier,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
) : ReferralInteractor {
|
||||
|
||||
private val tokensForReferral = mutableListOf<TokenData>()
|
||||
|
|
@ -85,13 +85,14 @@ internal class ReferralInteractorImpl(
|
|||
}
|
||||
.onLeft(Timber::e)
|
||||
|
||||
val publicAddress = userWalletManager.getWalletAddress(
|
||||
networkId = tokenData.networkId,
|
||||
derivationPath = cryptoCurrency.network.derivationPath.value,
|
||||
val publicAddress = walletManagersFacade.getDefaultAddress(
|
||||
userWalletId = userWalletId,
|
||||
network = cryptoCurrency.network,
|
||||
)
|
||||
?: error("Address not found: ${cryptoCurrency.network.id}")
|
||||
|
||||
return repository.startReferral(
|
||||
walletId = userWalletManager.getWalletId(),
|
||||
walletId = userWalletId.stringValue,
|
||||
networkId = tokenData.networkId,
|
||||
tokenId = tokenData.id,
|
||||
address = publicAddress,
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ import com.tangem.core.decompose.di.ModelScoped
|
|||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.account.supplier.SingleAccountSupplier
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.feature.referral.domain.ReferralInteractor
|
||||
import com.tangem.feature.referral.domain.ReferralInteractorImpl
|
||||
import com.tangem.feature.referral.domain.ReferralRepository
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -23,21 +23,21 @@ class ReferralDomainModule {
|
|||
@ModelScoped
|
||||
fun provideReferralInteractor(
|
||||
referralRepository: ReferralRepository,
|
||||
userWalletManager: UserWalletManager,
|
||||
derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
getUserWalletUseCase: GetUserWalletUseCase,
|
||||
addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
singleAccountSupplier: SingleAccountSupplier,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
): ReferralInteractor {
|
||||
return ReferralInteractorImpl(
|
||||
repository = referralRepository,
|
||||
userWalletManager = userWalletManager,
|
||||
derivePublicKeysUseCase = derivePublicKeysUseCase,
|
||||
getUserWalletUseCase = getUserWalletUseCase,
|
||||
addCryptoCurrenciesUseCase = addCryptoCurrenciesUseCase,
|
||||
manageCryptoCurrenciesUseCase = manageCryptoCurrenciesUseCase,
|
||||
singleAccountSupplier = singleAccountSupplier,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -50,6 +50,7 @@ import com.tangem.domain.transaction.usecase.gasless.EstimateFeeForGaslessTxUseC
|
|||
import com.tangem.domain.transaction.usecase.gasless.EstimateFeeForTokenUseCase
|
||||
import com.tangem.domain.transaction.usecase.gasless.GetFeeForTokenUseCase
|
||||
import com.tangem.domain.utils.convertToSdkAmount
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.feature.swap.domain.api.SwapRepository
|
||||
import com.tangem.feature.swap.domain.models.ExpressDataError
|
||||
|
|
@ -58,8 +59,6 @@ import com.tangem.feature.swap.domain.models.domain.*
|
|||
import com.tangem.feature.swap.domain.models.toStringWithRightOffset
|
||||
import com.tangem.feature.swap.domain.models.ui.*
|
||||
import com.tangem.lib.crypto.BlockchainUtils.SOLANA_TRANSACTION_SIZE_THRESHOLD_BYTES
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import com.tangem.lib.crypto.models.ProxyAmount
|
||||
import com.tangem.utils.coroutines.runSuspendCatching
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
|
|
@ -72,7 +71,6 @@ import java.math.RoundingMode
|
|||
|
||||
@Suppress("LargeClass", "LongParameterList")
|
||||
internal class SwapInteractorImpl @AssistedInject constructor(
|
||||
private val userWalletManager: UserWalletManager,
|
||||
private val repository: SwapRepository,
|
||||
private val allowPermissionsHandler: AllowPermissionsHandler,
|
||||
private val getMultiCryptoCurrencyStatusUseCase: GetMultiCryptoCurrencyStatusUseCase,
|
||||
|
|
@ -107,6 +105,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
@Assisted private val userWalletId: UserWalletId,
|
||||
) : SwapInteractor {
|
||||
|
||||
|
|
@ -706,11 +705,13 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
)
|
||||
when (feePaidCurrency) {
|
||||
FeePaidCurrency.Coin -> {
|
||||
val nativeBalance = userWalletManager.getNativeTokenBalance(
|
||||
val nativeBalance = walletManagersFacade.getNativeTokenBalance(
|
||||
userWalletId = userWalletId,
|
||||
networkId = fromTokenStatus.currency.network.backendId,
|
||||
derivationPath = fromTokenStatus.currency.network.derivationPath.value,
|
||||
)
|
||||
nativeBalance?.let { it.value - fee }
|
||||
|
||||
nativeBalance - fee
|
||||
}
|
||||
else -> null // it doesnt matter for this fun
|
||||
}
|
||||
|
|
@ -1292,8 +1293,8 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
|
||||
private suspend fun storeLastCryptoCurrencyId(cryptoCurrency: CryptoCurrency) {
|
||||
swapTransactionRepository.storeLastSwappedCryptoCurrencyId(
|
||||
UserWalletId(userWalletManager.getWalletId()),
|
||||
cryptoCurrency.id,
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencyId = cryptoCurrency.id,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -1707,12 +1708,12 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
feeValue: BigDecimal,
|
||||
fromToken: CryptoCurrency,
|
||||
): IncludeFeeInAmount {
|
||||
val tokenForFeeBalance =
|
||||
userWalletManager.getNativeTokenBalance(
|
||||
networkId,
|
||||
fromToken.network.derivationPath.value,
|
||||
) ?: ProxyAmount.empty()
|
||||
val reducedBalance = tokenForFeeBalance.value - reduceBalanceBy
|
||||
val tokenForFeeBalance = walletManagersFacade.getNativeTokenBalance(
|
||||
userWalletId = userWalletId,
|
||||
networkId = networkId,
|
||||
derivationPath = fromToken.network.derivationPath.value,
|
||||
)
|
||||
val reducedBalance = tokenForFeeBalance - reduceBalanceBy
|
||||
val amountWithFee = amount.value + feeValue
|
||||
return when {
|
||||
fromToken is CryptoCurrency.Token -> {
|
||||
|
|
@ -1943,13 +1944,14 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
fromToken: CryptoCurrency,
|
||||
selectedToken: CryptoCurrencyStatus? = null,
|
||||
): Either<ExpressDataError, TransactionFeeResult> = either {
|
||||
val nativeBalance = userWalletManager.getNativeTokenBalance(
|
||||
val nativeBalance = walletManagersFacade.getNativeTokenBalance(
|
||||
userWalletId = userWalletId,
|
||||
networkId = network.backendId,
|
||||
derivationPath = fromToken.network.derivationPath.value,
|
||||
) ?: ProxyAmount.empty()
|
||||
)
|
||||
|
||||
// if native balance is zero - we can't calculate fee
|
||||
if (nativeBalance.value.signum() == 0) {
|
||||
if (nativeBalance.signum() == 0) {
|
||||
raise(ExpressDataError.UnknownError)
|
||||
}
|
||||
|
||||
|
|
@ -1958,7 +1960,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
val amountToSend = createNativeAmountForDex(txAmountValue, fromToken.network)
|
||||
|
||||
// transaction.txValue is always native coin
|
||||
if (nativeBalance.value < amountToSend.value) {
|
||||
if (nativeBalance < amountToSend.value) {
|
||||
error("It's impossible to calculate fee for nativeBalance.value < amountToSend.value")
|
||||
}
|
||||
|
||||
|
|
@ -2107,7 +2109,6 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
permissionState = PermissionDataState.PermissionLoading,
|
||||
)
|
||||
}
|
||||
val derivationPath = fromToken.network.derivationPath.value
|
||||
// setting up amount for approve with given amount for swap [SwapApproveType.Limited]
|
||||
val callData = SmartContractCallDataProviderFactory.getApprovalCallData(
|
||||
spenderAddress = spenderAddress,
|
||||
|
|
@ -2166,7 +2167,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
permissionState = PermissionDataState.PermissionReadyForRequest(
|
||||
currency = fromToken.symbol,
|
||||
amount = INFINITY_SYMBOL,
|
||||
walletAddress = getWalletAddress(networkId, derivationPath),
|
||||
walletAddress = getWalletAddress(fromToken.network),
|
||||
spenderAddress = getTokenAddress(fromToken),
|
||||
requestApproveData = RequestApproveStateData(
|
||||
fee = feeState,
|
||||
|
|
@ -2405,8 +2406,9 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun getWalletAddress(networkId: String, derivationPath: String?): String {
|
||||
return userWalletManager.getWalletAddress(networkId, derivationPath)
|
||||
private suspend fun getWalletAddress(network: Network): String {
|
||||
return walletManagersFacade.getDefaultAddress(userWalletId, network)
|
||||
?: error("Address not found for network: ${network.id}")
|
||||
}
|
||||
|
||||
private fun getTokenAddress(currency: CryptoCurrency): String {
|
||||
|
|
@ -2438,31 +2440,29 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
val percentsToFeeIncrease = BigDecimal.ONE
|
||||
return when (val feePaidCurrency = getFeePaidCurrency(fromTokenStatus.currency)) {
|
||||
FeePaidCurrency.Coin -> {
|
||||
val nativeTokenBalance = userWalletManager.getNativeTokenBalance(
|
||||
networkId,
|
||||
fromTokenStatus.currency.network.derivationPath.value,
|
||||
val nativeTokenBalance = walletManagersFacade.getNativeTokenBalance(
|
||||
userWalletId = userWalletId,
|
||||
networkId = networkId,
|
||||
derivationPath = fromTokenStatus.currency.network.derivationPath.value,
|
||||
)
|
||||
nativeTokenBalance?.let { balance ->
|
||||
val balanceToCheck = when (fromTokenStatus.currency) {
|
||||
is CryptoCurrency.Token -> {
|
||||
balance.value
|
||||
}
|
||||
is CryptoCurrency.Coin -> {
|
||||
// need to check balance minus amount only if amount to swap in native token
|
||||
balance.value.minus(spendAmount.value)
|
||||
}
|
||||
|
||||
val balanceToCheck = when (fromTokenStatus.currency) {
|
||||
is CryptoCurrency.Token -> nativeTokenBalance
|
||||
is CryptoCurrency.Coin -> {
|
||||
// need to check balance minus amount only if amount to swap in native token
|
||||
nativeTokenBalance.minus(spendAmount.value)
|
||||
}
|
||||
if (balanceToCheck > fee.multiply(percentsToFeeIncrease)) {
|
||||
SwapFeeState.Enough
|
||||
} else {
|
||||
val nativeToken = getNativeToken(fromTokenStatus.currency.network.backendId)
|
||||
SwapFeeState.NotEnough(
|
||||
feeCurrency = nativeToken,
|
||||
currencyName = nativeToken.network.name,
|
||||
currencySymbol = nativeToken.symbol,
|
||||
)
|
||||
}
|
||||
} ?: SwapFeeState.NotEnough()
|
||||
}
|
||||
if (balanceToCheck > fee.multiply(percentsToFeeIncrease)) {
|
||||
SwapFeeState.Enough
|
||||
} else {
|
||||
val nativeToken = getNativeToken(fromTokenStatus.currency.network.backendId)
|
||||
SwapFeeState.NotEnough(
|
||||
feeCurrency = nativeToken,
|
||||
currencyName = nativeToken.network.name,
|
||||
currencySymbol = nativeToken.symbol,
|
||||
)
|
||||
}
|
||||
}
|
||||
FeePaidCurrency.SameCurrency -> {
|
||||
val balance = fromTokenStatus.value.amount ?: return SwapFeeState.NotEnough()
|
||||
|
|
|
|||
|
|
@ -6,14 +6,15 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.data.common.account.WalletAccountsSaver
|
||||
import com.tangem.domain.apptheme.ChangeAppThemeModeUseCase
|
||||
import com.tangem.domain.apptheme.GetAppThemeModeUseCase
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.feedback.repository.FeedbackRepository
|
||||
import com.tangem.feature.tester.presentation.actions.TesterActionsContentState.HideAllCurrenciesUM
|
||||
import com.tangem.feature.tester.presentation.actions.TesterActionsContentState.ToggleAppThemeUM
|
||||
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
|
|
@ -24,10 +25,11 @@ import javax.inject.Inject
|
|||
|
||||
@HiltViewModel
|
||||
internal class TesterActionsViewModel @Inject constructor(
|
||||
private val userWalletManager: UserWalletManager,
|
||||
private val changeAppThemeModeUseCase: ChangeAppThemeModeUseCase,
|
||||
private val getAppThemeModeUseCase: GetAppThemeModeUseCase,
|
||||
private val feedbackRepository: FeedbackRepository,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val walletAccountsSaver: WalletAccountsSaver,
|
||||
) : ViewModel() {
|
||||
|
||||
var uiState: TesterActionsContentState by mutableStateOf(initialState)
|
||||
|
|
@ -56,7 +58,20 @@ internal class TesterActionsViewModel @Inject constructor(
|
|||
uiState = uiState.copy(
|
||||
hideAllCurrenciesUM = HideAllCurrenciesUM.Progress,
|
||||
)
|
||||
userWalletManager.hideAllTokens()
|
||||
|
||||
val userWalletId = userWalletsListRepository.selectedUserWalletSync()?.walletId
|
||||
|
||||
if (userWalletId != null) {
|
||||
walletAccountsSaver.update(userWalletId = userWalletId) { response ->
|
||||
response ?: return@update response
|
||||
|
||||
response.copy(
|
||||
accounts = response.accounts.map { accountDTO ->
|
||||
accountDTO.copy(tokens = emptyList())
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
uiState = uiState.copy(
|
||||
hideAllCurrenciesUM = HideAllCurrenciesUM.Clickable(this@TesterActionsViewModel::hideAllCurrencies),
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
package com.tangem.lib.crypto
|
||||
|
||||
import com.tangem.lib.crypto.models.ProxyAmount
|
||||
|
||||
/**
|
||||
* Provider for user tokens data
|
||||
*/
|
||||
interface UserWalletManager {
|
||||
|
||||
/**
|
||||
* Returns user walletId or empty string
|
||||
*/
|
||||
fun getWalletId(): String
|
||||
|
||||
suspend fun hideAllTokens()
|
||||
|
||||
/**
|
||||
* Returns wallet public address for token
|
||||
*
|
||||
* @param networkId for currency
|
||||
* @param derivationPath if null uses default
|
||||
*/
|
||||
@Throws(IllegalStateException::class)
|
||||
suspend fun getWalletAddress(networkId: String, derivationPath: String?): String
|
||||
|
||||
@Throws(IllegalStateException::class)
|
||||
suspend fun getNativeTokenBalance(networkId: String, derivationPath: String?): ProxyAmount?
|
||||
|
||||
@Throws(IllegalStateException::class)
|
||||
suspend fun getLastTransactionHash(networkId: String, derivationPath: String?): String?
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
package com.tangem.lib.crypto.models
|
||||
|
||||
/**
|
||||
* Analytics data for send events in analytics engine
|
||||
*
|
||||
* @property feeType type of fee (min,max,normal)
|
||||
* @property tokenSymbol symbol
|
||||
* @property permissionType optional parameter used for type tx approve
|
||||
*/
|
||||
data class AnalyticsData(
|
||||
val feeType: String,
|
||||
val tokenSymbol: String,
|
||||
val permissionType: String? = null,
|
||||
)
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package com.tangem.lib.crypto.models
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Tx data for create and make approve transaction
|
||||
*
|
||||
* @property networkId id of network
|
||||
* @property feeAmount amount of fee
|
||||
* @property gasLimit gasLimit for given tx
|
||||
* @property destinationAddress address to send tx
|
||||
* @property dataToSign data to sing with signer
|
||||
*/
|
||||
data class ApproveTxData(
|
||||
val networkId: String,
|
||||
val feeAmount: BigDecimal,
|
||||
val gasLimit: Int,
|
||||
val destinationAddress: String,
|
||||
val dataToSign: String,
|
||||
)
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
package com.tangem.lib.crypto.models
|
||||
|
||||
/**
|
||||
* Currency data class that can be native blockchain Token
|
||||
* or custom Token (used in this lib to replace and divide logic Currency from app module)
|
||||
*/
|
||||
sealed class Currency(
|
||||
open val id: String,
|
||||
open val name: String,
|
||||
open val symbol: String,
|
||||
open val networkId: String,
|
||||
) {
|
||||
|
||||
data class NativeToken(
|
||||
override val id: String,
|
||||
override val name: String,
|
||||
override val symbol: String,
|
||||
override val networkId: String,
|
||||
) : Currency(id, name, symbol, networkId)
|
||||
|
||||
class NonNativeToken(
|
||||
override val id: String,
|
||||
override val name: String,
|
||||
override val symbol: String,
|
||||
override val networkId: String,
|
||||
val contractAddress: String,
|
||||
val decimalCount: Int,
|
||||
) : Currency(id, name, symbol, networkId)
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
package com.tangem.lib.crypto.models
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Proxy amount is always has a Coin type
|
||||
*
|
||||
* @property currencySymbol
|
||||
* @property value amount in [BigDecimal]
|
||||
* @property decimals count for token
|
||||
*/
|
||||
data class ProxyAmount(
|
||||
val currencySymbol: String,
|
||||
var value: BigDecimal,
|
||||
val decimals: Int,
|
||||
) {
|
||||
|
||||
companion object {
|
||||
fun empty(): ProxyAmount {
|
||||
return ProxyAmount("", BigDecimal.ZERO, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
package com.tangem.lib.crypto.models
|
||||
|
||||
data class ProxyFiatCurrency(
|
||||
val code: String,
|
||||
val name: String,
|
||||
val symbol: String,
|
||||
)
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package com.tangem.lib.crypto.models
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Tx data for create and make transaction
|
||||
*
|
||||
* @property networkId id of network
|
||||
* @property feeAmount amount of fee
|
||||
* @property gasLimit gasLimit for given tx
|
||||
* @property destinationAddress address to send tx
|
||||
* @property dataToSign data to sing with signer
|
||||
* @property amountToSend amount of tx
|
||||
* @property currencyToSend currency for tx
|
||||
*/
|
||||
// TODO split to cex,dex
|
||||
data class SwapTxData(
|
||||
val networkId: String,
|
||||
val feeAmount: BigDecimal,
|
||||
val gasLimit: Int,
|
||||
val destinationAddress: String,
|
||||
val dataToSign: String,
|
||||
val amountToSend: BigDecimal,
|
||||
val currencyToSend: Currency,
|
||||
)
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
package com.tangem.lib.crypto.models.transactions
|
||||
|
||||
sealed interface SendTxResult {
|
||||
|
||||
object Success : SendTxResult
|
||||
object UserCancelledError : SendTxResult
|
||||
data class TangemSdkError(val code: Int, val cause: Throwable?) : SendTxResult
|
||||
data class BlockchainSdkError(val code: Int, val cause: Throwable?) : SendTxResult
|
||||
data class NetworkError(val ex: Exception? = null) : SendTxResult
|
||||
data class UnknownError(val ex: Exception? = null) : SendTxResult
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue