Updated on 2026-08-14
This commit is contained in:
parent
19fb8f2bcd
commit
ecdb72e55c
58 changed files with 1082 additions and 346 deletions
|
|
@ -154,6 +154,7 @@ internal class DefaultOnboardingVisaComponent @AssistedInject constructor(
|
|||
appComponentContext = factoryContext,
|
||||
config = OnboardingVisaApproveComponent.Config(
|
||||
visaDataForApprove = route.visaDataForApprove,
|
||||
scanResponse = model.currentScanResponse.value,
|
||||
),
|
||||
params = OnboardingVisaApproveComponent.Params(
|
||||
childParams = childParams,
|
||||
|
|
|
|||
|
|
@ -10,12 +10,16 @@ import com.tangem.core.decompose.model.ParamsContainer
|
|||
import com.tangem.domain.common.visa.VisaUtilities
|
||||
import com.tangem.domain.common.visa.VisaWalletPublicKeyUtility
|
||||
import com.tangem.domain.visa.model.VisaCardActivationStatus
|
||||
import com.tangem.domain.visa.model.VisaCardId
|
||||
import com.tangem.domain.visa.model.VisaCustomerWalletDataToSignRequest
|
||||
import com.tangem.domain.visa.model.VisaDataForApprove
|
||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||
import com.tangem.domain.visa.repository.VisaAuthRepository
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.onboarding.v2.visa.impl.child.accesscode.OnboardingVisaAccessCodeComponent
|
||||
import com.tangem.features.onboarding.v2.visa.impl.child.accesscode.ui.state.OnboardingVisaAccessCodeUM
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.sdk.api.visa.VisaCardActivationTaskMode
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -28,6 +32,7 @@ import javax.inject.Inject
|
|||
@ComponentScoped
|
||||
internal class OnboardingVisaAccessCodeModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
|
|
@ -36,11 +41,18 @@ internal class OnboardingVisaAccessCodeModel @Inject constructor(
|
|||
) : Model() {
|
||||
|
||||
private val params: OnboardingVisaAccessCodeComponent.Config = paramsContainer.require()
|
||||
private val visaActivationRepository = visaActivationRepositoryFactory.create(
|
||||
VisaCardId(
|
||||
cardId = params.scanResponse.card.cardId,
|
||||
cardPublicKey = params.scanResponse.card.cardPublicKey.toHexString(),
|
||||
),
|
||||
)
|
||||
private val activationStatus =
|
||||
params.scanResponse.visaCardActivationStatus as? VisaCardActivationStatus.NotStartedActivation
|
||||
?: error("Visa activation status is not set or incorrect for this step")
|
||||
|
||||
private val _uiState = MutableStateFlow(getInitialState())
|
||||
|
||||
val uiState = _uiState.asStateFlow()
|
||||
val onBack = MutableSharedFlow<Unit>()
|
||||
val onDone = MutableSharedFlow<OnboardingVisaAccessCodeComponent.DoneEvent>()
|
||||
|
|
@ -126,46 +138,65 @@ internal class OnboardingVisaAccessCodeModel @Inject constructor(
|
|||
val challengeToSign = runCatching {
|
||||
visaAuthRepository.getCardAuthChallenge(
|
||||
cardId = activationStatus.activationInput.cardId,
|
||||
cardPublicKey = activationStatus.activationInput.cardPublicKey.toHexString(),
|
||||
cardPublicKey = activationStatus.activationInput.cardPublicKey,
|
||||
)
|
||||
}.getOrElse {
|
||||
loading(false)
|
||||
// show alert
|
||||
// TODO show alert
|
||||
return@launch
|
||||
}
|
||||
|
||||
val result = tangemSdkManager.activateVisaCard(
|
||||
accessCode = accessCode,
|
||||
challengeToSign = challengeToSign,
|
||||
mode = VisaCardActivationTaskMode.Full(
|
||||
accessCode = accessCode,
|
||||
authorizationChallenge = challengeToSign,
|
||||
),
|
||||
activationInput = activationStatus.activationInput,
|
||||
)
|
||||
//
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
// TODO load approve data from backend
|
||||
val targetAddress = "x9F65354e595284956599F2892fA4A4a87653D6E6"
|
||||
val foundCardId = tryToFindExistingWalletCardId(targetAddress)
|
||||
) as? CompletionResult.Success ?: run {
|
||||
loading(false)
|
||||
// TODO show alert
|
||||
return@launch
|
||||
}
|
||||
|
||||
modelScope.launch {
|
||||
onDone.emit(
|
||||
OnboardingVisaAccessCodeComponent.DoneEvent(
|
||||
visaDataForApprove = VisaDataForApprove(
|
||||
targetAddress = targetAddress,
|
||||
approveHash = "48b55c482123a10ad9022f9f4c5dd95c",
|
||||
customerWalletCardId = foundCardId,
|
||||
),
|
||||
walletFound = foundCardId != null,
|
||||
newScanResponse = params.scanResponse.copy(
|
||||
card = result.data.newCardDTO,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
loading(false)
|
||||
// show alert
|
||||
}
|
||||
runCatching {
|
||||
visaActivationRepository.activateCard(result.data.signedActivationData)
|
||||
}.onFailure {
|
||||
loading(false)
|
||||
// TODO show alert
|
||||
return@launch
|
||||
}
|
||||
|
||||
// load data to sign by customer wallet for the next step
|
||||
val dataToSign = runCatching {
|
||||
visaActivationRepository.getCustomerWalletAcceptanceData(
|
||||
VisaCustomerWalletDataToSignRequest(
|
||||
orderId = result.data.signedActivationData.dataToSign.request.orderId,
|
||||
cardWalletAddress = result.data.signedActivationData.cardWalletAddress,
|
||||
),
|
||||
)
|
||||
}.getOrElse {
|
||||
loading(false)
|
||||
// TODO show alert
|
||||
return@launch
|
||||
}
|
||||
|
||||
val targetAddress = result.data.signedActivationData.dataToSign.request.customerWalletAddress
|
||||
val foundCardId = tryToFindExistingWalletCardId(targetAddress)
|
||||
|
||||
modelScope.launch {
|
||||
onDone.emit(
|
||||
OnboardingVisaAccessCodeComponent.DoneEvent(
|
||||
visaDataForApprove = VisaDataForApprove(
|
||||
targetAddress = targetAddress,
|
||||
customerWalletCardId = foundCardId,
|
||||
dataToSign = dataToSign,
|
||||
),
|
||||
walletFound = foundCardId != null,
|
||||
newScanResponse = params.scanResponse.copy(
|
||||
card = result.data.newCardDTO,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.visa.model.VisaDataForApprove
|
||||
import com.tangem.features.onboarding.v2.visa.impl.DefaultOnboardingVisaComponent
|
||||
import com.tangem.features.onboarding.v2.visa.impl.child.approve.model.OnboardingVisaApproveModel
|
||||
|
|
@ -43,6 +44,7 @@ internal class OnboardingVisaApproveComponent(
|
|||
|
||||
data class Config(
|
||||
val visaDataForApprove: VisaDataForApprove,
|
||||
val scanResponse: ScanResponse,
|
||||
)
|
||||
|
||||
data class Params(
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@ package com.tangem.features.onboarding.v2.visa.impl.child.approve.model
|
|||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.core.decompose.di.ComponentScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.domain.visa.model.VisaCardId
|
||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||
import com.tangem.features.onboarding.v2.visa.impl.child.approve.OnboardingVisaApproveComponent
|
||||
import com.tangem.features.onboarding.v2.visa.impl.child.approve.ui.state.OnboardingVisaApproveUM
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
|
|
@ -20,11 +23,19 @@ import javax.inject.Inject
|
|||
@ComponentScoped
|
||||
internal class OnboardingVisaApproveModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<OnboardingVisaApproveComponent.Config>()
|
||||
private val visaActivationRepository = visaActivationRepositoryFactory.create(
|
||||
VisaCardId(
|
||||
cardId = params.scanResponse.card.cardId,
|
||||
cardPublicKey = params.scanResponse.card.cardPublicKey.toHexString(),
|
||||
),
|
||||
)
|
||||
|
||||
private val _uiState = MutableStateFlow(getInitialState())
|
||||
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
|
@ -42,20 +53,21 @@ internal class OnboardingVisaApproveModel @Inject constructor(
|
|||
modelScope.launch {
|
||||
val result = tangemSdkManager.visaCustomerWalletApprove(
|
||||
visaDataForApprove = params.visaDataForApprove,
|
||||
)
|
||||
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
// TODO make backend call
|
||||
|
||||
onDone.emit(Unit)
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
loading(false)
|
||||
// TODO show dialog
|
||||
return@launch
|
||||
}
|
||||
) as? CompletionResult.Success ?: run {
|
||||
loading(false)
|
||||
// TODO show dialog
|
||||
return@launch
|
||||
}
|
||||
|
||||
runCatching {
|
||||
visaActivationRepository.approveByCustomerWallet(result.data)
|
||||
}.onFailure {
|
||||
loading(false)
|
||||
// TODO show dialog
|
||||
return@launch
|
||||
}
|
||||
|
||||
onDone.emit(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package com.tangem.features.onboarding.v2.visa.impl.child.inprogress.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.core.decompose.di.ComponentScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.domain.visa.model.VisaActivationRemoteState
|
||||
import com.tangem.domain.visa.model.VisaCardId
|
||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||
import com.tangem.features.onboarding.v2.visa.impl.child.inprogress.OnboardingVisaInProgressComponent
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -17,12 +19,17 @@ import javax.inject.Inject
|
|||
@ComponentScoped
|
||||
internal class OnboardingVisaInProgressModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<OnboardingVisaInProgressComponent.Config>()
|
||||
private val visaActivationRepository = visaActivationRepositoryFactory.create(params.scanResponse.card.cardId)
|
||||
private val visaActivationRepository = visaActivationRepositoryFactory.create(
|
||||
VisaCardId(
|
||||
cardId = params.scanResponse.card.cardId,
|
||||
cardPublicKey = params.scanResponse.card.cardPublicKey.toHexString(),
|
||||
),
|
||||
)
|
||||
val onDone = MutableSharedFlow<Unit>()
|
||||
|
||||
init {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
package com.tangem.features.onboarding.v2.visa.impl.child.otherwallet.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.core.decompose.di.ComponentScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.navigation.share.ShareManager
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.domain.visa.model.VisaActivationRemoteState
|
||||
import com.tangem.domain.visa.model.VisaCardId
|
||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||
import com.tangem.features.onboarding.v2.visa.impl.child.otherwallet.OnboardingVisaOtherWalletComponent
|
||||
import com.tangem.features.onboarding.v2.visa.impl.child.otherwallet.ui.state.OnboardingVisaOtherWalletUM
|
||||
|
|
@ -22,15 +24,19 @@ import javax.inject.Inject
|
|||
@ComponentScoped
|
||||
internal class OnboardingVisaOtherWalletModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val shareManager: ShareManager,
|
||||
private val visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||
) : Model() {
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private val config = paramsContainer.require<OnboardingVisaOtherWalletComponent.Config>()
|
||||
private val visaActivationRepository = visaActivationRepositoryFactory.create(config.scanResponse.card.cardId)
|
||||
private val visaActivationRepository = visaActivationRepositoryFactory.create(
|
||||
VisaCardId(
|
||||
cardId = config.scanResponse.card.cardId,
|
||||
cardPublicKey = config.scanResponse.card.cardPublicKey.toHexString(),
|
||||
),
|
||||
)
|
||||
private val _uiState = MutableStateFlow(getInitialState())
|
||||
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
|
@ -61,10 +67,10 @@ internal class OnboardingVisaOtherWalletModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onShareClicked() {
|
||||
shareManager.shareText("https://tangem.com/${config.visaDataForApprove.approveHash}")
|
||||
shareManager.shareText("https://tangem.com/")
|
||||
}
|
||||
|
||||
private fun onOpenInBrowserClicked() {
|
||||
urlOpener.openUrl("https://tangem.com/${config.visaDataForApprove.approveHash}")
|
||||
urlOpener.openUrl("https://tangem.com/")
|
||||
}
|
||||
}
|
||||
|
|
@ -52,12 +52,13 @@ internal class OnboardingVisaModel @Inject constructor(
|
|||
fun navigateFromWelcome(route: OnboardingVisaRoute.Welcome) {
|
||||
if (route.isWelcomeBack) {
|
||||
val scanResponse = _currentScanResponse.value
|
||||
val activationStatus = scanResponse.visaCardActivationStatus as? VisaCardActivationStatus
|
||||
.ActivationStarted ?: error("Activation status is not correct for welcome back route")
|
||||
val activationStatus = scanResponse.visaCardActivationStatus
|
||||
as? VisaCardActivationStatus.ActivationStarted
|
||||
?: error("Activation status is not correct for welcome back route")
|
||||
|
||||
when (activationStatus.remoteState) {
|
||||
VisaActivationRemoteState.CardWalletSignatureRequired,
|
||||
VisaActivationRemoteState.CustomerWalletSignatureRequired,
|
||||
is VisaActivationRemoteState.CardWalletSignatureRequired,
|
||||
is VisaActivationRemoteState.CustomerWalletSignatureRequired,
|
||||
-> OnboardingVisaRoute.AccessCode
|
||||
VisaActivationRemoteState.WaitingPinCode -> OnboardingVisaRoute.PinCode
|
||||
VisaActivationRemoteState.WaitingForActivationFinishing -> OnboardingVisaRoute.InProgress
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue