Updated on 2026-08-14

This commit is contained in:
Tangem 2023-05-03 13:33:50 +03:00
parent 43a7201ac8
commit c7458d8ab0
20 changed files with 544 additions and 124 deletions

View file

@ -1,13 +1,21 @@
package com.tangem.tap.features.onboarding.products.wallet.redux
import android.net.Uri
import com.tangem.common.CompletionResult
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
import org.rekotlin.Action
sealed class OnboardingWalletAction : Action {
object Init : OnboardingWalletAction()
object GetToCreateWalletStep : OnboardingWalletAction()
object GetToSaltPayStep : OnboardingWalletAction()
object CreateWallet : OnboardingWalletAction()
data class WalletWasCreated(
val result: CompletionResult<CreateProductWalletTaskResponse>,
) : OnboardingWalletAction()
object Done : OnboardingWalletAction()
object FinishOnboarding : OnboardingWalletAction()
@ -19,6 +27,24 @@ sealed class OnboardingWalletAction : Action {
object OnBackPressed : OnboardingWalletAction()
}
sealed class OnboardingWallet2Action : OnboardingWalletAction() {
data class Init(val maxProgress: Int) : OnboardingWallet2Action()
data class SetDependencies(val maxProgress: Int) : OnboardingWallet2Action()
data class CreateWallet(
val callback: (CompletionResult<CreateWalletResponse>) -> Unit,
) : OnboardingWallet2Action()
data class ImportWallet(
val mnemonicComponents: List<String>,
val callback: (CompletionResult<CreateWalletResponse>) -> Unit,
) : OnboardingWallet2Action()
data class WalletWasCreated(
val result: CompletionResult<CreateWalletResponse>,
) : OnboardingWallet2Action()
}
sealed class BackupAction : Action {
object IntroduceBackup : BackupAction()

View file

@ -6,12 +6,13 @@ import com.tangem.common.CompletionResult
import com.tangem.common.extensions.ifNotNull
import com.tangem.core.analytics.Analytics
import com.tangem.domain.common.TapWorkarounds.isSaltPay
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
import com.tangem.operations.backup.BackupService
import com.tangem.tap.backupService
import com.tangem.tap.*
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchOnMain
@ -20,6 +21,7 @@ import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.home.redux.HomeAction
@ -29,12 +31,6 @@ import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivat
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction
import com.tangem.tap.features.wallet.models.toCurrencies
import com.tangem.tap.features.wallet.redux.Artwork
import com.tangem.tap.preferencesStorage
import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.tap.tangemSdk
import com.tangem.tap.tangemSdkManager
import com.tangem.tap.userTokensRepository
import kotlinx.coroutines.launch
import org.rekotlin.Action
import org.rekotlin.DispatchFunction
@ -47,7 +43,10 @@ object OnboardingWalletMiddleware {
private val onboardingWalletMiddleware: Middleware<AppState> = { dispatch, state ->
{ next ->
{ action ->
handleWalletAction(action, state, dispatch)
when (action) {
is OnboardingWallet2Action -> handleWallet2Action(action, state)
else -> handleWalletAction(action, state, dispatch)
}
next(action)
}
}
@ -114,42 +113,44 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
}
}
is OnboardingWalletAction.CreateWallet -> {
scanResponse ?: return
scope.launch {
scanResponse ?: return@launch
val result = tangemSdkManager.createProductWallet(scanResponse)
withMainContext {
when (result) {
is CompletionResult.Success -> {
Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
// here we must use updated scanResponse after createWallet & derivation
val updatedResponse = globalState.onboardingState.onboardingManager.scanResponse.copy(
card = result.data.card,
derivedKeys = result.data.derivedKeys,
primaryCard = result.data.primaryCard,
)
onboardingManager.scanResponse = updatedResponse
store.state.globalState.topUpController?.registerEmptyWallet(updatedResponse)
store.dispatchOnMain(OnboardingWalletAction.WalletWasCreated(result))
}
}
is OnboardingWalletAction.WalletWasCreated -> {
scanResponse ?: return
when (val result = action.result) {
is CompletionResult.Success -> {
Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
// here we must use updated scanResponse after createWallet & derivation
val updatedResponse = globalState.onboardingState.onboardingManager.scanResponse.copy(
card = result.data.card,
derivedKeys = result.data.derivedKeys,
primaryCard = result.data.primaryCard,
)
onboardingManager.scanResponse = updatedResponse
store.state.globalState.topUpController?.registerEmptyWallet(updatedResponse)
val blockchainNetworks = if (DemoHelper.isDemoCardId(result.data.card.cardId)) {
DemoHelper.config.demoBlockchains
} else {
listOf(Blockchain.Bitcoin, Blockchain.Ethereum)
}.map { blockchain ->
BlockchainNetwork(blockchain, result.data.card)
}
scope.launch {
userTokensRepository.saveUserTokens(
card = result.data.card,
tokens = blockchainNetworks.toCurrencies(),
)
}
startCardActivation(updatedResponse)
store.dispatch(OnboardingWalletAction.ResumeBackup)
}
is CompletionResult.Failure -> Unit
val blockchainNetworks = if (DemoHelper.isDemoCardId(result.data.card.cardId)) {
DemoHelper.config.demoBlockchains
} else {
listOf(Blockchain.Bitcoin, Blockchain.Ethereum)
}.map { blockchain ->
BlockchainNetwork(blockchain, result.data.card)
}
scope.launch {
userTokensRepository.saveUserTokens(
card = result.data.card,
tokens = blockchainNetworks.toCurrencies(),
)
}
startCardActivation(updatedResponse)
store.dispatch(OnboardingWalletAction.ResumeBackup)
}
is CompletionResult.Failure -> Unit
}
}
OnboardingWalletAction.FinishOnboarding -> {
@ -194,6 +195,62 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
}
}
private fun handleWallet2Action(action: OnboardingWallet2Action, state: () -> AppState?) {
val globalState = store.state.globalState
val onboardingManager = globalState.onboardingState.onboardingManager
val scanResponse = onboardingManager?.scanResponse
when (action) {
is OnboardingWallet2Action.Init -> {
if (scanResponse?.cardTypesResolver?.isWallet2() == true) {
store.dispatch(OnboardingWallet2Action.SetDependencies(action.maxProgress))
}
}
is OnboardingWallet2Action.CreateWallet -> {
scanResponse ?: return
scope.launch {
val mediateResult = when (val result = tangemSdkManager.createProductWallet(scanResponse)) {
is CompletionResult.Success -> {
val response = CreateWalletResponse(
card = result.data.card,
derivedKeys = result.data.derivedKeys,
primaryCard = result.data.primaryCard,
)
CompletionResult.Success(response)
}
is CompletionResult.Failure -> {
CompletionResult.Failure(result.error)
}
}
withMainContext {
action.callback(mediateResult)
}
}
}
is OnboardingWallet2Action.ImportWallet -> {
// TODO: implement
}
is OnboardingWallet2Action.WalletWasCreated -> {
val result = when (val mediateResult = action.result) {
is CompletionResult.Success -> {
val response = CreateProductWalletTaskResponse(
card = mediateResult.data.card,
derivedKeys = mediateResult.data.derivedKeys,
primaryCard = mediateResult.data.primaryCard,
)
CompletionResult.Success(response)
}
is CompletionResult.Failure -> {
CompletionResult.Failure(mediateResult.error)
}
}
store.dispatchOnMain(OnboardingWalletAction.WalletWasCreated(result))
}
else -> Unit
}
}
private fun updateScanResponseAfterBackup(scanResponse: ScanResponse, backupState: BackupState): ScanResponse {
val card = if (backupState.backupCardsNumber > 0) {
val cardsCount = backupState.backupCardsNumber

View file

@ -19,8 +19,8 @@ private fun internalReduce(action: Action, appState: AppState): OnboardingWallet
is GlobalAction.Onboarding -> ReducerForGlobalAction.reduce(action, state)
is OnboardingSaltPayAction -> OnboardingSaltPayReducer.reduce(action, state)
is BackupAction -> state.copy(backupState = BackupReducer.reduce(action, state.backupState, state.isSaltPay))
is OnboardingWalletAction.GetToCreateWalletStep -> OnboardingWalletState(
is OnboardingWallet2Action -> OnboardingWallet2Reducer.reduce(action, state)
is OnboardingWalletAction.GetToCreateWalletStep -> state.copy(
step = OnboardingWalletStep.CreateWallet,
)
is OnboardingWalletAction.GetToSaltPayStep -> state.copy(
@ -65,6 +65,17 @@ private object ReducerForGlobalAction {
private fun maxBackupCards(isSaltPay: Boolean): Int = if (isSaltPay) 1 else 2
}
private object OnboardingWallet2Reducer {
fun reduce(action: OnboardingWallet2Action, state: OnboardingWalletState): OnboardingWalletState = when (action) {
is OnboardingWallet2Action.SetDependencies -> state.copy(
wallet2State = OnboardingWallet2State(
maxProgress = action.maxProgress,
),
)
else -> state
}
}
private object BackupReducer {
@Suppress("ComplexMethod")
fun reduce(action: BackupAction, state: BackupState, isSaltPay: Boolean): BackupState {

View file

@ -14,6 +14,7 @@ import org.rekotlin.StateType
*/
data class OnboardingWalletState(
val step: OnboardingWalletStep = OnboardingWalletStep.None,
val wallet2State: OnboardingWallet2State? = null,
val backupState: BackupState = BackupState(),
val onboardingSaltPayState: OnboardingSaltPayState? = null,
val isSaltPay: Boolean = false,
@ -31,14 +32,14 @@ data class OnboardingWalletState(
}
@Suppress("MagicNumber")
fun getMaxProgress(): Int = when {
isSaltPay -> 12
else -> 6
fun getMaxProgress(): Int {
val baseProgress = if (isSaltPay) 12 else 6
return getWallet2Progress() + baseProgress
}
@Suppress("ComplexMethod", "MagicNumber")
fun getProgressStep(): Int {
return when {
val progressByStep = when {
step == OnboardingWalletStep.CreateWallet -> 1
step == OnboardingWalletStep.Backup -> {
when (backupState.backupStep) {
@ -69,11 +70,19 @@ data class OnboardingWalletState(
step == OnboardingWalletStep.Done -> getMaxProgress()
else -> 1
}
return getWallet2Progress() + progressByStep
}
private fun getWallet2Progress(): Int = wallet2State?.maxProgress ?: 0
}
data class OnboardingWallet2State(
val maxProgress: Int,
)
enum class OnboardingWalletStep {
None, CreateWallet, Backup, SaltPay, Done
None, CreateWallet, SaltPay, Backup, Done
}
data class BackupState(

View file

@ -18,15 +18,7 @@ import com.tangem.common.extensions.guard
import com.tangem.core.analytics.Analytics
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.compose.PinCodeWidget
import com.tangem.tap.common.extensions.configureSettings
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.getDrawableCompat
import com.tangem.tap.common.extensions.hide
import com.tangem.tap.common.extensions.setDrawable
import com.tangem.tap.common.extensions.show
import com.tangem.tap.common.extensions.stop
import com.tangem.tap.common.extensions.toFormattedCurrencyString
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.feedback.SupportInfo
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.redux.navigation.AppScreen
@ -34,11 +26,7 @@ import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.common.toggleWidget.IndeterminateProgressButtonWidget
import com.tangem.tap.common.toggleWidget.RefreshBalanceWidget
import com.tangem.tap.common.transitions.InternalNoteLayoutTransition
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupState
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStep
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep
import com.tangem.tap.features.onboarding.products.wallet.redux.*
import com.tangem.tap.features.onboarding.products.wallet.saltPay.UtorgWebChromeClient
import com.tangem.tap.features.onboarding.products.wallet.saltPay.UtorgWebViewClient
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.SaltPayDialog
@ -56,7 +44,7 @@ import com.tangem.wallet.databinding.LayoutOnboardingMainBinding
/**
[REDACTED_AUTHOR]
*/
internal class OnboardingSaltPayView(
internal class OnboardingSaltPayStateHandler(
private val walletFragment: OnboardingWalletFragment,
) {

View file

@ -0,0 +1,48 @@
package com.tangem.tap.features.onboarding.products.wallet.ui
import com.tangem.feature.onboarding.api.OnboardingSeedPhrase
import com.tangem.feature.onboarding.api.OnboardingSeedPhraseApi
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseViewModel
import com.tangem.tap.common.extensions.hide
import com.tangem.tap.common.extensions.show
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep
/**
[REDACTED_AUTHOR]
*/
internal class OnboardingSeedPhraseStateHandler(
private val walletFragment: OnboardingWalletFragment,
private val onboardingSeedPhraseApi: OnboardingSeedPhraseApi = OnboardingSeedPhrase(),
) {
fun newState(state: OnboardingWalletState, seedPhraseViewModel: SeedPhraseViewModel) {
if (state.step == OnboardingWalletStep.CreateWallet && !seedPhraseViewModel.isFinished) {
switchToWallet2SeedPhraseOnboarding(state, seedPhraseViewModel)
} else {
switchToWalletOnboarding(state)
}
}
private fun switchToWalletOnboarding(state: OnboardingWalletState) {
walletFragment.bindingSeedPhrase.onboardingSeedPhraseContainer.hide()
walletFragment.pbBinding.pbState.show()
walletFragment.binding.onboardingWalletContainer.show()
walletFragment.handleOnboardingStep(state)
}
private fun switchToWallet2SeedPhraseOnboarding(
state: OnboardingWalletState,
seedPhraseViewModel: SeedPhraseViewModel,
) {
walletFragment.pbBinding.pbState.hide()
walletFragment.binding.onboardingWalletContainer.hide()
walletFragment.bindingSeedPhrase.onboardingSeedPhraseContainer.show()
walletFragment.bindingSeedPhrase.onboardingSeedPhraseContainer.setContent {
onboardingSeedPhraseApi.ScreenContent(
viewModel = seedPhraseViewModel,
maxProgress = state.getMaxProgress(),
)
}
}
}

View file

@ -10,6 +10,7 @@ import android.widget.FrameLayout
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.MenuProvider
import androidx.fragment.app.viewModels
import androidx.transition.TransitionInflater
import androidx.transition.TransitionManager
import by.kirich1409.viewbindingdelegate.viewBinding
@ -17,46 +18,53 @@ import coil.load
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.tabs.TabLayoutMediator
import com.tangem.common.CardIdFormatter
import com.tangem.common.CompletionResult
import com.tangem.common.core.CardIdDisplayFormat
import com.tangem.core.analytics.Analytics
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseMediator
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseRouter
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseViewModel
import com.tangem.sdk.ui.widget.leapfrogWidget.LeapfrogWidget
import com.tangem.sdk.ui.widget.leapfrogWidget.PropertyCalculator
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.extensions.hide
import com.tangem.tap.common.extensions.inflate
import com.tangem.tap.common.extensions.resourceUri
import com.tangem.tap.common.extensions.show
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.feedback.SupportInfo
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.features.BaseFragment
import com.tangem.tap.features.FragmentOnBackPressedHandler
import com.tangem.tap.features.addBackPressHandler
import com.tangem.tap.features.onboarding.OnboardingMenuProvider
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupState
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStep
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep
import com.tangem.tap.features.onboarding.products.wallet.redux.*
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction
import com.tangem.tap.features.onboarding.products.wallet.saltPay.ui.OnboardingSaltPayView
import com.tangem.tap.features.onboarding.products.wallet.saltPay.ui.OnboardingSaltPayStateHandler
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AccessCodeDialog
import com.tangem.tap.store
import com.tangem.wallet.R
import com.tangem.wallet.databinding.FragmentOnboardingWalletBinding
import com.tangem.wallet.databinding.LayoutOnboardingSaltpayBinding
import com.tangem.wallet.databinding.LayoutOnboardingSeedPhraseBinding
import com.tangem.wallet.databinding.ViewOnboardingProgressBinding
import dagger.hilt.android.AndroidEntryPoint
import org.rekotlin.StoreSubscriber
@Suppress("LargeClass", "MagicNumber")
@AndroidEntryPoint
class OnboardingWalletFragment :
BaseFragment(R.layout.fragment_onboarding_wallet),
StoreSubscriber<OnboardingWalletState>,
FragmentOnBackPressedHandler {
private val pbBinding: ViewOnboardingProgressBinding by viewBinding(ViewOnboardingProgressBinding::bind)
internal val binding: FragmentOnboardingWalletBinding by viewBinding(FragmentOnboardingWalletBinding::bind)
internal val pbBinding: ViewOnboardingProgressBinding by viewBinding(ViewOnboardingProgressBinding::bind)
internal val bindingSeedPhrase: LayoutOnboardingSeedPhraseBinding by lazy { binding.onboardingSeedPhraseContainer }
internal val bindingSaltPay: LayoutOnboardingSaltpayBinding by lazy { binding.onboardingSaltpayContainer }
private val onboardingSaltPayView: OnboardingSaltPayView = OnboardingSaltPayView(this)
private val seedPhraseStateHandler: OnboardingSeedPhraseStateHandler = OnboardingSeedPhraseStateHandler(this)
private val seedPhraseViewModel by viewModels<SeedPhraseViewModel>()
private val saltPayStateHandler: OnboardingSaltPayStateHandler = OnboardingSaltPayStateHandler(this)
private lateinit var cardsWidget: WalletCardsWidget
private var accessCodeDialog: AccessCodeDialog? = null
@ -69,6 +77,13 @@ class OnboardingWalletFragment :
exitTransition = inflater.inflateTransition(R.transition.fade)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
seedPhraseViewModel.setRouter(makeSeedPhraseRouter())
seedPhraseViewModel.setMediator(makeSeedPhraseMediator())
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@ -88,6 +103,7 @@ class OnboardingWalletFragment :
binding.toolbar.setNavigationOnClickListener { activity?.onBackPressed() }
addBackPressHandler(this)
store.dispatch(OnboardingWallet2Action.Init(seedPhraseViewModel.maxProgress))
store.dispatch(OnboardingWalletAction.Init)
store.dispatch(OnboardingSaltPayAction.Init)
store.dispatch(
@ -159,13 +175,19 @@ class OnboardingWalletFragment :
pbBinding.pbState.max = state.getMaxProgress()
pbBinding.pbState.progress = state.getProgressStep()
if (state.isSaltPay) {
onboardingSaltPayView.newState(state)
} else {
loadImageIntoImageView(state.cardArtworkUri, binding.imvFrontCard)
loadImageIntoImageView(state.cardArtworkUri, binding.imvFirstBackupCard)
loadImageIntoImageView(state.cardArtworkUri, binding.imvSecondBackupCard)
handleOnboardingStep(state)
when {
state.wallet2State != null -> {
seedPhraseStateHandler.newState(state, seedPhraseViewModel)
}
state.isSaltPay -> {
saltPayStateHandler.newState(state)
}
else -> {
loadImageIntoImageView(state.cardArtworkUri, binding.imvFrontCard)
loadImageIntoImageView(state.cardArtworkUri, binding.imvFirstBackupCard)
loadImageIntoImageView(state.cardArtworkUri, binding.imvSecondBackupCard)
handleOnboardingStep(state)
}
}
}
@ -271,7 +293,7 @@ class OnboardingWalletFragment :
layoutButtonsAddCards.btnContinue.isEnabled = state.backupCardsNumber != 0
if (isSaltPay) {
onboardingSaltPayView.showAddBackupCards(state)
saltPayStateHandler.showAddBackupCards(state)
} else {
when (state.backupCardsNumber) {
0 -> {
@ -443,4 +465,33 @@ class OnboardingWalletFragment :
resources.getValue(R.dimen.device_scale_factor_for_twins_welcome, typedValue, true)
return typedValue.float
}
private fun makeSeedPhraseRouter(): SeedPhraseRouter = SeedPhraseRouter(
onBack = ::handleOnBackPressed,
onOpenChat = {
store.dispatch(GlobalAction.OpenChat(SupportInfo()))
},
onOpenUriClick = { uri ->
store.dispatchOpenUrl(uri.toString())
},
)
private fun makeSeedPhraseMediator(): SeedPhraseMediator {
return object : SeedPhraseMediator {
override fun createWallet(callback: (CompletionResult<CreateWalletResponse>) -> Unit) {
store.dispatch(OnboardingWallet2Action.CreateWallet(callback))
}
override fun onWalletCreated(result: CompletionResult<CreateWalletResponse>) {
store.dispatch(OnboardingWallet2Action.WalletWasCreated(result))
}
override fun importWallet(
mnemonicComponents: List<String>,
callback: (CompletionResult<CreateWalletResponse>) -> Unit,
) {
store.dispatch(OnboardingWallet2Action.ImportWallet(mnemonicComponents, callback))
}
}
}
}