Updated on 2026-08-14
This commit is contained in:
parent
c62f464b86
commit
e047c491cf
11 changed files with 158 additions and 20 deletions
|
|
@ -4,12 +4,12 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
interface GiveApprovalComponent : ComposableBottomSheetComponent {
|
||||
|
||||
data class Params(
|
||||
val userWallet: UserWallet,
|
||||
val userWalletId: UserWalletId,
|
||||
val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
val amount: String,
|
||||
|
|
@ -19,6 +19,7 @@ interface GiveApprovalComponent : ComposableBottomSheetComponent {
|
|||
)
|
||||
|
||||
interface Callback {
|
||||
fun onApproveClick()
|
||||
fun onApproveDone()
|
||||
fun onApproveFailed()
|
||||
fun onCancelClick()
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ dependencies {
|
|||
implementation(projects.core.navigation)
|
||||
implementation(projects.core.ui)
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.core.analytics)
|
||||
implementation(projects.core.analytics.models)
|
||||
|
||||
/** Common */
|
||||
implementation(projects.common.ui)
|
||||
|
|
@ -33,6 +35,7 @@ dependencies {
|
|||
|
||||
/** Domain */
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.wallets)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.transaction.models)
|
||||
implementation(projects.domain.transaction)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.common.ui.userwallet.ext.walletInterationIcon
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.child
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
|
|
@ -46,7 +45,7 @@ internal class DefaultGiveApprovalComponent @AssistedInject constructor(
|
|||
feeDisplaySource = FeeSelectorParams.FeeDisplaySource.Screen,
|
||||
analyticsCategoryName = CommonSendAnalyticEvents.APPROVE_CATEGORY,
|
||||
analyticsSendSource = CommonSendAnalyticEvents.CommonSendSource.Approve,
|
||||
userWalletId = params.userWallet.walletId,
|
||||
userWalletId = params.userWalletId,
|
||||
),
|
||||
onResult = model::onFeeResult,
|
||||
)
|
||||
|
|
@ -84,7 +83,7 @@ internal class DefaultGiveApprovalComponent @AssistedInject constructor(
|
|||
approveType = uiState.approveType,
|
||||
approveItems = uiState.approveItems,
|
||||
onChangeApproveType = model::onChangeApproveType,
|
||||
walletInteractionIcon = walletInterationIcon(params.userWallet),
|
||||
walletInteractionIcon = uiState.walletInteractionIcon,
|
||||
isApproveEnabled = uiState.isApproveButtonEnabled,
|
||||
isApproveLoading = uiState.isApproveLoading,
|
||||
onApproveClick = model::onApproveClick,
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@ package com.tangem.features.approval.impl
|
|||
|
||||
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
|
||||
import com.tangem.features.approval.api.GiveApprovalFeatureToggles
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultGiveApprovalFeatureToggles(
|
||||
internal class DefaultGiveApprovalFeatureToggles @Inject constructor(
|
||||
private val featureToggles: FeatureTogglesManager,
|
||||
) : GiveApprovalFeatureToggles {
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ package com.tangem.features.approval.impl.di
|
|||
import com.tangem.core.decompose.di.ModelComponent
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.features.approval.api.GiveApprovalComponent
|
||||
import com.tangem.features.approval.api.GiveApprovalFeatureToggles
|
||||
import com.tangem.features.approval.impl.DefaultGiveApprovalComponent
|
||||
import com.tangem.features.approval.impl.DefaultGiveApprovalFeatureToggles
|
||||
import com.tangem.features.approval.impl.model.GiveApprovalModel
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
|
@ -17,6 +19,10 @@ import javax.inject.Singleton
|
|||
@Module
|
||||
internal interface GiveApprovalFeatureModule {
|
||||
|
||||
@Singleton
|
||||
@Binds
|
||||
fun bindGiveApprovalFeatureToggle(toggles: DefaultGiveApprovalFeatureToggles): GiveApprovalFeatureToggles
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindComponentFactory(factory: DefaultGiveApprovalComponent.Factory): GiveApprovalComponent.Factory
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import com.tangem.blockchain.common.TransactionData
|
|||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.common.ui.bottomsheet.permission.state.ApproveType
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
|
|
@ -28,6 +31,8 @@ import com.tangem.features.approval.api.GiveApprovalComponent
|
|||
import com.tangem.features.send.v2.api.callbacks.FeeSelectorModelCallback
|
||||
import com.tangem.features.send.v2.api.entity.FeeSelectorUM
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.common.ui.userwallet.ext.walletInterationIcon
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.utils.TangemBlogUrlBuilder.RESOURCE_TO_LEARN_ABOUT_APPROVING_IN_SWAP
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -52,14 +57,23 @@ internal class GiveApprovalModel @Inject constructor(
|
|||
private val createAndSendGaslessTransactionUseCase: CreateAndSendGaslessTransactionUseCase,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : Model(), FeeSelectorModelCallback {
|
||||
|
||||
private val params: GiveApprovalComponent.Params = paramsContainer.require()
|
||||
|
||||
private val userWallet by lazy {
|
||||
requireNotNull(
|
||||
getUserWalletUseCase(params.userWalletId).getOrNull(),
|
||||
) { "No wallet found for id: $params.userWalletId" }
|
||||
}
|
||||
|
||||
val uiState: StateFlow<GiveApprovalUM>
|
||||
field = MutableStateFlow(
|
||||
GiveApprovalUM(
|
||||
approveType = ApproveType.LIMITED,
|
||||
walletInteractionIcon = walletInterationIcon(userWallet),
|
||||
isApproveButtonEnabled = false,
|
||||
isApproveLoading = false,
|
||||
),
|
||||
|
|
@ -73,6 +87,7 @@ internal class GiveApprovalModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun onApproveClick() {
|
||||
params.callback.onApproveClick()
|
||||
uiState.update { it.copy(isApproveLoading = true) }
|
||||
modelScope.launch(dispatchers.main) {
|
||||
val isSuccess = sendApprovalTransaction()
|
||||
|
|
@ -113,7 +128,7 @@ internal class GiveApprovalModel @Inject constructor(
|
|||
|
||||
return createApprovalTransactionUseCase(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
userWalletId = params.userWallet.walletId,
|
||||
userWalletId = params.userWalletId,
|
||||
amount = getApprovalAmount(),
|
||||
contractAddress = tokenCurrency.contractAddress,
|
||||
spenderAddress = params.spenderAddress,
|
||||
|
|
@ -126,7 +141,7 @@ internal class GiveApprovalModel @Inject constructor(
|
|||
|
||||
return getFeeUseCase(
|
||||
transactionData = approvalTransaction,
|
||||
userWallet = params.userWallet,
|
||||
userWallet = userWallet,
|
||||
network = params.cryptoCurrencyStatus.currency.network,
|
||||
)
|
||||
}
|
||||
|
|
@ -138,13 +153,13 @@ internal class GiveApprovalModel @Inject constructor(
|
|||
return if (maybeToken == null) {
|
||||
getFeeForGaslessUseCase(
|
||||
transactionData = approvalTransaction,
|
||||
userWallet = params.userWallet,
|
||||
userWallet = userWallet,
|
||||
network = params.cryptoCurrencyStatus.currency.network,
|
||||
)
|
||||
} else {
|
||||
getFeeForTokenUseCase(
|
||||
transactionData = approvalTransaction,
|
||||
userWallet = params.userWallet,
|
||||
userWallet = userWallet,
|
||||
token = maybeToken.currency,
|
||||
)
|
||||
}
|
||||
|
|
@ -162,7 +177,7 @@ internal class GiveApprovalModel @Inject constructor(
|
|||
|
||||
val transactionData = createApprovalTransactionUseCase(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
userWalletId = params.userWallet.walletId,
|
||||
userWalletId = params.userWalletId,
|
||||
amount = getApprovalAmount(),
|
||||
fee = selectedFee,
|
||||
contractAddress = tokenCurrency.contractAddress,
|
||||
|
|
@ -174,14 +189,14 @@ internal class GiveApprovalModel @Inject constructor(
|
|||
|
||||
return if (isFeeInTokenCurrency) {
|
||||
createAndSendGaslessTransactionUseCase(
|
||||
userWallet = params.userWallet,
|
||||
userWallet = userWallet,
|
||||
transactionData = transactionData,
|
||||
fee = feeExtended,
|
||||
)
|
||||
} else {
|
||||
sendTransactionUseCase(
|
||||
txData = transactionData,
|
||||
userWallet = params.userWallet,
|
||||
userWallet = userWallet,
|
||||
network = tokenCurrency.network,
|
||||
)
|
||||
}.fold(
|
||||
|
|
@ -189,7 +204,32 @@ internal class GiveApprovalModel @Inject constructor(
|
|||
Timber.e("Failed to send approval transaction: $error")
|
||||
false
|
||||
},
|
||||
ifRight = { true },
|
||||
ifRight = {
|
||||
sendApproveSuccessAnalytics(feeContent)
|
||||
true
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun sendApproveSuccessAnalytics(feeContent: FeeSelectorUM.Content) {
|
||||
val currency = params.cryptoCurrencyStatus.currency
|
||||
val feeToken = feeContent.feeExtraInfo.feeCryptoCurrencyStatus.currency.symbol
|
||||
val permissionType = when (uiState.value.approveType) {
|
||||
ApproveType.LIMITED -> "Current transaction"
|
||||
ApproveType.UNLIMITED -> "Unlimited"
|
||||
}
|
||||
val event = AnalyticsParam.TxSentFrom.Approve(
|
||||
blockchain = currency.network.name,
|
||||
token = currency.symbol,
|
||||
feeType = feeContent.toAnalyticType(),
|
||||
feeToken = feeToken,
|
||||
permissionType = permissionType,
|
||||
)
|
||||
analyticsEventHandler.send(
|
||||
Basic.TransactionSent(
|
||||
sentFrom = event,
|
||||
memoType = Basic.TransactionSent.MemoType.Null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.approval.impl.model
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.tangem.common.ui.bottomsheet.permission.state.ApproveType
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
@ -7,6 +8,7 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
internal data class GiveApprovalUM(
|
||||
val approveType: ApproveType,
|
||||
val approveItems: ImmutableList<ApproveType> = ApproveType.entries.toImmutableList(),
|
||||
@DrawableRes val walletInteractionIcon: Int?,
|
||||
val isApproveButtonEnabled: Boolean,
|
||||
val isApproveLoading: Boolean,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue