Updated on 2026-08-14
This commit is contained in:
parent
b2189b3895
commit
4f3d1f10c7
11 changed files with 268 additions and 80 deletions
|
|
@ -42,6 +42,21 @@ internal object TransactionDomainModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSendMultipleTransactionUseCase(
|
||||
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
transactionRepository: TransactionRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
): SendMultipleTransactionUseCase {
|
||||
return SendMultipleTransactionUseCase(
|
||||
demoConfig = DemoConfig(),
|
||||
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||
transactionRepository = transactionRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAssociateAssetUseCase(
|
||||
|
|
|
|||
|
|
@ -158,6 +158,21 @@ internal class DefaultTransactionRepository(
|
|||
(walletManager as TransactionSender).send(txData, signer)
|
||||
}
|
||||
|
||||
override suspend fun sendMultipleTransactions(
|
||||
txsData: List<TransactionData>,
|
||||
signer: CommonSigner,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
) = withContext(coroutineDispatcherProvider.io) {
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
blockchain = blockchain,
|
||||
derivationPath = network.derivationPath.value,
|
||||
)
|
||||
(walletManager as TransactionSender).sendMultiple(txsData, signer)
|
||||
}
|
||||
|
||||
override fun createTransactionDataExtras(
|
||||
data: String,
|
||||
network: Network,
|
||||
|
|
|
|||
|
|
@ -86,10 +86,13 @@ internal class FeedbackDataBuilder {
|
|||
builder.appendKeyValue("Fee", error.fee ?: "Unable to receive")
|
||||
}
|
||||
|
||||
fun addStakingInfo(validatorName: String?, transactionType: String?, unsignedTransaction: String?) {
|
||||
fun addStakingInfo(validatorName: String?, transactionTypes: List<String>, unsignedTransactions: List<String?>) {
|
||||
builder.appendKeyValue("Validator", validatorName ?: "unknown")
|
||||
builder.appendKeyValue("Action", transactionType ?: "unknown")
|
||||
builder.appendKeyValue("Unsigned transaction", unsignedTransaction ?: "unknown")
|
||||
builder.appendKeyValue("Action", transactionTypes.joinToString(separator = "\n").ifEmpty { "unknown" })
|
||||
builder.appendKeyValue(
|
||||
key = "Unsigned transaction",
|
||||
value = unsignedTransactions.joinToString(separator = "\n") { it ?: "unknown" }.ifEmpty { "unknown" },
|
||||
)
|
||||
}
|
||||
|
||||
fun addDelimiter(): StringBuilder = builder.appendDelimiter()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ sealed interface FeedbackEmailType {
|
|||
data class StakingProblem(
|
||||
override val cardInfo: CardInfo,
|
||||
val validatorName: String?,
|
||||
val transactionType: String?,
|
||||
val unsignedTransaction: String?,
|
||||
val transactionTypes: List<String>,
|
||||
val unsignedTransactions: List<String?>,
|
||||
) : FeedbackEmailType
|
||||
}
|
||||
|
|
@ -26,8 +26,8 @@ internal class EmailMessageBodyResolver(
|
|||
is FeedbackEmailType.StakingProblem -> addStakingProblemBody(
|
||||
type.cardInfo,
|
||||
type.validatorName,
|
||||
type.transactionType,
|
||||
type.unsignedTransaction,
|
||||
type.transactionTypes,
|
||||
type.unsignedTransactions,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -81,8 +81,8 @@ internal class EmailMessageBodyResolver(
|
|||
private suspend fun FeedbackDataBuilder.addStakingProblemBody(
|
||||
cardInfo: CardInfo,
|
||||
validatorName: String?,
|
||||
transactionType: String?,
|
||||
unsignedTransaction: String?,
|
||||
transactionTypes: List<String>,
|
||||
unsignedTransactions: List<String?>,
|
||||
) {
|
||||
addCardInfo(cardInfo)
|
||||
addDelimiter()
|
||||
|
|
@ -102,7 +102,7 @@ internal class EmailMessageBodyResolver(
|
|||
addDelimiter()
|
||||
}
|
||||
|
||||
addStakingInfo(validatorName, transactionType, unsignedTransaction)
|
||||
addStakingInfo(validatorName, transactionTypes, unsignedTransactions)
|
||||
addDelimiter()
|
||||
|
||||
addPhoneInfo(phoneInfo = feedbackRepository.getPhoneInfo())
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.blockchain.common.TransactionData
|
|||
import com.tangem.blockchain.common.TransactionExtras
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionSendResult
|
||||
import com.tangem.blockchain.common.transaction.TransactionsSendResult
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.transaction.models.TransactionType
|
||||
|
|
@ -58,6 +59,13 @@ interface TransactionRepository {
|
|||
network: Network,
|
||||
): com.tangem.blockchain.extensions.Result<TransactionSendResult>
|
||||
|
||||
suspend fun sendMultipleTransactions(
|
||||
txsData: List<TransactionData>,
|
||||
signer: CommonSigner,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): com.tangem.blockchain.extensions.Result<TransactionsSendResult>
|
||||
|
||||
fun createTransactionDataExtras(
|
||||
data: String,
|
||||
network: Network,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,147 @@
|
|||
package com.tangem.domain.transaction.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.blockchain.common.BlockchainSdkError
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.common.TransactionSigner
|
||||
import com.tangem.blockchain.common.transaction.TransactionsSendResult
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.blockchain.network.ResultChecker
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.demo.DemoTransactionSender
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.transaction.R
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
import com.tangem.domain.transaction.error.SendTransactionError.Companion.USER_CANCELLED_ERROR_CODE
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.sdk.extensions.localizedDescriptionRes
|
||||
import com.tangem.utils.toFormattedString
|
||||
|
||||
// TODO [REDACTED_TASK_KEY] merge with SendTransactionUseCase
|
||||
class SendMultipleTransactionUseCase(
|
||||
private val demoConfig: DemoConfig,
|
||||
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
private val transactionRepository: TransactionRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
) {
|
||||
suspend operator fun invoke(
|
||||
txsData: List<TransactionData>,
|
||||
userWallet: UserWallet,
|
||||
network: Network,
|
||||
): Either<SendTransactionError?, List<String>> {
|
||||
val card = userWallet.scanResponse.card
|
||||
val isCardNotBackedUp = card.backupStatus?.isActive != true && !card.isTangemTwins
|
||||
|
||||
val signer = cardSdkConfigRepository.getCommonSigner(cardId = card.cardId.takeIf { isCardNotBackedUp })
|
||||
|
||||
val linkedTerminal = cardSdkConfigRepository.isLinkedTerminal()
|
||||
if (userWallet.scanResponse.card.isStart2Coin) {
|
||||
cardSdkConfigRepository.setLinkedTerminal(false)
|
||||
}
|
||||
val sendResult = try {
|
||||
if (demoConfig.isDemoCardId(cardId = userWallet.cardId)) {
|
||||
sendDemo(
|
||||
userWallet = userWallet,
|
||||
network = network,
|
||||
transactionsData = txsData,
|
||||
signer = signer,
|
||||
)
|
||||
} else {
|
||||
val sendResult = transactionRepository.sendMultipleTransactions(
|
||||
txsData = txsData,
|
||||
signer = signer,
|
||||
userWalletId = userWallet.walletId,
|
||||
network = network,
|
||||
)
|
||||
when (sendResult) {
|
||||
is Result.Failure -> handleError(sendResult).left()
|
||||
is Result.Success -> sendResult.data.right()
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
cardSdkConfigRepository.setLinkedTerminal(linkedTerminal)
|
||||
SendTransactionError.DataError(ex.message).left()
|
||||
}
|
||||
|
||||
cardSdkConfigRepository.setLinkedTerminal(linkedTerminal)
|
||||
return sendResult.fold(
|
||||
ifRight = { result -> result.hashes.right() },
|
||||
ifLeft = { it.left() },
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun sendDemo(
|
||||
userWallet: UserWallet,
|
||||
network: Network,
|
||||
transactionsData: List<TransactionData>,
|
||||
signer: TransactionSigner,
|
||||
): Either<SendTransactionError, TransactionsSendResult> {
|
||||
val demoTransactionSender = DemoTransactionSender(
|
||||
walletManagersFacade
|
||||
.getOrCreateWalletManager(userWallet.walletId, network)
|
||||
?: error("WalletManager is null"),
|
||||
)
|
||||
|
||||
val result = demoTransactionSender.sendMultiple(transactionDataList = transactionsData, signer = signer)
|
||||
|
||||
return if (result is Result.Failure && result.error.customMessage.contains(DemoTransactionSender.ID)) {
|
||||
SendTransactionError.DemoCardError.left()
|
||||
} else {
|
||||
TransactionsSendResult(listOf("hash")).right()
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleError(result: Result.Failure): SendTransactionError {
|
||||
if (ResultChecker.isNetworkError(result)) {
|
||||
return SendTransactionError.NetworkError(
|
||||
code = result.error.message,
|
||||
message = result.error.customMessage,
|
||||
)
|
||||
}
|
||||
val error = result.error as? BlockchainSdkError ?: return SendTransactionError.UnknownError()
|
||||
return when (error) {
|
||||
is BlockchainSdkError.WrappedTangemError -> parseWrappedError(error)
|
||||
is BlockchainSdkError.CreateAccountUnderfunded -> {
|
||||
val minAmount = error.minReserve
|
||||
val minValue = minAmount.value?.toFormattedString(minAmount.decimals).orEmpty()
|
||||
SendTransactionError.CreateAccountUnderfunded(minValue)
|
||||
}
|
||||
else -> {
|
||||
SendTransactionError.BlockchainSdkError(
|
||||
code = error.code,
|
||||
message = error.customMessage,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseWrappedError(error: BlockchainSdkError.WrappedTangemError): SendTransactionError {
|
||||
return if (error.code == USER_CANCELLED_ERROR_CODE) {
|
||||
SendTransactionError.UserCancelledError
|
||||
} else {
|
||||
when (val tangemError = error.tangemError) {
|
||||
is TangemSdkError -> {
|
||||
val resource = tangemError.localizedDescriptionRes()
|
||||
val resId = resource.resId ?: R.string.common_unknown_error
|
||||
val resArgs = resource.args.map { it.value }
|
||||
SendTransactionError.TangemSdkError(tangemError.code, resId, wrappedList(resArgs))
|
||||
}
|
||||
is BlockchainSdkError.WrappedTangemError -> {
|
||||
parseWrappedError(tangemError) // todo remove when sdk errors are revised
|
||||
}
|
||||
else -> {
|
||||
SendTransactionError.BlockchainSdkError(error.code, tangemError.customMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||
import com.tangem.domain.staking.model.stakekit.transaction.StakingGasEstimate
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.presentation.state.FeeState
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState
|
||||
|
|
@ -17,31 +15,23 @@ import kotlinx.collections.immutable.ImmutableList
|
|||
internal class SetConfirmationStateAssentTransformer(
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val feeCryptoCurrencyStatus: CryptoCurrencyStatus?,
|
||||
private val stakingGasEstimate: StakingGasEstimate,
|
||||
private val fee: Fee,
|
||||
private val pendingActionList: ImmutableList<PendingAction>,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(
|
||||
confirmationState = prevState.confirmationState.copyWrapped(stakingGasEstimate),
|
||||
confirmationState = prevState.confirmationState.copyWrapped(fee),
|
||||
)
|
||||
}
|
||||
|
||||
private fun StakingStates.ConfirmationState.copyWrapped(
|
||||
gasEstimate: StakingGasEstimate,
|
||||
): StakingStates.ConfirmationState {
|
||||
private fun StakingStates.ConfirmationState.copyWrapped(fee: Fee): StakingStates.ConfirmationState {
|
||||
if (this is StakingStates.ConfirmationState.Data) {
|
||||
val isFeeConvertibleToFiat = feeCryptoCurrencyStatus?.currency?.network?.hasFiatFeeRate == true
|
||||
return copy(
|
||||
innerState = InnerConfirmationStakingState.ASSENT,
|
||||
feeState = FeeState.Content(
|
||||
fee = Fee.Common(
|
||||
Amount(
|
||||
currencySymbol = gasEstimate.token.symbol,
|
||||
value = gasEstimate.amount,
|
||||
decimals = gasEstimate.token.decimals,
|
||||
),
|
||||
),
|
||||
fee = fee,
|
||||
rate = feeCryptoCurrencyStatus?.value?.fiatRate,
|
||||
isFeeConvertibleToFiat = isFeeConvertibleToFiat,
|
||||
appCurrency = appCurrencyProvider(),
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.staking.model.stakekit.transaction.StakingGasEstimate
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.presentation.state.*
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
|
|
@ -15,32 +13,24 @@ import com.tangem.utils.transformer.Transformer
|
|||
internal class SetConfirmationStateCompletedTransformer(
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val feeCryptoCurrencyStatus: CryptoCurrencyStatus?,
|
||||
private val stakingGasEstimate: StakingGasEstimate,
|
||||
private val fee: Fee,
|
||||
private val txUrl: String,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(
|
||||
confirmationState = prevState.confirmationState.copyWrapped(stakingGasEstimate),
|
||||
confirmationState = prevState.confirmationState.copyWrapped(fee),
|
||||
)
|
||||
}
|
||||
|
||||
private fun StakingStates.ConfirmationState.copyWrapped(
|
||||
gasEstimate: StakingGasEstimate,
|
||||
): StakingStates.ConfirmationState {
|
||||
private fun StakingStates.ConfirmationState.copyWrapped(fee: Fee): StakingStates.ConfirmationState {
|
||||
if (this is StakingStates.ConfirmationState.Data) {
|
||||
val isFeeConvertibleToFiat = feeCryptoCurrencyStatus?.currency?.network?.hasFiatFeeRate == true
|
||||
return copy(
|
||||
isPrimaryButtonEnabled = true,
|
||||
innerState = InnerConfirmationStakingState.COMPLETED,
|
||||
feeState = FeeState.Content(
|
||||
fee = Fee.Common(
|
||||
Amount(
|
||||
currencySymbol = gasEstimate.token.symbol,
|
||||
value = gasEstimate.amount,
|
||||
decimals = gasEstimate.token.decimals,
|
||||
),
|
||||
),
|
||||
fee = fee,
|
||||
rate = feeCryptoCurrencyStatus?.value?.fiatRate,
|
||||
isFeeConvertibleToFiat = isFeeConvertibleToFiat,
|
||||
appCurrency = appCurrencyProvider(),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ import androidx.lifecycle.SavedStateHandle
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.bundle.unbundle
|
||||
|
|
@ -28,7 +30,6 @@ import com.tangem.domain.staking.model.stakekit.PendingAction
|
|||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
import com.tangem.domain.staking.model.stakekit.transaction.ActionParams
|
||||
import com.tangem.domain.staking.model.stakekit.transaction.StakingGasEstimate
|
||||
import com.tangem.domain.staking.model.stakekit.transaction.StakingTransaction
|
||||
import com.tangem.domain.staking.model.stakekit.transaction.StakingTransactionType
|
||||
import com.tangem.domain.tokens.FetchPendingTransactionsUseCase
|
||||
|
|
@ -37,10 +38,7 @@ import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
|
|||
import com.tangem.domain.tokens.UpdateDelayedNetworkStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.transaction.usecase.CreateApprovalTransactionUseCase
|
||||
import com.tangem.domain.transaction.usecase.GetAllowanceUseCase
|
||||
import com.tangem.domain.transaction.usecase.GetFeeUseCase
|
||||
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
|
||||
import com.tangem.domain.transaction.usecase.*
|
||||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
|
|
@ -70,6 +68,7 @@ import kotlinx.coroutines.*
|
|||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import javax.inject.Inject
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
|
|
@ -87,6 +86,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
private val getConstructedStakingTransactionUseCase: GetConstructedStakingTransactionUseCase,
|
||||
private val estimateGasUseCase: EstimateGasUseCase,
|
||||
private val sendTransactionUseCase: SendTransactionUseCase,
|
||||
private val sendMultipleTransactionUseCase: SendMultipleTransactionUseCase,
|
||||
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
|
||||
private val saveUnsubmittedHashUseCase: SaveUnsubmittedHashUseCase,
|
||||
private val submitHashUseCase: SubmitHashUseCase,
|
||||
|
|
@ -143,7 +143,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
private var stakingApproval: StakingApproval = StakingApproval.Empty
|
||||
private val allowanceTaskScheduler = SingleTaskScheduler<BigDecimal>()
|
||||
|
||||
private var transactionInProgress: StakingTransaction? = null
|
||||
private val transactionsInProgress: CopyOnWriteArrayList<StakingTransaction> = CopyOnWriteArrayList()
|
||||
|
||||
private var approvalJobHolder: JobHolder = JobHolder()
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
val defaultAddress = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
|
||||
?: error("No available address")
|
||||
|
||||
val stakingTransaction = getStakingTransactionUseCase(
|
||||
val stakingTransactions = getStakingTransactionUseCase(
|
||||
userWalletId = userWalletId,
|
||||
network = cryptoCurrencyStatus.currency.network,
|
||||
params = ActionParams(
|
||||
|
|
@ -206,9 +206,9 @@ internal class StakingViewModel @Inject constructor(
|
|||
return@launch
|
||||
}
|
||||
|
||||
stakingTransaction
|
||||
val fullTransactionsData = stakingTransactions
|
||||
.filterNot { it.type == StakingTransactionType.APPROVAL }
|
||||
.forEach { transaction ->
|
||||
.map { transaction ->
|
||||
val (constructedTransaction, transactionData) = getConstructedStakingTransactionUseCase(
|
||||
networkId = cryptoCurrencyStatus.currency.network.id.value,
|
||||
fee = fee,
|
||||
|
|
@ -218,17 +218,20 @@ internal class StakingViewModel @Inject constructor(
|
|||
stakingEventFactory.createStakingErrorAlert(it)
|
||||
return@launch
|
||||
}
|
||||
val gasEstimate = constructedTransaction.gasEstimate
|
||||
?: return@launch stakingEventFactory.createGenericErrorAlert("Gas estimate is null")
|
||||
|
||||
transactionInProgress = constructedTransaction
|
||||
sendStakingTransaction(
|
||||
transactionId = constructedTransaction.id,
|
||||
gasEstimate = gasEstimate,
|
||||
txData = transactionData,
|
||||
pendingActionList = confirmationState.pendingActions,
|
||||
FullTransactionData(
|
||||
stakeKitTransaction = constructedTransaction,
|
||||
tangemTransaction = transactionData,
|
||||
)
|
||||
}
|
||||
|
||||
transactionsInProgress.addAll(fullTransactionsData.map { it.stakeKitTransaction })
|
||||
|
||||
sendStakingTransaction(
|
||||
fullTransactionsData = fullTransactionsData,
|
||||
fee = fee,
|
||||
pendingActionList = confirmationState.pendingActions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -291,7 +294,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
validatorAddress: String,
|
||||
) {
|
||||
val pendingAction = pendingActions.firstOrNull()
|
||||
val stakingGasEstimate = estimateGasUseCase(
|
||||
val gasEstimate = estimateGasUseCase(
|
||||
userWalletId = userWalletId,
|
||||
network = cryptoCurrencyStatus.currency.network,
|
||||
params = ActionParams(
|
||||
|
|
@ -313,7 +316,13 @@ internal class StakingViewModel @Inject constructor(
|
|||
SetConfirmationStateAssentTransformer(
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
stakingGasEstimate = stakingGasEstimate,
|
||||
fee = Fee.Common(
|
||||
Amount(
|
||||
currencySymbol = gasEstimate.token.symbol,
|
||||
value = gasEstimate.amount,
|
||||
decimals = gasEstimate.token.decimals,
|
||||
),
|
||||
),
|
||||
pendingActionList = pendingActions,
|
||||
),
|
||||
)
|
||||
|
|
@ -555,8 +564,8 @@ internal class StakingViewModel @Inject constructor(
|
|||
val email = FeedbackEmailType.StakingProblem(
|
||||
cardInfo = cardInfo,
|
||||
validatorName = validator?.name,
|
||||
transactionType = transactionInProgress?.type?.name,
|
||||
unsignedTransaction = transactionInProgress?.unsignedTransaction,
|
||||
transactionTypes = transactionsInProgress.map { it.type.name },
|
||||
unsignedTransactions = transactionsInProgress.map { it.unsignedTransaction },
|
||||
)
|
||||
|
||||
feedbackManager.sendEmail(email)
|
||||
|
|
@ -632,13 +641,12 @@ internal class StakingViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private suspend fun sendStakingTransaction(
|
||||
transactionId: String,
|
||||
gasEstimate: StakingGasEstimate,
|
||||
txData: TransactionData,
|
||||
fullTransactionsData: List<FullTransactionData>,
|
||||
fee: Fee,
|
||||
pendingActionList: ImmutableList<PendingAction>,
|
||||
) {
|
||||
sendTransactionUseCase(
|
||||
txData = txData,
|
||||
sendMultipleTransactionUseCase(
|
||||
txsData = fullTransactionsData.map { it.tangemTransaction },
|
||||
userWallet = userWallet,
|
||||
network = cryptoCurrencyStatus.currency.network,
|
||||
).fold(
|
||||
|
|
@ -648,18 +656,21 @@ internal class StakingViewModel @Inject constructor(
|
|||
SetConfirmationStateAssentTransformer(
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
stakingGasEstimate = gasEstimate,
|
||||
fee = fee,
|
||||
pendingActionList = pendingActionList,
|
||||
),
|
||||
)
|
||||
stakingEventFactory.createSendTransactionErrorAlert(error)
|
||||
},
|
||||
ifRight = { txHash ->
|
||||
transactionInProgress = null
|
||||
submitHash(transactionId, txHash)
|
||||
ifRight = { transactionHashes ->
|
||||
transactionsInProgress.clear()
|
||||
submitHash(
|
||||
transactionIds = fullTransactionsData.map { it.stakeKitTransaction.id },
|
||||
transactionHashes = transactionHashes,
|
||||
)
|
||||
scheduleUpdates()
|
||||
val txUrl = getExplorerTransactionUrlUseCase(
|
||||
txHash = txHash,
|
||||
txHash = transactionHashes.last(),
|
||||
networkId = cryptoCurrencyStatus.currency.network.id,
|
||||
).getOrElse { "" }
|
||||
|
||||
|
|
@ -667,7 +678,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
SetConfirmationStateCompletedTransformer(
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
stakingGasEstimate = gasEstimate,
|
||||
fee = fee,
|
||||
txUrl = txUrl,
|
||||
),
|
||||
)
|
||||
|
|
@ -675,18 +686,22 @@ internal class StakingViewModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun submitHash(transactionId: String, transactionHash: String) {
|
||||
submitHashUseCase.submitHash(
|
||||
transactionId = transactionId,
|
||||
transactionHash = transactionHash,
|
||||
)
|
||||
.onLeft {
|
||||
saveUnsubmittedHashUseCase.invoke(
|
||||
private suspend fun submitHash(transactionIds: List<String>, transactionHashes: List<String>) {
|
||||
transactionIds
|
||||
.zip(transactionHashes)
|
||||
.forEach { (transactionId, transactionHash) ->
|
||||
submitHashUseCase.submitHash(
|
||||
transactionId = transactionId,
|
||||
transactionHash = transactionHash,
|
||||
)
|
||||
}.onRight {
|
||||
Timber.d("Successful hash submission")
|
||||
.onLeft {
|
||||
saveUnsubmittedHashUseCase.invoke(
|
||||
transactionId = transactionId,
|
||||
transactionHash = transactionHash,
|
||||
)
|
||||
}.onRight {
|
||||
Timber.d("Successful hash submission")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -750,6 +765,11 @@ internal class StakingViewModel @Inject constructor(
|
|||
InnerConfirmationStakingState.ASSENT
|
||||
}
|
||||
|
||||
private data class FullTransactionData(
|
||||
val stakeKitTransaction: StakingTransaction,
|
||||
val tangemTransaction: TransactionData.Compiled,
|
||||
)
|
||||
|
||||
private companion object {
|
||||
const val WHAT_IS_STAKING_ARTICLE_URL = "https://tangem.com/en/blog/post/how-to-stake-cryptocurrency/"
|
||||
const val ALLOWANCE_UPDATE_DELAY = 10_000L
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ markdown = "0.7.2"
|
|||
# endregion Other libraries
|
||||
|
||||
# region Tangem
|
||||
tangemBlockchainSdk = "develop-748"
|
||||
tangemBlockchainSdk = "develop-750"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "develop-378"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue