Updated on 2026-08-14

This commit is contained in:
Tangem 2024-11-01 08:49:59 +03:00
parent 4594602447
commit b98bc113fc
54 changed files with 667 additions and 198 deletions

View file

@ -90,6 +90,7 @@ dependencies {
implementation(projects.libs.crypto)
implementation(projects.libs.auth)
implementation(projects.libs.blockchainSdk)
implementation(projects.libs.tangemSdkApi)
implementation(projects.data.appCurrency)
implementation(projects.data.appTheme)

View file

@ -59,6 +59,7 @@ import com.tangem.features.staking.api.navigation.StakingRouter
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
import com.tangem.features.wallet.navigation.WalletRouter
import com.tangem.operations.backup.BackupService
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.sdk.extensions.init
import com.tangem.tap.common.ActivityResultCallbackHolder
import com.tangem.tap.common.DialogManager
@ -68,7 +69,6 @@ import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.extensions.showFragmentAllowingStateLoss
import com.tangem.tap.common.redux.NotificationsHandler
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
import com.tangem.tap.features.intentHandler.IntentProcessor
import com.tangem.tap.features.intentHandler.handlers.BackgroundScanIntentHandler

View file

@ -6,8 +6,8 @@ import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase
import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.tap.network.exchangeServices.DefaultRampManager
import com.tangem.tap.proxy.AppStateHolder
import dagger.Module

View file

@ -3,9 +3,9 @@ package com.tangem.tap.di
import android.content.Context
import com.tangem.domain.card.BuildConfig
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.domain.sdk.impl.DefaultTangemSdkManager
import com.tangem.tap.domain.sdk.impl.MockTangemSdkManager
import com.tangem.tap.domain.sdk.TangemSdkManager
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn

View file

@ -2,7 +2,7 @@ package com.tangem.tap.di.data
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.domain.card.DefaultDerivationsRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module

View file

@ -9,9 +9,9 @@ import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.domain.card.DefaultDeleteSavedAccessCodesUseCase
import com.tangem.tap.domain.card.DefaultResetCardUseCase
import com.tangem.tap.domain.sdk.TangemSdkManager
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn

View file

@ -12,7 +12,7 @@ import com.tangem.domain.settings.repositories.PromoSettingsRepository
import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.domain.settings.DefaultLegacySettingsRepository
import dagger.Module
import dagger.Provides

View file

@ -6,7 +6,7 @@ import arrow.core.right
import com.tangem.common.doOnFailure
import com.tangem.common.doOnSuccess
import com.tangem.domain.card.DeleteSavedAccessCodesUseCase
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.sdk.api.TangemSdkManager
internal class DefaultDeleteSavedAccessCodesUseCase(
private val tangemSdkManager: TangemSdkManager,

View file

@ -20,7 +20,7 @@ import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.operations.derivation.ExtendedPublicKeysMap
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.domain.tasks.UserWalletIdPreflightReadFilter
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext

View file

@ -14,7 +14,7 @@ import com.tangem.domain.card.ResetCardUseCase
import com.tangem.domain.card.ResetCardUserCodeParams
import com.tangem.domain.card.models.ResetCardError
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.sdk.api.TangemSdkManager
internal class DefaultResetCardUseCase(
private val tangemSdkManager: TangemSdkManager,

View file

@ -3,7 +3,7 @@ package com.tangem.tap.domain.scanCard.repository
import com.tangem.common.CompletionResult
import com.tangem.domain.card.repository.ScanCardRepository
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.domain.scanCard.utils.ScanCardExceptionConverter
// TODO: Move to the :data:card module

View file

@ -32,8 +32,9 @@ import com.tangem.operations.pins.SetUserCodeCommand
import com.tangem.operations.preflightread.PreflightReadFilter
import com.tangem.operations.usersetttings.SetUserCodeRecoveryAllowedTask
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.derivationsFinder
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.tap.domain.tasks.product.*
import com.tangem.tap.domain.twins.CreateFirstTwinWalletTask
import com.tangem.tap.domain.twins.CreateSecondTwinWalletTask

View file

@ -20,9 +20,9 @@ import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.preflightread.PreflightReadFilter
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.domain.sdk.mocks.MockProvider
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
@Suppress("TooManyFunctions")
class MockTangemSdkManager(

View file

@ -6,7 +6,7 @@ import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
import com.tangem.sdk.api.CreateProductWalletTaskResponse
interface MockContent {

View file

@ -4,10 +4,10 @@ import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemError
import com.tangem.common.core.TangemSdkError
import com.tangem.domain.models.scan.ProductType
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.tap.domain.sdk.mocks.content.NoteMockContent
import com.tangem.tap.domain.sdk.mocks.content.WalletMockContent
import com.tangem.tap.domain.sdk.mocks.content.Wallet2MockContent
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
object MockProvider {

View file

@ -8,8 +8,8 @@ import com.tangem.domain.models.scan.ScanResponse
import com.tangem.operations.attestation.Attestation
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.tap.domain.sdk.mocks.MockContent
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
import java.util.Date
object NoteMockContent : MockContent {

View file

@ -13,8 +13,8 @@ import com.tangem.operations.backup.PrimaryCard
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.derivation.ExtendedPublicKeysMap
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.tap.domain.sdk.mocks.MockContent
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
import java.util.Date
object Wallet2MockContent : MockContent {

View file

@ -13,8 +13,8 @@ import com.tangem.operations.backup.PrimaryCard
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.derivation.ExtendedPublicKeysMap
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.tap.domain.sdk.mocks.MockContent
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
import java.util.Date
object WalletMockContent : MockContent {

View file

@ -1,7 +1,7 @@
package com.tangem.tap.domain.settings
import com.tangem.domain.settings.repositories.LegacySettingsRepository
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.sdk.api.TangemSdkManager
internal class DefaultLegacySettingsRepository(
private val tangemSdkManager: TangemSdkManager,

View file

@ -2,7 +2,6 @@ package com.tangem.tap.domain.tasks.product
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.CompletionResult
import com.tangem.common.card.Card
import com.tangem.common.card.EllipticCurve
import com.tangem.common.card.FirmwareVersion
import com.tangem.common.core.CardSession
@ -19,33 +18,15 @@ import com.tangem.domain.common.DerivationStyleProvider
import com.tangem.domain.common.TapWorkarounds.isTestCard
import com.tangem.domain.common.configs.CardConfig
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.KeyWalletPublicKey
import com.tangem.operations.CommandResponse
import com.tangem.operations.backup.PrimaryCard
import com.tangem.operations.backup.StartPrimaryCardLinkingCommand
import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
import com.tangem.operations.derivation.ExtendedPublicKeysMap
import com.tangem.operations.read.ReadWalletsListCommand
import com.tangem.operations.wallet.CreateWalletTask
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.operations.wallet.CreateWalletResponse as SdkCreateWalletResponse
data class CreateProductWalletTaskResponse(
val card: CardDTO,
val derivedKeys: Map<KeyWalletPublicKey, ExtendedPublicKeysMap> = mapOf(),
val primaryCard: PrimaryCard? = null,
) : CommandResponse {
constructor(
card: Card,
derivedKeys: Map<KeyWalletPublicKey, ExtendedPublicKeysMap> = mapOf(),
primaryCard: PrimaryCard? = null,
) : this(
card = CardDTO(card),
derivedKeys = derivedKeys,
primaryCard = primaryCard,
)
}
private data class CreateWalletResponse(
val cardId: String,
val wallet: CardDTO.Wallet,

View file

@ -18,13 +18,13 @@ import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.builder.UserWalletIdBuilder
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.domain.extensions.signedHashesCount
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.tap.features.details.ui.cardsettings.domain.CardSettingsInteractor
import com.tangem.tap.features.details.ui.common.utils.*
import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletMode

View file

@ -6,10 +6,10 @@ import com.tangem.common.doOnSuccess
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.Analytics
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.tap.features.details.ui.cardsettings.domain.CardSettingsInteractor
import com.tangem.tap.features.details.ui.common.utils.isAccessCodeRecoveryEnabled
import com.tangem.tap.store

View file

@ -7,10 +7,10 @@ import com.tangem.common.core.TangemSdkError
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.Analytics
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.tap.features.details.redux.SecurityOption
import com.tangem.tap.features.details.ui.cardsettings.domain.CardSettingsInteractor
import com.tangem.tap.features.details.ui.common.utils.getAllowedSecurityOptions

View file

@ -2,11 +2,11 @@ package com.tangem.tap.features.onboarding.products.wallet.redux
import android.net.Uri
import com.tangem.common.CompletionResult
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.common.card.Card
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import kotlinx.coroutines.CoroutineScope
import org.rekotlin.Action

View file

@ -28,13 +28,13 @@ import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSo
import com.tangem.feature.wallet.presentation.wallet.domain.BackupValidator
import com.tangem.operations.attestation.OnlineCardVerifier
import com.tangem.operations.backup.BackupService
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.tap.*
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.home.redux.HomeAction
import com.tangem.tap.features.onboarding.OnboardingDialog

View file

@ -5,11 +5,11 @@ import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.redux.StateDialog
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.extensions.onUserWalletSelected
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.tap.network.exchangeServices.ExchangeService
import org.rekotlin.Action
import org.rekotlin.Store

View file

@ -30,6 +30,7 @@ dependencies {
implementation(projects.domain.core)
/** Tangem libraries */
implementation(projects.libs.tangemSdkApi)
implementation(deps.tangem.card.core)
implementation(deps.tangem.card.android) {
exclude(module = "joda-time")
@ -40,12 +41,14 @@ dependencies {
implementation(deps.lifecycle.runtime.ktx)
/** Compose libraries */
implementation(deps.compose.material) // to use buttons
implementation(deps.compose.material3)
implementation(deps.compose.animation)
implementation(deps.compose.foundation)
implementation(deps.compose.ui)
implementation(deps.compose.ui.tooling)
implementation(deps.compose.coil)
implementation(deps.decompose.ext.compose)
/** Other libraries */
implementation(deps.kotlin.immutable.collections)

View file

@ -0,0 +1,9 @@
package com.tangem.features.onboarding.v2
import com.tangem.core.ui.extensions.TextReference
import kotlinx.coroutines.flow.StateFlow
interface TitleProvider {
val currentTitle: StateFlow<TextReference>
fun changeTitle(text: TextReference)
}

View file

@ -1,7 +1,9 @@
package com.tangem.features.onboarding.v2.entry.impl
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import com.arkivanov.decompose.extensions.compose.jetpack.subscribeAsState
import com.arkivanov.decompose.router.stack.ChildStack
import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.childStack
@ -12,16 +14,19 @@ import com.tangem.core.decompose.context.child
import com.tangem.core.decompose.context.childByContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.decompose.navigation.inner.InnerNavigationHolder
import com.tangem.core.ui.extensions.stringReference
import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent
import com.tangem.features.onboarding.v2.entry.impl.model.OnboardingEntryModel
import com.tangem.features.onboarding.v2.entry.impl.routing.OnboardingChildFactory
import com.tangem.features.onboarding.v2.entry.impl.routing.OnboardingRoute
import com.tangem.features.onboarding.v2.entry.impl.ui.OnboardingEntry
import com.tangem.features.onboarding.v2.stepper.api.OnboardingStepperComponent
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
internal class DefaultOnboardingEntryComponent @AssistedInject constructor(
@Assisted val context: AppComponentContext,
@ -30,6 +35,7 @@ internal class DefaultOnboardingEntryComponent @AssistedInject constructor(
onboardingChildFactory: OnboardingChildFactory,
) : OnboardingEntryComponent, AppComponentContext by context {
private val innerNavigationLinkJobHolder = JobHolder()
private val model: OnboardingEntryModel = getOrCreateModel(params)
private val stepperComponent = stepperFactory.create(
@ -39,7 +45,7 @@ internal class DefaultOnboardingEntryComponent @AssistedInject constructor(
initState = OnboardingStepperComponent.StepperState(
currentStep = 0,
steps = 0,
title = stringReference(""),
title = model.titleProvider.currentTitle.value,
showProgress = false,
),
popBack = {
@ -68,6 +74,10 @@ internal class DefaultOnboardingEntryComponent @AssistedInject constructor(
},
)
init {
linkToInnerNavigation()
}
private fun popInternal(onComplete: (Boolean) -> Unit) {
val activeChild = innerStack.value.active.instance
if (activeChild is InnerNavigationHolder) {
@ -77,16 +87,36 @@ internal class DefaultOnboardingEntryComponent @AssistedInject constructor(
}
}
private fun linkToInnerNavigation() {
innerStack.observe { stack ->
val activeChild = stack.active.instance
if (activeChild is InnerNavigationHolder) {
componentScope.launch {
activeChild.innerNavigation.state.collect { state ->
stepperComponent.state.update {
it.copy(
currentStep = state.stackSize,
steps = state.stackMaxSize ?: 0,
title = model.titleProvider.currentTitle.value,
showProgress = state.stackMaxSize != null,
)
}
}
}.saveIn(innerNavigationLinkJobHolder)
}
}
}
@Composable
override fun Content(modifier: Modifier) {
val innerStackState by innerStack.subscribeAsState()
OnboardingEntry(
modifier = modifier,
stepperContent = { modifierParam ->
stepperComponent.Content(modifierParam)
},
content = { modifierParam ->
// TODO
},
childStack = innerStackState,
)
}

View file

@ -1,11 +1,16 @@
package com.tangem.features.onboarding.v2.entry.impl.di
import com.tangem.core.decompose.di.DecomposeComponent
import com.tangem.core.decompose.model.Model
import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent
import com.tangem.features.onboarding.v2.entry.impl.DefaultOnboardingEntryComponent
import com.tangem.features.onboarding.v2.entry.impl.model.OnboardingEntryModel
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
import javax.inject.Singleton
@Module
@ -17,4 +22,13 @@ internal interface ComponentModule {
fun bindOnboardingEntryComponent(
factory: DefaultOnboardingEntryComponent.Factory,
): OnboardingEntryComponent.Factory
}
@Module
@InstallIn(DecomposeComponent::class)
internal interface ModelModule {
@Binds
@IntoMap
@ClassKey(OnboardingEntryModel::class)
fun provideModel(model: OnboardingEntryModel): Model
}

View file

@ -2,6 +2,12 @@ package com.tangem.features.onboarding.v2.entry.impl.model
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.ui.extensions.TextReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.scan.ProductType
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.features.onboarding.v2.TitleProvider
import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent
import com.tangem.features.onboarding.v2.entry.impl.model.state.OnboardingState
import com.tangem.features.onboarding.v2.entry.impl.routing.OnboardingRoute
@ -11,13 +17,42 @@ import javax.inject.Inject
@ComponentScoped
internal class OnboardingEntryModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
private val params: OnboardingEntryComponent.Params,
) : Model() {
private val params = paramsContainer.require<OnboardingEntryComponent.Params>()
val titleProvider = object : TitleProvider {
override val currentTitle = MutableStateFlow(stringReference(""))
override fun changeTitle(text: TextReference) {
currentTitle.value = text
}
}
val state = MutableStateFlow(
OnboardingState(
currentRoute = OnboardingRoute.Wallet12(params.scanResponse),
currentRoute = routeByProductType(params.scanResponse),
),
)
private fun routeByProductType(scanResponse: ScanResponse): OnboardingRoute {
return when (scanResponse.productType) {
ProductType.Note -> TODO()
ProductType.Twins -> TODO()
ProductType.Wallet -> OnboardingRoute.Wallet12(
scanResponse = scanResponse,
withSeedPhraseFlow = false,
titleProvider = titleProvider,
)
ProductType.Wallet2 -> OnboardingRoute.Wallet12(
scanResponse = scanResponse,
withSeedPhraseFlow = true,
titleProvider = titleProvider,
)
ProductType.Start2Coin -> TODO()
ProductType.Ring -> TODO()
ProductType.Visa -> TODO()
}
}
}

View file

@ -1,21 +1,24 @@
package com.tangem.features.onboarding.v2.entry.impl.routing
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.features.onboarding.v2.wallet12.api.OnboardingWallet12Component
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
import javax.inject.Inject
internal class OnboardingChildFactory @Inject constructor(
private val wallet12ComponentFactory: OnboardingWallet12Component.Factory,
private val wallet12ComponentFactory: OnboardingMultiWalletComponent.Factory,
) {
fun createChild(route: OnboardingRoute, childContext: AppComponentContext) {
when (route) {
fun createChild(route: OnboardingRoute, childContext: AppComponentContext): Any {
return when (route) {
is OnboardingRoute.Wallet12 -> wallet12ComponentFactory.create(
context = childContext,
params = OnboardingWallet12Component.Params(
params = OnboardingMultiWalletComponent.Params(
scanResponse = route.scanResponse,
withSeedPhraseFlow = route.withSeedPhraseFlow,
titleProvider = route.titleProvider,
),
)
else -> Unit
}
}
}

View file

@ -2,8 +2,15 @@ package com.tangem.features.onboarding.v2.entry.impl.routing
import com.tangem.core.decompose.navigation.Route
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.features.onboarding.v2.TitleProvider
sealed class OnboardingRoute : Route {
data class Wallet12(val scanResponse: ScanResponse) : OnboardingRoute()
data object None : OnboardingRoute()
data class Wallet12(
val titleProvider: TitleProvider,
val scanResponse: ScanResponse,
val withSeedPhraseFlow: Boolean,
) : OnboardingRoute()
}

View file

@ -4,19 +4,19 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.arkivanov.decompose.extensions.compose.jetpack.stack.Children
import com.arkivanov.decompose.extensions.compose.jetpack.stack.animation.slide
import com.arkivanov.decompose.extensions.compose.jetpack.stack.animation.stackAnimation
import com.arkivanov.decompose.router.stack.ChildStack
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.onboarding.v2.impl.R
import com.tangem.features.onboarding.v2.entry.impl.routing.OnboardingRoute
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
@Composable
internal inline fun OnboardingEntry(
modifier: Modifier = Modifier,
childStack: ChildStack<OnboardingRoute, Any>,
stepperContent: @Composable (Modifier) -> Unit,
content: @Composable (Modifier) -> Unit,
) {
Column(
modifier = modifier
@ -25,28 +25,19 @@ internal inline fun OnboardingEntry(
.background(TangemTheme.colors.background.primary),
) {
stepperContent(Modifier.fillMaxWidth())
content(Modifier.fillMaxSize())
}
}
@Preview
@Composable
private fun Preview() {
TangemThemePreview {
OnboardingEntry(
stepperContent = {
TangemTopAppBar(
title = "Onboarding",
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_back_24,
enabled = true,
onIconClicked = {},
),
)
},
content = { modifier ->
Box(modifier.background(Color.Cyan.copy(alpha = 0.3f)))
},
)
Children(
stack = childStack,
animation = stackAnimation(slide()),
) {
when (it.configuration) {
is OnboardingRoute.Wallet12 -> {
(it.instance as OnboardingMultiWalletComponent).Content(
modifier = modifier,
)
}
OnboardingRoute.None -> {}
}
}
}
}

View file

@ -0,0 +1,18 @@
package com.tangem.features.onboarding.v2.multiwallet.api
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.decompose.navigation.inner.InnerNavigationHolder
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.features.onboarding.v2.TitleProvider
interface OnboardingMultiWalletComponent : ComposableContentComponent, InnerNavigationHolder {
data class Params(
val titleProvider: TitleProvider,
val scanResponse: ScanResponse,
val withSeedPhraseFlow: Boolean,
)
interface Factory : ComponentFactory<Params, OnboardingMultiWalletComponent>
}

View file

@ -0,0 +1,58 @@
package com.tangem.features.onboarding.v2.multiwallet.impl
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.decompose.navigation.inner.InnerNavigation
import com.tangem.core.decompose.navigation.inner.InnerNavigationState
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletModel
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.OnboardingMultiWallet
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.MutableStateFlow
internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor(
@Assisted private val context: AppComponentContext,
@Assisted private val params: OnboardingMultiWalletComponent.Params,
) : OnboardingMultiWalletComponent, AppComponentContext by context {
private val model: OnboardingMultiWalletModel = getOrCreateModel(params)
override val innerNavigation: InnerNavigation = object : InnerNavigation {
override val state = MutableStateFlow(
Wallet12InnerNavigationState(1, 5), // TODO
)
override fun pop(onComplete: (Boolean) -> Unit) {
// TODO
}
}
@Composable
override fun Content(modifier: Modifier) {
val uiState by model.uiState.collectAsStateWithLifecycle()
OnboardingMultiWallet(
modifier = modifier,
state = uiState,
)
}
@AssistedFactory
interface Factory : OnboardingMultiWalletComponent.Factory {
override fun create(
context: AppComponentContext,
params: OnboardingMultiWalletComponent.Params,
): DefaultOnboardingMultiWalletComponent
}
}
data class Wallet12InnerNavigationState(
override val stackSize: Int,
override val stackMaxSize: Int?,
) : InnerNavigationState

View file

@ -0,0 +1,33 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.di
import com.tangem.core.decompose.di.DecomposeComponent
import com.tangem.core.decompose.model.Model
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
import com.tangem.features.onboarding.v2.multiwallet.impl.DefaultOnboardingMultiWalletComponent
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletModel
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal interface ComponentModule {
@Binds
@Singleton
fun bindComponent(factory: DefaultOnboardingMultiWalletComponent.Factory): OnboardingMultiWalletComponent.Factory
}
@Module
@InstallIn(DecomposeComponent::class)
internal interface ModelModule {
@Binds
@IntoMap
@ClassKey(OnboardingMultiWalletModel::class)
fun provideModel(model: OnboardingMultiWalletModel): Model
}

View file

@ -0,0 +1,16 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.model
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.features.onboarding.v2.impl.R
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.state.OnboardingMultiWalletUM
internal fun resetCardDialog(onConfirm: () -> Unit, onDismiss: () -> Unit, onDismissButtonClick: () -> Unit) =
OnboardingMultiWalletUM.Dialog(
title = resourceReference(R.string.onboarding_activation_error_title),
description = resourceReference(R.string.onboarding_activation_error_message),
confirmButtonText = resourceReference(R.string.common_ok),
dismissButtonText = resourceReference(R.string.common_support),
onDismiss = onDismiss,
onConfirm = onConfirm,
onDismissButtonClick = onDismissButtonClick,
)

View file

@ -0,0 +1,140 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.model
import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError
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.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.models.scan.CardDTO
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.state.OnboardingMultiWalletUM
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject
@ComponentScoped
internal class OnboardingMultiWalletModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
private val tangemSdkManager: TangemSdkManager,
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
private val getCardInfoUseCase: GetCardInfoUseCase,
) : Model() {
private val params = paramsContainer.require<OnboardingMultiWalletComponent.Params>()
private val currentScanResponse = MutableStateFlow(params.scanResponse)
val state = MutableStateFlow(
OnboardingMultiWalletState(
currentStep = getInitialStep(),
),
)
val uiState = MutableStateFlow(
OnboardingMultiWalletUM(
onCreateWalletClick = { createWallet(false) },
showSeedPhraseOption = params.withSeedPhraseFlow,
onOtherOptionsClick = { /* navigate */ },
onBack = { },
dialog = null,
),
)
init {
initScreenTitleSub()
}
private fun getInitialStep(): OnboardingMultiWalletState.Step {
val card = currentScanResponse.value.card
return when {
card.wallets.isNotEmpty() && card.backupStatus == CardDTO.BackupStatus.NoBackup ->
OnboardingMultiWalletState.Step.AddBackupDevice
card.wallets.isNotEmpty() && card.backupStatus?.isActive == true ->
OnboardingMultiWalletState.Step.FinishBackup
else ->
OnboardingMultiWalletState.Step.CreateWallet
}
}
private fun initScreenTitleSub() {
val title = screenTitleByStep(getInitialStep())
params.titleProvider.changeTitle(title)
modelScope.launch {
state
.map { it.currentStep }
.collectLatest { step ->
val title = screenTitleByStep(step)
params.titleProvider.changeTitle(title)
}
}
}
private fun createWallet(shouldReset: Boolean) {
modelScope.launch {
val result = tangemSdkManager.createProductWallet(
scanResponse = currentScanResponse.value,
shouldReset = shouldReset,
)
when (result) {
is CompletionResult.Success -> {
currentScanResponse.update {
it.copy(
card = result.data.card,
derivedKeys = result.data.derivedKeys,
primaryCard = result.data.primaryCard,
)
}
// TODO
// Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
}
is CompletionResult.Failure -> {
if (result.error is TangemSdkError.WalletAlreadyCreated) {
// show should reset dialog
handleActivationError()
}
}
}
}
}
private fun handleActivationError() {
uiState.update {
it.copy(
dialog = resetCardDialog(
onConfirm = {
uiState.update { it.copy(dialog = null) }
resetCard()
},
onDismiss = {
uiState.update { it.copy(dialog = null) }
},
onDismissButtonClick = ::navigateToSupportScreen,
),
)
}
}
private fun resetCard() {
createWallet(true)
}
fun navigateToSupportScreen() {
modelScope.launch {
val cardInfo = getCardInfoUseCase(currentScanResponse.value).getOrNull() ?: return@launch
sendFeedbackEmailUseCase(FeedbackEmailType.DirectUserRequest(cardInfo))
}
}
}

View file

@ -0,0 +1,10 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.model
data class OnboardingMultiWalletState(
val currentStep: Step,
) {
enum class Step {
GeneratePrivateKeys, CreateWallet, AddBackupDevice, FinishBackup, Done
}
}

View file

@ -0,0 +1,13 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.model
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.features.onboarding.v2.impl.R
fun screenTitleByStep(step: OnboardingMultiWalletState.Step): TextReference = when (step) {
OnboardingMultiWalletState.Step.GeneratePrivateKeys -> TODO()
OnboardingMultiWalletState.Step.CreateWallet -> resourceReference(R.string.onboarding_create_wallet_header)
OnboardingMultiWalletState.Step.AddBackupDevice -> TODO()
OnboardingMultiWalletState.Step.FinishBackup -> TODO()
OnboardingMultiWalletState.Step.Done -> TODO()
}

View file

@ -0,0 +1,79 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.ui
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.BasicDialog
import com.tangem.core.ui.components.DialogButtonUM
import com.tangem.core.ui.components.PrimaryButtonIconEnd
import com.tangem.core.ui.components.SecondaryButton
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.onboarding.v2.impl.R
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.state.OnboardingMultiWalletUM
@Composable
internal fun OnboardingMultiWallet(state: OnboardingMultiWalletUM, modifier: Modifier = Modifier) {
if (state.dialog != null) {
BasicDialog(
title = state.dialog.title.resolveReference(),
message = state.dialog.description.resolveReference(),
confirmButton = DialogButtonUM(
title = state.dialog.confirmButtonText.resolveReference(),
onClick = state.dialog.onConfirm,
),
dismissButton = DialogButtonUM(
title = state.dialog.dismissButtonText.resolveReference(),
onClick = state.dialog.onDismissButtonClick,
),
onDismissDialog = state.dialog.onDismiss,
)
}
Column(
modifier = modifier
.fillMaxSize()
.navigationBarsPadding()
.verticalScroll(rememberScrollState()),
) {
Box(Modifier.weight(1f))
PrimaryButtonIconEnd(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp)
.fillMaxWidth(),
iconResId = R.drawable.ic_tangem_24,
text = stringResource(R.string.onboarding_create_wallet_button_create_wallet),
onClick = state.onCreateWalletClick,
)
SecondaryButton(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
.fillMaxWidth(),
text = stringResource(R.string.onboarding_create_wallet_options_button_options),
onClick = state.onOtherOptionsClick,
)
}
}
@Preview
@Composable
private fun Preview() {
TangemThemePreview {
OnboardingMultiWallet(
state = OnboardingMultiWalletUM(
onCreateWalletClick = {},
showSeedPhraseOption = true,
onBack = {},
onOtherOptionsClick = {},
dialog = null,
),
)
}
}

View file

@ -0,0 +1,21 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.ui.state
import com.tangem.core.ui.extensions.TextReference
internal data class OnboardingMultiWalletUM(
val onCreateWalletClick: () -> Unit,
val showSeedPhraseOption: Boolean,
val onOtherOptionsClick: () -> Unit,
val onBack: () -> Unit,
val dialog: Dialog?,
) {
data class Dialog(
val title: TextReference,
val description: TextReference,
val dismissButtonText: TextReference,
val confirmButtonText: TextReference,
val onConfirm: () -> Unit,
val onDismissButtonClick: () -> Unit,
val onDismiss: () -> Unit,
)
}

View file

@ -5,7 +5,7 @@ import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.models.scan.ScanResponse
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.MutableStateFlow
internal interface OnboardingStepperComponent : ComposableContentComponent {
@ -22,11 +22,7 @@ internal interface OnboardingStepperComponent : ComposableContentComponent {
val scanResponse: ScanResponse,
)
val state: StateFlow<StepperState>
fun changeStep(step: Int)
fun nextStep()
fun changeTitle(title: TextReference)
val state: MutableStateFlow<StepperState>
interface Factory : ComponentFactory<Params, OnboardingStepperComponent>
}

View file

@ -7,7 +7,6 @@ import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.arkivanov.essenty.instancekeeper.getOrCreateSimple
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.feedback.GetCardInfoUseCase
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.feedback.models.FeedbackEmailType
@ -17,7 +16,6 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
internal class DefaultOnboardingStepperComponent @AssistedInject constructor(
@ -29,24 +27,6 @@ internal class DefaultOnboardingStepperComponent @AssistedInject constructor(
override val state = instanceKeeper.getOrCreateSimple { MutableStateFlow(params.initState) }
override fun changeStep(step: Int) {
state.update { it.copy(currentStep = step.coerceAtLeast(minimumValue = 0)) }
}
override fun nextStep() {
state.update { state ->
if (state.currentStep < state.steps - 1) {
state.copy(currentStep = state.currentStep + 1)
} else {
state
}
}
}
override fun changeTitle(title: TextReference) {
state.update { it.copy(title = title) }
}
private fun openSupport() {
componentScope.launch {
val cardInfo = getCardInfoUseCase(params.scanResponse).getOrNull() ?: return@launch

View file

@ -1,13 +0,0 @@
package com.tangem.features.onboarding.v2.wallet12.api
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.decompose.navigation.inner.InnerNavigationHolder
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.models.scan.ScanResponse
interface OnboardingWallet12Component : ComposableContentComponent, InnerNavigationHolder {
data class Params(val scanResponse: ScanResponse)
interface Factory : ComponentFactory<Params, OnboardingWallet12Component>
}

View file

@ -1,46 +0,0 @@
package com.tangem.features.onboarding.v2.wallet12.impl
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.navigation.inner.InnerNavigation
import com.tangem.core.decompose.navigation.inner.InnerNavigationState
import com.tangem.features.onboarding.v2.wallet12.api.OnboardingWallet12Component
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.MutableStateFlow
@Suppress("UnusedPrivateMember")
class DefaultOnboardingWallet12Component @AssistedInject constructor(
@Assisted private val context: AppComponentContext,
@Assisted private val params: OnboardingWallet12Component.Params,
) : OnboardingWallet12Component, AppComponentContext by context {
override val innerNavigation: InnerNavigation = object : InnerNavigation {
override val state = MutableStateFlow(
Wallet12InnerNavigationState(0, null), // TODO
)
override fun pop(onComplete: (Boolean) -> Unit) {
// TODO
}
}
@Composable
override fun Content(modifier: Modifier) {
}
@AssistedFactory
interface Factory : OnboardingWallet12Component.Factory {
override fun create(
context: AppComponentContext,
params: OnboardingWallet12Component.Params,
): DefaultOnboardingWallet12Component
}
}
data class Wallet12InnerNavigationState(
override val stackSize: Int,
override val stackMaxSize: Int?,
) : InnerNavigationState

View file

@ -1,20 +0,0 @@
package com.tangem.features.onboarding.v2.wallet12.impl.di
import com.tangem.features.onboarding.v2.wallet12.api.OnboardingWallet12Component
import com.tangem.features.onboarding.v2.wallet12.impl.DefaultOnboardingWallet12Component
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal interface ComponentModule {
@Binds
@Singleton
fun bindOnboardingWallet12Component(
factory: DefaultOnboardingWallet12Component.Factory,
): OnboardingWallet12Component.Factory
}

1
libs/tangem-sdk-api/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,35 @@
plugins {
alias(deps.plugins.android.library)
alias(deps.plugins.kotlin.android)
alias(deps.plugins.kotlin.kapt)
alias(deps.plugins.kotlin.serialization)
alias(deps.plugins.hilt.android)
id("configuration")
}
android {
namespace = "com.tangem.legacy"
}
dependencies {
implementation(projects.common)
implementation(projects.domain.models)
implementation(projects.domain.card)
implementation(projects.domain.legacy)
implementation(projects.domain.wallets.models)
implementation(projects.core.res)
/** Tangem libraries */
implementation(deps.tangem.card.core)
implementation(deps.tangem.card.android) {
exclude(module = "joda-time")
}
/** Other libraries */
implementation(deps.timber)
/** DI */
implementation(deps.hilt.android)
kapt(deps.hilt.kapt)
}

View file

@ -0,0 +1,24 @@
package com.tangem.sdk.api
import com.tangem.common.card.Card
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.KeyWalletPublicKey
import com.tangem.operations.CommandResponse
import com.tangem.operations.backup.PrimaryCard
import com.tangem.operations.derivation.ExtendedPublicKeysMap
data class CreateProductWalletTaskResponse(
val card: CardDTO,
val derivedKeys: Map<KeyWalletPublicKey, ExtendedPublicKeysMap> = mapOf(),
val primaryCard: PrimaryCard? = null,
) : CommandResponse {
constructor(
card: Card,
derivedKeys: Map<KeyWalletPublicKey, ExtendedPublicKeysMap> = mapOf(),
primaryCard: PrimaryCard? = null,
) : this(
card = CardDTO(card),
derivedKeys = derivedKeys,
primaryCard = primaryCard,
)
}

View file

@ -1,4 +1,4 @@
package com.tangem.tap.domain.sdk
package com.tangem.sdk.api
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
@ -19,7 +19,6 @@ import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.preflightread.PreflightReadFilter
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
@Suppress("TooManyFunctions")
interface TangemSdkManager {
@ -96,8 +95,8 @@ interface TangemSdkManager {
): CompletionResult<CardDTO>
@Deprecated(
"TangemSdkManager shouldn't run custom tasks. " +
"All of them should be specified in TangemSdkManager certain methods.",
"com.tangem.sdk.api.TangemSdkManager shouldn't run custom tasks. " +
"All of them should be specified in com.tangem.sdk.api.TangemSdkManager certain methods.",
)
suspend fun <T> runTaskAsync(
runnable: CardSessionRunnable<T>,
@ -111,7 +110,7 @@ interface TangemSdkManager {
@Suppress("MagicNumber")
fun changeDisplayedCardIdNumbersCount(scanResponse: ScanResponse?)
@Deprecated("TangemSdkManager shouldn't returns a string from resources")
@Deprecated("com.tangem.sdk.api.TangemSdkManager shouldn't returns a string from resources")
fun getString(@StringRes stringResId: Int, vararg formatArgs: Any?): String
fun setUserCodeRequestPolicy(policy: UserCodeRequestPolicy)

View file

@ -0,0 +1,49 @@
package com.tangem.sdk.api
import androidx.annotation.StringRes
import com.tangem.common.core.TangemError
import com.tangem.legacy.R
interface TapErrors
interface ArgError {
val args: List<Any>?
}
interface MultiMessageError : TapErrors {
val errorList: List<TapError>
val builder: (List<String>) -> String
}
sealed class TapError(
@StringRes val messageResource: Int,
override val args: List<Any>? = null,
) : Throwable(), TapErrors, ArgError {
object UnknownError : TapError(R.string.send_error_unknown)
open class CustomError(val customMessage: String) : TapError(R.string.common_custom_string, listOf(customMessage))
object NoInternetConnection : TapError(R.string.wallet_notification_no_internet)
sealed class WalletManager {
class NoAccountError(amountToCreateAccount: String) : CustomError(amountToCreateAccount)
class InternalError(message: String) : CustomError(message)
object BlockchainIsUnreachableTryLater : TapError(R.string.wallet_balance_blockchain_unreachable_try_later)
}
}
sealed class TapSdkError(override val messageResId: Int?) : TangemError(code = 50100) {
override var customMessage: String = code.toString()
object CardForDifferentApp : TapSdkError(R.string.alert_unsupported_card)
object CardNotSupportedByRelease : TapSdkError(R.string.error_wrong_card_type)
}
fun TapErrors.assembleErrors(): MutableList<Pair<Int, List<Any>?>> {
val idList = mutableListOf<Pair<Int, List<Any>?>>()
when (this) {
is MultiMessageError -> this.errorList.forEach { idList.addAll(it.assembleErrors()) }
is TapError -> idList.add(Pair(this.messageResource, this.args))
}
return idList
}

View file

@ -147,6 +147,7 @@ include(":libs:auth")
include(":libs:blockchain-sdk")
include(":libs:crypto")
include(":libs:visa")
include(":libs:tangem-sdk-api")
// endregion Libs modules
// region Feature modules