Updated on 2026-08-14
This commit is contained in:
parent
b3138bf560
commit
3088258c74
14 changed files with 339 additions and 97 deletions
|
|
@ -38,6 +38,7 @@ dependencies {
|
|||
implementation(projects.domain.notifications)
|
||||
|
||||
// region Project - Libs
|
||||
implementation(projects.libs.blockchainSdk)
|
||||
implementation(projects.libs.crypto)
|
||||
// endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -1,41 +1,46 @@
|
|||
package com.tangem.features.managetokens.utils.list
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.raise.ensureNotNull
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.account.producer.SingleAccountProducer
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.domain.account.producer.SingleAccountListProducer
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.account.supplier.SingleAccountSupplier
|
||||
import com.tangem.domain.account.supplier.SingleAccountListSupplier
|
||||
import com.tangem.domain.managetokens.CheckIsCurrencyNotAddedUseCase
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.features.managetokens.component.AddCustomTokenMode
|
||||
import com.tangem.lib.crypto.derivation.AccountNodeRecognizer
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class CustomTokenFormUseCasesFacade @AssistedInject constructor(
|
||||
@Assisted private val mode: AddCustomTokenMode,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
private val checkIsCurrencyNotAddedUseCase: CheckIsCurrencyNotAddedUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val singleAccountSupplier: SingleAccountSupplier,
|
||||
@Assisted private val mode: AddCustomTokenMode,
|
||||
private val singleAccountListSupplier: SingleAccountListSupplier,
|
||||
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
) {
|
||||
|
||||
suspend fun addCryptoCurrenciesUseCase(currency: CryptoCurrency): Either<Throwable, Unit> = when (mode) {
|
||||
is AddCustomTokenMode.Account -> {
|
||||
manageCryptoCurrenciesUseCase(
|
||||
accountId = AccountId.forCryptoPortfolio(
|
||||
userWalletId = mode.userWalletId,
|
||||
derivationIndex = DerivationIndex.Main,
|
||||
),
|
||||
add = currency,
|
||||
)
|
||||
is AddCustomTokenMode.Account -> either {
|
||||
val accountId = getAccountId(currency)
|
||||
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, add = currency).bind()
|
||||
}
|
||||
is AddCustomTokenMode.Wallet -> {
|
||||
addCryptoCurrenciesUseCase.invoke(
|
||||
|
|
@ -59,16 +64,13 @@ internal class CustomTokenFormUseCasesFacade @AssistedInject constructor(
|
|||
contractAddress: String?,
|
||||
): Either<Throwable, Boolean> = when (mode) {
|
||||
is AddCustomTokenMode.Account -> {
|
||||
val account = singleAccountSupplier.getSyncOrNull(
|
||||
params = SingleAccountProducer.Params(accountId = mode.accountId),
|
||||
getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = mode.accountId.userWalletId,
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
contractAddress = contractAddress,
|
||||
)
|
||||
?: return IllegalStateException("Account not found").left()
|
||||
|
||||
account.cryptoCurrencies.none { currency ->
|
||||
networkId == currency.network.id &&
|
||||
derivationPath == currency.network.derivationPath &&
|
||||
contractAddress.equals(currency.id.contractAddress, ignoreCase = true)
|
||||
}
|
||||
.fold(ifEmpty = { true }, ifSome = { false })
|
||||
.right()
|
||||
}
|
||||
is AddCustomTokenMode.Wallet -> checkIsCurrencyNotAddedUseCase.invoke(
|
||||
|
|
@ -79,6 +81,56 @@ internal class CustomTokenFormUseCasesFacade @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun Raise<Throwable>.getAccountId(currency: CryptoCurrency): AccountId {
|
||||
val accountList = singleAccountListSupplier.getSyncOrNull(
|
||||
params = SingleAccountListProducer.Params(userWalletId = mode.userWalletId),
|
||||
)
|
||||
|
||||
ensureNotNull(accountList) {
|
||||
IllegalStateException("Account list not found: ${mode.userWalletId}")
|
||||
}
|
||||
|
||||
if (accountList.activeAccounts == 1) {
|
||||
return AccountId.forMainCryptoPortfolio(userWalletId = mode.userWalletId)
|
||||
}
|
||||
|
||||
val currencyAccountIndex = currency.getAccountIndex().bind()
|
||||
|
||||
val account = accountList.accounts.firstOrNull { account ->
|
||||
val cryptoPortfolioAccount = account as? Account.CryptoPortfolio
|
||||
|
||||
cryptoPortfolioAccount?.derivationIndex?.value == currencyAccountIndex
|
||||
}
|
||||
|
||||
return account?.accountId ?: AccountId.forMainCryptoPortfolio(userWalletId = mode.userWalletId)
|
||||
}
|
||||
|
||||
private fun CryptoCurrency.getAccountIndex(): Either<Throwable, Int> = either {
|
||||
val currency = this@getAccountIndex
|
||||
val blockchain = Blockchain.fromNetworkId(networkId = currency.network.backendId)
|
||||
if (blockchain == null) {
|
||||
val exception = IllegalStateException("Token has unknown networkId: ${currency.id}")
|
||||
Timber.e(exception)
|
||||
raise(exception)
|
||||
}
|
||||
|
||||
val derivationPathValue = currency.network.derivationPath.value
|
||||
if (derivationPathValue == null) {
|
||||
val exception = IllegalStateException("Token has no derivation path: ${currency.id}")
|
||||
Timber.e(exception)
|
||||
raise(exception)
|
||||
}
|
||||
|
||||
val accountNodeRecognizer = AccountNodeRecognizer(blockchain)
|
||||
val index = accountNodeRecognizer.recognize(derivationPathValue)?.toInt()
|
||||
|
||||
ensureNotNull(index) {
|
||||
val exception = IllegalStateException("Token has unrecognized derivation path: ${currency.id}")
|
||||
Timber.e(exception)
|
||||
exception
|
||||
}
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(mode: AddCustomTokenMode): CustomTokenFormUseCasesFacade
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue