Updated on 2026-08-14
This commit is contained in:
parent
26419a5754
commit
b5a54b0e29
7 changed files with 105 additions and 14 deletions
|
|
@ -305,7 +305,7 @@ internal class DefaultOnrampRepository(
|
|||
toAmount = quote.toAmount.value,
|
||||
)
|
||||
} else {
|
||||
error("Express signature invalid")
|
||||
throw OnrampRedirectError.VerificationFailed
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.domain.onramp.model
|
||||
|
||||
sealed class OnrampRedirectError : Throwable() {
|
||||
|
||||
data class DataError(override val cause: Throwable?) : OnrampRedirectError()
|
||||
|
||||
data object VerificationFailed : OnrampRedirectError()
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.domain.onramp
|
|||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.onramp.model.OnrampProviderWithQuote
|
||||
import com.tangem.domain.onramp.model.OnrampRedirectError
|
||||
import com.tangem.domain.onramp.repositories.OnrampRepository
|
||||
import com.tangem.domain.onramp.repositories.OnrampTransactionRepository
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
|
@ -16,7 +17,7 @@ class GetOnrampRedirectUrlUseCase(
|
|||
userWalletId: UserWalletId,
|
||||
quote: OnrampProviderWithQuote.Data,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
): Either<Throwable, String> {
|
||||
): Either<OnrampRedirectError, String> {
|
||||
return Either.catch {
|
||||
val transaction = repository.getOnrampData(
|
||||
userWalletId = userWalletId,
|
||||
|
|
@ -25,6 +26,8 @@ class GetOnrampRedirectUrlUseCase(
|
|||
)
|
||||
transactionRepository.storeTransaction(transaction)
|
||||
transaction.redirectUrl
|
||||
}.mapLeft { throwable ->
|
||||
if (throwable is OnrampRedirectError) throwable else OnrampRedirectError.DataError(throwable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,10 +5,12 @@ import com.tangem.core.ui.decompose.ComposableContentComponent
|
|||
import com.tangem.domain.onramp.model.OnrampProviderWithQuote
|
||||
import com.tangem.domain.onramp.model.OnrampSource
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
internal interface OnrampMainComponent : ComposableContentComponent {
|
||||
|
||||
data class Params(
|
||||
val userWalletId: UserWalletId,
|
||||
val cryptoCurrency: CryptoCurrency,
|
||||
val source: OnrampSource,
|
||||
val openSettings: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,26 @@
|
|||
package com.tangem.features.onramp.main.model
|
||||
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||
import com.arkivanov.decompose.router.slot.activate
|
||||
import com.tangem.common.ui.alerts.models.AlertDemoModeUM
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.components.BasicDialog
|
||||
import com.tangem.core.ui.components.DialogButtonUM
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.message.ContentMessage
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.onramp.*
|
||||
import com.tangem.domain.onramp.analytics.OnrampAnalyticsEvent
|
||||
import com.tangem.domain.onramp.model.OnrampAvailability
|
||||
import com.tangem.domain.onramp.model.OnrampCurrency
|
||||
import com.tangem.domain.onramp.model.OnrampProviderWithQuote
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.onramp.impl.R
|
||||
import com.tangem.features.onramp.main.OnrampMainComponent
|
||||
import com.tangem.features.onramp.main.entity.OnrampIntents
|
||||
import com.tangem.features.onramp.main.entity.OnrampMainBottomSheetConfig
|
||||
|
|
@ -31,12 +41,15 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val router: Router,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val checkOnrampAvailabilityUseCase: CheckOnrampAvailabilityUseCase,
|
||||
private val getOnrampCurrencyUseCase: GetOnrampCurrencyUseCase,
|
||||
private val clearOnrampCacheUseCase: ClearOnrampCacheUseCase,
|
||||
private val fetchQuotesUseCase: OnrampFetchQuotesUseCase,
|
||||
private val getOnrampQuotesUseCase: GetOnrampQuotesUseCase,
|
||||
private val amountInputManager: InputManager,
|
||||
private val messageSender: UiMessageSender,
|
||||
getWalletsUseCase: GetWalletsUseCase,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model(), OnrampIntents {
|
||||
|
||||
|
|
@ -50,7 +63,7 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
currentStateProvider = Provider { _state.value },
|
||||
onrampIntents = this,
|
||||
)
|
||||
|
||||
private val selectedUserWallet = getWalletsUseCase.invokeSync().first { it.walletId == params.userWalletId }
|
||||
private val _state: MutableStateFlow<OnrampMainComponentUM> = MutableStateFlow(
|
||||
value = stateFactory.getInitialState(
|
||||
currency = params.cryptoCurrency.name,
|
||||
|
|
@ -145,15 +158,19 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onBuyClick(quote: OnrampProviderWithQuote.Data) {
|
||||
val currentContentState = state.value as? OnrampMainComponentUM.Content ?: return
|
||||
analyticsEventHandler.send(
|
||||
OnrampAnalyticsEvent.OnBuyClick(
|
||||
providerName = quote.provider.info.name,
|
||||
currency = currentContentState.amountBlockState.currencyUM.code,
|
||||
cryptoCurrency = params.cryptoCurrency.name,
|
||||
),
|
||||
)
|
||||
params.openRedirectPage(quote)
|
||||
if (isDemoCardUseCase.invoke(selectedUserWallet.cardId)) {
|
||||
showDemoWarning()
|
||||
} else {
|
||||
val currentContentState = state.value as? OnrampMainComponentUM.Content ?: return
|
||||
analyticsEventHandler.send(
|
||||
OnrampAnalyticsEvent.OnBuyClick(
|
||||
providerName = quote.provider.info.name,
|
||||
currency = currentContentState.amountBlockState.currencyUM.code,
|
||||
cryptoCurrency = params.cryptoCurrency.name,
|
||||
),
|
||||
)
|
||||
params.openRedirectPage(quote)
|
||||
}
|
||||
}
|
||||
|
||||
override fun openCurrenciesList() {
|
||||
|
|
@ -175,4 +192,33 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
modelScope.launch { clearOnrampCacheUseCase.invoke() }
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun showDemoWarning() {
|
||||
val alertUM = AlertDemoModeUM(onConfirmClick = {})
|
||||
|
||||
messageSender.send(
|
||||
message = ContentMessage { onDismiss ->
|
||||
val confirmButton = DialogButtonUM(
|
||||
title = alertUM.confirmButtonText.resolveReference(),
|
||||
onClick = {
|
||||
alertUM.onConfirmClick()
|
||||
onDismiss()
|
||||
},
|
||||
)
|
||||
|
||||
val dismissButton = DialogButtonUM(
|
||||
title = stringResource(id = R.string.common_cancel),
|
||||
onClick = onDismiss,
|
||||
)
|
||||
|
||||
BasicDialog(
|
||||
message = alertUM.message.resolveReference(),
|
||||
confirmButton = confirmButton,
|
||||
onDismissDialog = onDismiss,
|
||||
title = alertUM.title.resolveReference(),
|
||||
dismissButton = dismissButton,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,19 @@
|
|||
package com.tangem.features.onramp.redirect.model
|
||||
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.components.BasicDialog
|
||||
import com.tangem.core.ui.components.DialogButtonUM
|
||||
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
|
||||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.message.ContentMessage
|
||||
import com.tangem.domain.onramp.GetOnrampRedirectUrlUseCase
|
||||
import com.tangem.features.onramp.impl.R
|
||||
import com.tangem.features.onramp.redirect.OnrampRedirectComponent
|
||||
|
|
@ -23,6 +28,7 @@ internal class OnrampRedirectModel @Inject constructor(
|
|||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val getOnrampRedirectUrlUseCase: GetOnrampRedirectUrlUseCase,
|
||||
private val messageSender: UiMessageSender,
|
||||
router: Router,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
|
@ -62,8 +68,33 @@ internal class OnrampRedirectModel @Inject constructor(
|
|||
quote = params.onrampProviderWithQuote,
|
||||
cryptoCurrency = params.cryptoCurrency,
|
||||
)
|
||||
.onLeft { Timber.e(it) }
|
||||
.onRight { urlOpener.openUrl(it) }
|
||||
.onLeft(::handleError)
|
||||
.onRight {
|
||||
params.onBack()
|
||||
urlOpener.openUrl(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleError(throwable: Throwable) {
|
||||
Timber.e(throwable)
|
||||
|
||||
val contentMessage = ContentMessage { onDismiss ->
|
||||
BasicDialog(
|
||||
message = stringResource(id = R.string.common_unknown_error),
|
||||
confirmButton = DialogButtonUM(
|
||||
title = stringResource(id = R.string.common_ok),
|
||||
onClick = {
|
||||
params.onBack()
|
||||
onDismiss()
|
||||
},
|
||||
),
|
||||
onDismissDialog = {
|
||||
params.onBack()
|
||||
onDismiss()
|
||||
},
|
||||
)
|
||||
}
|
||||
messageSender.send(contentMessage)
|
||||
}
|
||||
}
|
||||
|
|
@ -65,6 +65,7 @@ internal class DefaultOnrampComponent @AssistedInject constructor(
|
|||
OnrampChild.Main -> onrampMainComponentFactory.create(
|
||||
context = childByContext(componentContext),
|
||||
params = OnrampMainComponent.Params(
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrency = params.cryptoCurrency,
|
||||
openSettings = { navigation.push(OnrampChild.Settings) },
|
||||
source = params.source,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue