Updated on 2026-08-14
This commit is contained in:
commit
b3557dd0e4
1030 changed files with 32207 additions and 10702 deletions
|
|
@ -1,10 +1,21 @@
|
|||
package com.tangem.domain.transaction
|
||||
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
||||
interface FeeRepository {
|
||||
|
||||
/** Returns if fee is approximate for current [networkId] */
|
||||
fun isFeeApproximate(networkId: Network.ID, amountType: AmountType): Boolean
|
||||
|
||||
/** Returns fee calculated for the transaction [transactionData] */
|
||||
suspend fun calculateFee(
|
||||
userWallet: UserWallet,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
transactionData: TransactionData,
|
||||
): TransactionFee
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.tangem.domain.transaction.error
|
||||
|
||||
interface FeeErrorResolver {
|
||||
|
||||
fun resolve(throwable: Throwable): GetFeeError
|
||||
}
|
||||
|
|
@ -12,8 +12,6 @@ import com.tangem.domain.networks.single.SingleNetworkStatusProducer
|
|||
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.transaction.error.AssociateAssetError
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.isNullOrZero
|
||||
|
|
@ -22,10 +20,8 @@ import kotlinx.coroutines.flow.firstOrNull
|
|||
class AssociateAssetUseCase(
|
||||
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
private val tokensFeatureToggles: TokensFeatureToggles,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
|
|
@ -33,25 +29,19 @@ class AssociateAssetUseCase(
|
|||
currency: CryptoCurrency,
|
||||
): Either<AssociateAssetError, Unit> {
|
||||
return either {
|
||||
val networkCoin = if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
|
||||
multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
|
||||
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
|
||||
)
|
||||
?.firstOrNull {
|
||||
val network = currency.network
|
||||
it.network.id == network.id && it.network.derivationPath == network.derivationPath
|
||||
}
|
||||
?: error("Unable to create network coin for currencyID: ${currency.id}")
|
||||
} else {
|
||||
currenciesRepository.getNetworkCoin(
|
||||
userWalletId = userWalletId,
|
||||
networkId = currency.network.id,
|
||||
derivationPath = currency.network.derivationPath,
|
||||
)
|
||||
}
|
||||
val networkCoin = multiWalletCryptoCurrenciesSupplier.getSyncOrNull(
|
||||
params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId),
|
||||
)
|
||||
?.firstOrNull {
|
||||
val network = currency.network
|
||||
it.network.id == network.id && it.network.derivationPath == network.derivationPath
|
||||
}
|
||||
?: error("Unable to create network coin for currencyID: ${currency.id}")
|
||||
|
||||
if (isBalanceZero(userWalletId, networkCoin)) {
|
||||
raise(AssociateAssetError.NotEnoughBalance(networkCoin))
|
||||
}
|
||||
|
||||
val signer = cardSdkConfigRepository.getCommonSigner(
|
||||
cardId = null,
|
||||
twinKey = null, // use null here because no assets support for Twin cards
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ import com.tangem.domain.walletmanager.WalletManagersFacade
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
/**
|
||||
* Gets UTXO consolidation availability
|
||||
* Gets self send availability
|
||||
*/
|
||||
class IsUtxoConsolidationAvailableUseCase(
|
||||
class IsSelfSendAvailableUseCase(
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
) {
|
||||
|
||||
suspend fun invokeSync(userWalletId: UserWalletId, network: Network) =
|
||||
walletManagersFacade.checkUtxoConsolidationAvailability(
|
||||
walletManagersFacade.checkSelfSendAvailability(
|
||||
userWalletId = userWalletId,
|
||||
network = network,
|
||||
)
|
||||
|
|
@ -11,13 +11,13 @@ import com.tangem.domain.card.models.TwinKey
|
|||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.requireColdWallet
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
|
||||
class PrepareAndSignUseCase(
|
||||
private val transactionRepository: TransactionRepository,
|
||||
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
private val getHotTransactionSigner: (UserWallet.Hot) -> TransactionSigner,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
|
|
@ -57,7 +57,13 @@ class PrepareAndSignUseCase(
|
|||
}
|
||||
|
||||
private fun createSigner(userWallet: UserWallet): TransactionSigner {
|
||||
userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
return when (userWallet) {
|
||||
is UserWallet.Hot -> getHotTransactionSigner(userWallet)
|
||||
is UserWallet.Cold -> createColdSigner(userWallet)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createColdSigner(userWallet: UserWallet.Cold): TransactionSigner {
|
||||
val card = userWallet.scanResponse.card
|
||||
val isCardNotBackedUp = card.backupStatus?.isActive != true && !card.isTangemTwins
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
package com.tangem.domain.transaction.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.blockchain.blockchains.solana.SolanaWalletManager
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.domain.card.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.card.models.TwinKey
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
|
||||
/**
|
||||
* Use case for sending large Solana transactions that cannot be signed directly by the card.
|
||||
* It handles the transaction creating alt tables and sending the transaction through the Solana network.
|
||||
*
|
||||
* @property cardSdkConfigRepository Repository to access card SDK configurations and signers.
|
||||
* @property walletManagersFacade Facade to manage and retrieve wallet managers.
|
||||
*/
|
||||
class SendLargeSolanaTransactionUseCase(
|
||||
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWallet: UserWallet.Cold,
|
||||
network: Network,
|
||||
txHash: ByteArray,
|
||||
): Either<SendTransactionError, Unit> {
|
||||
val card = userWallet.scanResponse.card
|
||||
val isCardNotBackedUp = card.backupStatus?.isActive != true && !card.isTangemTwins
|
||||
|
||||
val signer = cardSdkConfigRepository.getCommonSigner(
|
||||
cardId = card.cardId.takeIf { isCardNotBackedUp },
|
||||
twinKey = TwinKey.getOrNull(scanResponse = userWallet.scanResponse),
|
||||
)
|
||||
|
||||
val walletManager = walletManagersFacade
|
||||
.getOrCreateWalletManager(userWallet.walletId, network)
|
||||
?: error("WalletManager is null")
|
||||
|
||||
if (walletManager !is SolanaWalletManager) return SendTransactionError.UnknownError().left()
|
||||
val result = walletManager.handleLargeLegacyTransaction(signer, txHash)
|
||||
return when (result) {
|
||||
is Result.Failure -> SendTransactionError.BlockchainSdkError(
|
||||
code = result.error.code,
|
||||
message = result.error.customMessage,
|
||||
).left()
|
||||
is Result.Success -> Unit.right()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -56,12 +56,11 @@ class ValidateWalletAddressUseCase(
|
|||
isCurrentAddress: (String) -> Boolean,
|
||||
): AddressValidationResult {
|
||||
val decodedXAddress = BlockchainUtils.decodeRippleXAddress(address, network.rawId)
|
||||
val isUtxoConsolidationAvailable =
|
||||
walletManagersFacade.checkUtxoConsolidationAvailability(userWalletId, network)
|
||||
val isSelfSendAvailable = walletManagersFacade.checkSelfSendAvailability(userWalletId, network)
|
||||
|
||||
val addressToValidate = decodedXAddress?.address ?: address
|
||||
val current = isCurrentAddress(addressToValidate)
|
||||
val isForbidSelfSend = current && !isUtxoConsolidationAvailable
|
||||
val isForbidSelfSend = current && !isSelfSendAvailable
|
||||
val isValidAddress = walletAddressServiceRepository.validateAddress(userWalletId, network, addressToValidate)
|
||||
|
||||
return when {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue