Updated on 2026-08-14
This commit is contained in:
parent
e0eafb4df9
commit
bde99e272b
32 changed files with 384 additions and 184 deletions
|
|
@ -25,7 +25,7 @@ dependencies {
|
|||
implementation(project(":domain:legacy"))
|
||||
implementation(project(":domain:models"))
|
||||
implementation(project(":domain:core"))
|
||||
implementation(project(":domain:card"))
|
||||
implementation(projects.domain.card)
|
||||
implementation(project(":domain:wallets"))
|
||||
implementation(project(":domain:wallets:models"))
|
||||
implementation(projects.domain.tokens)
|
||||
|
|
@ -41,6 +41,7 @@ dependencies {
|
|||
implementation(project(":libs:crypto"))
|
||||
implementation(project(":libs:auth"))
|
||||
implementation(project(":data:source:preferences"))
|
||||
implementation(projects.data.card)
|
||||
implementation(projects.data.tokens)
|
||||
|
||||
/** Features */
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@ import androidx.core.view.WindowCompat
|
|||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.data.card.sdk.CardSdkLifecycleObserver
|
||||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.features.tester.api.TesterRouter
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||
|
|
@ -56,7 +57,6 @@ import java.lang.ref.WeakReference
|
|||
import javax.inject.Inject
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
lateinit var tangemSdk: TangemSdk
|
||||
lateinit var tangemSdkManager: TangemSdkManager
|
||||
lateinit var backupService: BackupService
|
||||
internal var lockUserWalletsTimer: LockUserWalletsTimer? = null
|
||||
|
|
@ -88,7 +88,10 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
lateinit var testerRouter: TesterRouter
|
||||
|
||||
@Inject
|
||||
lateinit var injectedTangemSdk: TangemSdk
|
||||
lateinit var cardSdkLifecycleObserver: CardSdkLifecycleObserver
|
||||
|
||||
@Inject
|
||||
lateinit var cardSdkConfigRepository: CardSdkConfigRepository
|
||||
|
||||
@Inject
|
||||
lateinit var injectedTangemSdkManager: TangemSdkManager
|
||||
|
|
@ -122,11 +125,11 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
systemActions()
|
||||
store.dispatch(NavigationAction.ActivityCreated(WeakReference(this)))
|
||||
|
||||
tangemSdk = injectedTangemSdk
|
||||
cardSdkLifecycleObserver.onCreate(context = this)
|
||||
|
||||
tangemSdkManager = injectedTangemSdkManager
|
||||
appStateHolder.tangemSdkManager = tangemSdkManager
|
||||
appStateHolder.tangemSdk = tangemSdk
|
||||
backupService = BackupService.init(tangemSdk, this)
|
||||
backupService = BackupService.init(cardSdkConfigRepository.sdk, this)
|
||||
lockUserWalletsTimer = LockUserWalletsTimer(owner = this)
|
||||
|
||||
initUserWalletsListManager()
|
||||
|
|
@ -144,10 +147,37 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
walletRouter = walletRouter,
|
||||
walletConnectInteractor = walletConnectInteractor,
|
||||
tokenDetailsRouter = tokenDetailsRouter,
|
||||
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialogManager.onStart(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
// TODO: RESEARCH! NotificationsHandler is created in onResume and destroyed in onStop
|
||||
notificationsHandler = NotificationsHandler(binding.fragmentContainer)
|
||||
|
||||
navigateToInitialScreenIfNeededOnResume(intent)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
notificationsHandler = null
|
||||
dialogManager.onStop()
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
store.dispatch(NavigationAction.ActivityDestroyed(WeakReference(this)))
|
||||
intentProcessor.removeAll()
|
||||
cardSdkLifecycleObserver.onDestroy()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun initIntentHandlers() {
|
||||
val hasSavedWalletsProvider = { store.state.globalState.userWalletsListManager?.hasUserWallets == true }
|
||||
intentProcessor.addHandler(BackgroundScanIntentHandler(hasSavedWalletsProvider))
|
||||
|
|
@ -183,13 +213,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
notificationsHandler = NotificationsHandler(binding.fragmentContainer)
|
||||
|
||||
navigateToInitialScreenIfNeededOnResume(intent)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
super.onNewIntent(intent)
|
||||
scope.launch {
|
||||
|
|
@ -197,23 +220,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialogManager.onStart(this)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
notificationsHandler = null
|
||||
dialogManager.onStop()
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
store.dispatch(NavigationAction.ActivityDestroyed(WeakReference(this)))
|
||||
intentProcessor.removeAll()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun showSnackbar(text: Int, buttonTitle: Int?, action: View.OnClickListener?) {
|
||||
if (snackbar != null) return
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ package com.tangem.tap.common.redux
|
|||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import org.rekotlin.Middleware
|
||||
|
||||
class AccessCodeRequestPolicyMiddleware {
|
||||
|
|
@ -19,9 +20,8 @@ class AccessCodeRequestPolicyMiddleware {
|
|||
}
|
||||
|
||||
private fun updateAccessCodeRequestPolicy(scanResponse: ScanResponse) {
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes &&
|
||||
scanResponse.card.isAccessCodeSet,
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes && scanResponse.card.isAccessCodeSet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +1,43 @@
|
|||
package com.tangem.tap.di
|
||||
|
||||
import android.content.Context
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.sdk.extensions.initWithBiometrics
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.tap.domain.TangemSdkManager
|
||||
import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository
|
||||
import com.tangem.tap.userTokensRepository
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ActivityComponent
|
||||
import dagger.hilt.android.qualifiers.ActivityContext
|
||||
import dagger.hilt.android.scopes.ActivityScoped
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(ActivityComponent::class)
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object ActivityModule {
|
||||
|
||||
@Provides
|
||||
@ActivityScoped
|
||||
fun provideTangemSdk(@ActivityContext context: Context): TangemSdk {
|
||||
return TangemSdk.initWithBiometrics(context as FragmentActivity, TangemSdkManager.config)
|
||||
@Singleton
|
||||
fun provideTangemSdkManager(
|
||||
@ApplicationContext context: Context,
|
||||
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
): TangemSdkManager {
|
||||
return TangemSdkManager(cardSdkConfigRepository = cardSdkConfigRepository, resources = context.resources)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ActivityScoped
|
||||
fun provideTangemSdkManager(@ActivityContext context: Context, tangemSdk: TangemSdk): TangemSdkManager {
|
||||
return TangemSdkManager(tangemSdk, context)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ActivityScoped
|
||||
fun provideScanCardUseCase(tangemSdk: TangemSdk, tangemSdkManager: TangemSdkManager): ScanCardUseCase {
|
||||
@Singleton
|
||||
fun provideScanCardUseCase(
|
||||
tangemSdkManager: TangemSdkManager,
|
||||
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
): ScanCardUseCase {
|
||||
return ScanCardUseCase(
|
||||
tangemSdk = tangemSdk,
|
||||
scanCardRepository = DefaultScanCardRepository(userTokensRepository, tangemSdkManager),
|
||||
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||
scanCardRepository = DefaultScanCardRepository(
|
||||
userTokensRepository = userTokensRepository,
|
||||
tangemSdkManager = tangemSdkManager,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +1,25 @@
|
|||
package com.tangem.tap.domain
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import androidx.annotation.StringRes
|
||||
import com.tangem.Message
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.*
|
||||
import com.tangem.common.biometric.BiometricManager
|
||||
import com.tangem.common.card.FirmwareVersion
|
||||
import com.tangem.common.core.*
|
||||
import com.tangem.common.extensions.ByteArrayKey
|
||||
import com.tangem.common.usersCode.UserCodeRepository
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.crypto.bip39.DefaultMnemonic
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.operations.ScanTask
|
||||
import com.tangem.operations.derivation.DerivationTaskResponse
|
||||
import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
|
||||
import com.tangem.operations.pins.CheckUserCodesCommand
|
||||
import com.tangem.operations.pins.CheckUserCodesResponse
|
||||
import com.tangem.operations.pins.SetUserCodeCommand
|
||||
import com.tangem.operations.usersetttings.SetUserCodeRecoveryAllowedTask
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
|
|
@ -38,7 +36,10 @@ import kotlinx.coroutines.withContext
|
|||
import kotlin.coroutines.resume
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Context) {
|
||||
class TangemSdkManager(private val cardSdkConfigRepository: CardSdkConfigRepository, private val resources: Resources) {
|
||||
|
||||
private val tangemSdk: TangemSdk
|
||||
get() = cardSdkConfigRepository.sdk
|
||||
|
||||
private val userCodeRepository by lazy {
|
||||
UserCodeRepository(
|
||||
|
|
@ -63,7 +64,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
messageRes: Int? = null,
|
||||
allowsRequestAccessCodeFromRepository: Boolean = false,
|
||||
): CompletionResult<ScanResponse> {
|
||||
val message = Message(context.getString(messageRes ?: R.string.initial_message_scan_header))
|
||||
val message = Message(resources.getString(messageRes ?: R.string.initial_message_scan_header))
|
||||
return runTaskAsyncReturnOnMain(
|
||||
runnable = ScanProductTask(
|
||||
card = null,
|
||||
|
|
@ -80,7 +81,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
return runTaskAsync(
|
||||
CreateProductWalletTask(scanResponse.cardTypesResolver),
|
||||
scanResponse.card.cardId,
|
||||
Message(context.getString(R.string.initial_message_create_wallet_body)),
|
||||
Message(resources.getString(R.string.initial_message_create_wallet_body)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +93,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
is CompletionResult.Success -> runTaskAsync(
|
||||
CreateProductWalletTask(scanResponse.cardTypesResolver, seedResult.data),
|
||||
scanResponse.card.cardId,
|
||||
Message(context.getString(R.string.initial_message_create_wallet_body)),
|
||||
Message(resources.getString(R.string.initial_message_create_wallet_body)),
|
||||
)
|
||||
|
||||
is CompletionResult.Failure -> CompletionResult.Failure(seedResult.error)
|
||||
|
|
@ -111,7 +112,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
return runTaskAsyncReturnOnMain(
|
||||
CreateWalletAndRescanTask(),
|
||||
cardId,
|
||||
initialMessage = Message(context.getString(R.string.initial_message_create_wallet_body)),
|
||||
initialMessage = Message(resources.getString(R.string.initial_message_create_wallet_body)),
|
||||
)
|
||||
.map { CardDTO(it) }
|
||||
}
|
||||
|
|
@ -127,7 +128,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
return runTaskAsyncReturnOnMain(
|
||||
runnable = ResetToFactorySettingsTask(),
|
||||
cardId = cardId,
|
||||
initialMessage = Message(context.getString(R.string.card_settings_reset_card_to_factory)),
|
||||
initialMessage = Message(resources.getString(R.string.card_settings_reset_card_to_factory)),
|
||||
)
|
||||
.map { CardDTO(it) }
|
||||
}
|
||||
|
|
@ -154,7 +155,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
return runTaskAsyncReturnOnMain(
|
||||
SetUserCodeCommand.changePasscode(null),
|
||||
cardId,
|
||||
initialMessage = Message(context.getString(R.string.initial_message_change_passcode_body)),
|
||||
initialMessage = Message(resources.getString(R.string.initial_message_change_passcode_body)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +163,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
return runTaskAsyncReturnOnMain(
|
||||
SetUserCodeCommand.changeAccessCode(null),
|
||||
cardId,
|
||||
initialMessage = Message(context.getString(R.string.initial_message_change_access_code_body)),
|
||||
initialMessage = Message(resources.getString(R.string.initial_message_change_access_code_body)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -170,15 +171,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
return runTaskAsyncReturnOnMain(
|
||||
SetUserCodeCommand.resetUserCodes(),
|
||||
cardId,
|
||||
initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun checkUserCodes(cardId: String?): CompletionResult<CheckUserCodesResponse> {
|
||||
return runTaskAsyncReturnOnMain(
|
||||
CheckUserCodesCommand(),
|
||||
cardId,
|
||||
initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
|
||||
initialMessage = Message(resources.getString(R.string.initial_message_tap_header)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +179,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
return runTaskAsyncReturnOnMain(
|
||||
SetUserCodeRecoveryAllowedTask(enabled),
|
||||
cardId,
|
||||
initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
|
||||
initialMessage = Message(resources.getString(R.string.initial_message_tap_header)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +190,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
return runTaskAsyncReturnOnMain(
|
||||
runnable = ScanTask(allowRequestAccessCodeFromRepository),
|
||||
cardId = cardId,
|
||||
initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
|
||||
initialMessage = Message(resources.getString(R.string.initial_message_tap_header)),
|
||||
)
|
||||
.map { CardDTO(it) }
|
||||
}
|
||||
|
|
@ -233,31 +226,8 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("TangemSdkManager shouldn't returns a string from resources")
|
||||
fun getString(@StringRes stringResId: Int, vararg formatArgs: Any?): String {
|
||||
return context.getString(stringResId, *formatArgs)
|
||||
}
|
||||
|
||||
fun setAccessCodeRequestPolicy(useBiometricsForAccessCode: Boolean) {
|
||||
tangemSdk.config.userCodeRequestPolicy = if (useBiometricsForAccessCode) {
|
||||
UserCodeRequestPolicy.AlwaysWithBiometrics(codeType = UserCodeType.AccessCode)
|
||||
} else {
|
||||
UserCodeRequestPolicy.Default
|
||||
}
|
||||
}
|
||||
|
||||
fun useBiometricsForAccessCode(): Boolean {
|
||||
val policy = tangemSdk.config.userCodeRequestPolicy
|
||||
return policy is UserCodeRequestPolicy.AlwaysWithBiometrics && policy.codeType == UserCodeType.AccessCode
|
||||
}
|
||||
|
||||
companion object {
|
||||
val config = Config(
|
||||
linkedTerminal = true,
|
||||
allowUntrustedCards = true,
|
||||
filter = CardFilter(
|
||||
allowedCardTypes = FirmwareVersion.FirmwareType.values().toList(),
|
||||
maxFirmwareVersion = FirmwareVersion(major = 4, minor = 52),
|
||||
),
|
||||
)
|
||||
return resources.getString(stringResId, *formatArgs)
|
||||
}
|
||||
}
|
||||
|
|
@ -36,8 +36,8 @@ import com.tangem.tap.domain.walletconnect2.domain.models.binance.WcBinanceTrans
|
|||
import com.tangem.tap.features.details.redux.walletconnect.*
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialogData
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionRequestDialogData
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdk
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import com.trustwallet.walletconnect.models.ethereum.WCEthereumSignMessage.WCSignType.*
|
||||
import timber.log.Timber
|
||||
|
|
@ -163,7 +163,10 @@ class WalletConnectSdkHelper {
|
|||
private suspend fun sendTransaction(data: WcTransactionData, cardId: String?): String? {
|
||||
val result = (data.walletManager as TransactionSender).send(
|
||||
transactionData = data.transaction,
|
||||
signer = CommonSigner(tangemSdk, cardId),
|
||||
signer = CommonSigner(
|
||||
tangemSdk = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||
cardId = cardId,
|
||||
),
|
||||
)
|
||||
return when (result) {
|
||||
SimpleResult.Success -> {
|
||||
|
|
|
|||
|
|
@ -372,9 +372,9 @@ class DetailsMiddleware {
|
|||
Analytics.send(Settings.AppSettings.SaveAccessCodeSwitcherChanged(AnalyticsParam.OnOffState.On))
|
||||
|
||||
preferencesStorage.shouldSaveAccessCodes = true
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = scanResponse?.card?.isAccessCodeSet == true,
|
||||
)
|
||||
store.state.daggerGraphState
|
||||
.get(DaggerGraphState::cardSdkConfigRepository)
|
||||
.setAccessCodeRequestPolicy(isBiometricsRequestPolicy = scanResponse?.card?.isAccessCodeSet == true)
|
||||
|
||||
return CompletionResult.Success(Unit)
|
||||
}
|
||||
|
|
@ -385,9 +385,9 @@ class DetailsMiddleware {
|
|||
Analytics.send(Settings.AppSettings.SaveAccessCodeSwitcherChanged(AnalyticsParam.OnOffState.Off))
|
||||
|
||||
preferencesStorage.shouldSaveAccessCodes = false
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = false,
|
||||
)
|
||||
store.state.daggerGraphState
|
||||
.get(DaggerGraphState::cardSdkConfigRepository)
|
||||
.setAccessCodeRequestPolicy(isBiometricsRequestPolicy = false)
|
||||
}
|
||||
.doOnFailure { error ->
|
||||
Timber.e(error, "Unable to delete saved access codes")
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import com.tangem.core.analytics.models.AnalyticsEvent
|
|||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
||||
import com.tangem.tap.common.analytics.events.Shop
|
||||
|
|
@ -26,7 +25,11 @@ import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
|
|||
import com.tangem.tap.features.home.redux.HomeMiddleware.BUY_WALLET_URL
|
||||
import com.tangem.tap.features.send.redux.states.ButtonState
|
||||
import com.tangem.tap.features.signin.redux.SignInAction
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.userWalletsListManager
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.rekotlin.Action
|
||||
|
|
@ -74,8 +77,8 @@ private fun handleHomeAction(action: Action) {
|
|||
|
||||
private fun readCard(analyticsEvent: AnalyticsEvent?) = scope.launch {
|
||||
delay(timeMillis = 200)
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes,
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
|
||||
)
|
||||
|
||||
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan(
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ import com.tangem.tap.features.onboarding.OnboardingDialog
|
|||
import com.tangem.tap.features.onboarding.OnboardingHelper
|
||||
import com.tangem.tap.features.wallet.models.toCurrencies
|
||||
import com.tangem.tap.features.wallet.redux.Artwork
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import kotlinx.coroutines.launch
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.DispatchFunction
|
||||
import org.rekotlin.Middleware
|
||||
|
||||
object OnboardingWalletMiddleware {
|
||||
|
|
@ -43,8 +43,8 @@ private val onboardingWalletMiddleware: Middleware<AppState> = { dispatch, state
|
|||
{ next ->
|
||||
{ action ->
|
||||
when (action) {
|
||||
is OnboardingWallet2Action -> handleWallet2Action(action, state)
|
||||
else -> handleWalletAction(action, state, dispatch)
|
||||
is OnboardingWallet2Action -> handleWallet2Action(action)
|
||||
else -> handleWalletAction(action)
|
||||
}
|
||||
next(action)
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ private val onboardingWalletMiddleware: Middleware<AppState> = { dispatch, state
|
|||
}
|
||||
|
||||
@Suppress("LongMethod", "ComplexMethod")
|
||||
private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch: DispatchFunction) {
|
||||
private fun handleWalletAction(action: Action) {
|
||||
if (action !is OnboardingWalletAction) return
|
||||
|
||||
val globalState = store.state.globalState
|
||||
|
|
@ -178,7 +178,7 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
|||
}
|
||||
|
||||
@Suppress("LongMethod", "ComplexMethod")
|
||||
private fun handleWallet2Action(action: OnboardingWallet2Action, state: () -> AppState?) {
|
||||
private fun handleWallet2Action(action: OnboardingWallet2Action) {
|
||||
val globalState = store.state.globalState
|
||||
val onboardingManager = globalState.onboardingState.onboardingManager
|
||||
|
||||
|
|
@ -329,7 +329,9 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
is BackupAction.AddBackupCard -> {
|
||||
backupService.addBackupCard { result ->
|
||||
backupService.skipCompatibilityChecks = false
|
||||
tangemSdk.config.filter.cardIdFilter = null
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk
|
||||
.config.filter.cardIdFilter = null
|
||||
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
store.dispatchOnMain(BackupAction.AddBackupCard.Success)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.tangem.tap.domain.model.builders.UserWalletBuilder
|
|||
import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
|
||||
import com.tangem.tap.domain.userWalletList.isLockable
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import kotlinx.coroutines.launch
|
||||
import org.rekotlin.Middleware
|
||||
import timber.log.Timber
|
||||
|
|
@ -110,9 +111,10 @@ internal class SaveWalletMiddleware {
|
|||
// Enable saving access codes only if this is the first time user save the wallet
|
||||
if (isFirstSavedWallet) {
|
||||
preferencesStorage.shouldSaveAccessCodes = true
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = userWallet.hasAccessCode,
|
||||
)
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository)
|
||||
.setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = userWallet.hasAccessCode,
|
||||
)
|
||||
}
|
||||
|
||||
val savedUserWallet = userWalletsListManager.selectedUserWalletSync.guard {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider
|
|||
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.ton.TonTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder.XrpTransactionExtras
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
|
|
@ -15,6 +14,7 @@ import com.tangem.common.core.TangemSdkError
|
|||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.common.services.Result
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
|
|
@ -39,6 +39,7 @@ import com.tangem.tap.features.send.redux.FeeAction.RequestFee
|
|||
import com.tangem.tap.features.send.redux.states.*
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
|
|
@ -201,6 +202,7 @@ private fun sendTransaction(
|
|||
return@launch
|
||||
}
|
||||
|
||||
val tangemSdk = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk
|
||||
val linkedTerminalState = tangemSdk.config.linkedTerminal
|
||||
if (card.isStart2Coin) {
|
||||
tangemSdk.config.linkedTerminal = false
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ class TradeCryptoMiddleware {
|
|||
}
|
||||
|
||||
scope.launch {
|
||||
exchangeManager.buyErc20TestnetTokens(
|
||||
buyErc20TestnetTokens(
|
||||
card = card,
|
||||
walletManager = walletManager,
|
||||
token = currency.token,
|
||||
|
|
|
|||
|
|
@ -126,11 +126,13 @@ internal class WalletSelectorMiddleware {
|
|||
private fun addWallet() = scope.launch {
|
||||
Analytics.send(MyWallets.Button.ScanNewCard())
|
||||
|
||||
val prevUseBiometricsForAccessCode = tangemSdkManager.useBiometricsForAccessCode()
|
||||
val cardSdkConfigRepository = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository)
|
||||
|
||||
val prevUseBiometricsForAccessCode = cardSdkConfigRepository.isBiometricsRequestPolicy()
|
||||
|
||||
// Update access code policy for access code saving when a card was scanned
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes,
|
||||
cardSdkConfigRepository.setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
|
||||
)
|
||||
|
||||
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan(
|
||||
|
|
@ -147,14 +149,14 @@ internal class WalletSelectorMiddleware {
|
|||
saveUserWalletAndPopBackToWalletScreen(scanResponse)
|
||||
.doOnFailure { error ->
|
||||
// Rollback policy if card saving was failed
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
||||
cardSdkConfigRepository.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
||||
Timber.e(error, "Unable to save user wallet")
|
||||
store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error))
|
||||
}
|
||||
},
|
||||
onFailure = { error ->
|
||||
// Rollback policy if card scanning was failed
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
||||
cardSdkConfigRepository.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
||||
Timber.e(error, "Unable to scan card")
|
||||
store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error))
|
||||
},
|
||||
|
|
|
|||
|
|
@ -100,8 +100,8 @@ internal class WelcomeMiddleware {
|
|||
}
|
||||
|
||||
private suspend inline fun scanCardInternal(crossinline onCardScanned: suspend (ScanResponse) -> Unit) {
|
||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes,
|
||||
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
|
||||
)
|
||||
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan(
|
||||
analyticsEvent = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.SignIn),
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
|||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.TangemSigner
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdk
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -86,11 +86,7 @@ class CurrencyExchangeManager(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun CurrencyExchangeManager.buyErc20TestnetTokens(
|
||||
card: CardDTO,
|
||||
walletManager: EthereumWalletManager,
|
||||
token: Token,
|
||||
) {
|
||||
suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletManager, token: Token) {
|
||||
walletManager.safeUpdate()
|
||||
|
||||
val amountToSend = Amount(walletManager.wallet.blockchain)
|
||||
|
|
@ -109,7 +105,7 @@ suspend fun CurrencyExchangeManager.buyErc20TestnetTokens(
|
|||
|
||||
val signer = TangemSigner(
|
||||
card = card,
|
||||
tangemSdk = tangemSdk,
|
||||
tangemSdk = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||
initialMessage = Message(),
|
||||
) { signResponse ->
|
||||
store.dispatch(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.proxy
|
||||
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.navigation.NavigationStateHolder
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
|
|
@ -30,7 +29,6 @@ class AppStateHolder @Inject constructor() : WalletsStateHolder, NavigationState
|
|||
var userTokensRepository: UserTokensRepository? = null
|
||||
var mainStore: Store<AppState>? = null
|
||||
var tangemSdkManager: TangemSdkManager? = null
|
||||
var tangemSdk: TangemSdk? = null
|
||||
var walletStoresManager: WalletStoresManager? = null
|
||||
var appFiatCurrency: FiatCurrency = FiatCurrency.Default
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.tangem.blockchain.extensions.isNetworkError
|
|||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.common.BlockchainNetwork
|
||||
import com.tangem.domain.common.extensions.fromNetworkId
|
||||
import com.tangem.lib.crypto.TransactionManager
|
||||
|
|
@ -24,7 +25,6 @@ import com.tangem.tap.common.analytics.events.Basic
|
|||
import com.tangem.tap.common.analytics.events.Basic.TransactionSent.MemoType
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.TangemSigner
|
||||
import com.tangem.tap.tangemSdk
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
import java.math.MathContext
|
||||
|
|
@ -34,6 +34,7 @@ import java.math.RoundingMode
|
|||
class TransactionManagerImpl(
|
||||
private val appStateHolder: AppStateHolder,
|
||||
private val analytics: AnalyticsEventHandler,
|
||||
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
) : TransactionManager {
|
||||
|
||||
override suspend fun sendApproveTransaction(
|
||||
|
|
@ -395,7 +396,7 @@ class TransactionManagerImpl(
|
|||
val actualCard = requireNotNull(appStateHolder.getActualCard()) { "no card found" }
|
||||
return TangemSigner(
|
||||
card = actualCard,
|
||||
tangemSdk = tangemSdk,
|
||||
tangemSdk = cardSdkConfigRepository.sdk,
|
||||
initialMessage = Message(),
|
||||
) { signResponse ->
|
||||
appStateHolder.mainStore?.dispatch(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.proxy.di
|
|||
|
||||
import androidx.compose.ui.text.intl.Locale
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.feature.learn2earn.domain.api.Learn2earnDependencyProvider
|
||||
import com.tangem.lib.crypto.DerivationManager
|
||||
import com.tangem.lib.crypto.TransactionManager
|
||||
|
|
@ -39,8 +40,13 @@ class ProxyModule {
|
|||
fun provideTransactionManager(
|
||||
appStateHolder: AppStateHolder,
|
||||
analytics: AnalyticsEventHandler,
|
||||
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
): TransactionManager {
|
||||
return TransactionManagerImpl(appStateHolder, analytics)
|
||||
return TransactionManagerImpl(
|
||||
appStateHolder = appStateHolder,
|
||||
analytics = analytics,
|
||||
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.proxy.redux
|
||||
|
||||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.features.tester.api.TesterRouter
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||
import com.tangem.features.wallet.navigation.WalletRouter
|
||||
|
|
@ -15,5 +16,6 @@ sealed interface DaggerGraphAction : Action {
|
|||
val walletRouter: WalletRouter,
|
||||
val walletConnectInteractor: WalletConnectInteractor,
|
||||
val tokenDetailsRouter: TokenDetailsRouter,
|
||||
val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
) : DaggerGraphAction
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ object DaggerGraphReducer {
|
|||
walletRouter = action.walletRouter,
|
||||
walletConnectInteractor = action.walletConnectInteractor,
|
||||
tokenDetailsRouter = action.tokenDetailsRouter,
|
||||
cardSdkConfigRepository = action.cardSdkConfigRepository,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.datasource.asset.AssetReader
|
|||
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.features.tester.api.TesterRouter
|
||||
import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||
|
|
@ -29,6 +30,7 @@ data class DaggerGraphState(
|
|||
val tokenDetailsFeatureToggles: TokenDetailsFeatureToggles? = null,
|
||||
val tokenDetailsRouter: TokenDetailsRouter? = null,
|
||||
val scanCardProcessor: ScanCardProcessor? = null,
|
||||
val cardSdkConfigRepository: CardSdkConfigRepository? = null,
|
||||
) : StateType {
|
||||
|
||||
inline fun <reified T> get(getDependency: DaggerGraphState.() -> T?): T {
|
||||
|
|
|
|||
1
data/card/.gitignore
vendored
Normal file
1
data/card/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
21
data/card/build.gradle.kts
Normal file
21
data/card/build.gradle.kts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
alias(deps.plugins.kotlin.kapt)
|
||||
alias(deps.plugins.hilt.android)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.data.card"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(deps.hilt.android)
|
||||
kapt(deps.hilt.kapt)
|
||||
implementation(deps.tangem.card.android)
|
||||
implementation(deps.tangem.card.core)
|
||||
|
||||
implementation(projects.domain.card)
|
||||
implementation(projects.domain.models)
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package com.tangem.data.card
|
||||
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.common.UserCodeType
|
||||
import com.tangem.common.core.CardIdDisplayFormat
|
||||
import com.tangem.common.core.UserCodeRequestPolicy
|
||||
import com.tangem.data.card.sdk.CardSdkProvider
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
|
||||
/**
|
||||
* Implementation of repository for managing with CardSDK config
|
||||
*
|
||||
* @property cardSdkProvider CardSDK instance provider
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultCardSdkConfigRepository(
|
||||
private val cardSdkProvider: CardSdkProvider,
|
||||
) : CardSdkConfigRepository {
|
||||
|
||||
@Deprecated("Use CardSdkConfigRepository's methods instead of this property")
|
||||
override val sdk: TangemSdk
|
||||
get() = cardSdkProvider.sdk
|
||||
|
||||
override fun setAccessCodeRequestPolicy(isBiometricsRequestPolicy: Boolean) {
|
||||
sdk.config.userCodeRequestPolicy = if (isBiometricsRequestPolicy) {
|
||||
UserCodeRequestPolicy.AlwaysWithBiometrics(codeType = UserCodeType.AccessCode)
|
||||
} else {
|
||||
UserCodeRequestPolicy.Default
|
||||
}
|
||||
}
|
||||
|
||||
override fun isBiometricsRequestPolicy(): Boolean {
|
||||
return with(sdk.config.userCodeRequestPolicy) {
|
||||
this is UserCodeRequestPolicy.AlwaysWithBiometrics && codeType == UserCodeType.AccessCode
|
||||
}
|
||||
}
|
||||
|
||||
override fun resetCardIdDisplayFormat() {
|
||||
sdk.config.cardIdDisplayFormat = CardIdDisplayFormat.Full
|
||||
}
|
||||
|
||||
override fun updateCardIdDisplayFormat(productType: ProductType) {
|
||||
sdk.config.cardIdDisplayFormat = when (productType) {
|
||||
ProductType.Twins -> CardIdDisplayFormat.LastLuhn(numbers = 4)
|
||||
ProductType.Note,
|
||||
ProductType.Wallet,
|
||||
ProductType.Start2Coin,
|
||||
-> CardIdDisplayFormat.Full
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.data.card.di
|
||||
|
||||
import com.tangem.data.card.DefaultCardSdkConfigRepository
|
||||
import com.tangem.data.card.sdk.CardSdkProvider
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object CardDataModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideCardSdkConfigRepository(cardSdkProvider: CardSdkProvider): CardSdkConfigRepository {
|
||||
return DefaultCardSdkConfigRepository(cardSdkProvider = cardSdkProvider)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.data.card.di
|
||||
|
||||
import com.tangem.data.card.sdk.CardSdkLifecycleObserver
|
||||
import com.tangem.data.card.sdk.CardSdkProvider
|
||||
import com.tangem.data.card.sdk.DefaultCardSdkProvider
|
||||
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 CardSdkModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun provideCardSdkProvider(defaultCardSdkProvider: DefaultCardSdkProvider): CardSdkProvider
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun providerCardSdkLifecycleObserver(defaultCardSdkProvider: DefaultCardSdkProvider): CardSdkLifecycleObserver
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.data.card.sdk
|
||||
|
||||
import android.content.Context
|
||||
|
||||
/**
|
||||
* Lifecycle observer for creating Card SDK instance
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface CardSdkLifecycleObserver {
|
||||
|
||||
/** Callback of creating activity [context] */
|
||||
fun onCreate(context: Context)
|
||||
|
||||
/** Callback of destroying activity */
|
||||
fun onDestroy()
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.data.card.sdk
|
||||
|
||||
import com.tangem.TangemSdk
|
||||
|
||||
/**
|
||||
* CardSDK instance provider
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal interface CardSdkProvider {
|
||||
|
||||
/** CardSDK instance */
|
||||
val sdk: TangemSdk
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.tangem.data.card.sdk
|
||||
|
||||
import android.content.Context
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.common.CardFilter
|
||||
import com.tangem.common.card.FirmwareVersion
|
||||
import com.tangem.common.core.Config
|
||||
import com.tangem.sdk.extensions.initWithBiometrics
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Implementation of CardSDK instance provider
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Singleton
|
||||
internal class DefaultCardSdkProvider @Inject constructor() : CardSdkProvider, CardSdkLifecycleObserver {
|
||||
|
||||
override val sdk: TangemSdk
|
||||
get() = requireNotNull(value = _sdk) { "Impossible to get the TangemSdk when activity is destroyed" }
|
||||
|
||||
private var _sdk: TangemSdk? = null
|
||||
|
||||
override fun onCreate(context: Context) {
|
||||
_sdk = TangemSdk.initWithBiometrics(activity = context as FragmentActivity, config = config)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
_sdk = null
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
val config = Config(
|
||||
linkedTerminal = true,
|
||||
allowUntrustedCards = true,
|
||||
filter = CardFilter(
|
||||
allowedCardTypes = FirmwareVersion.FirmwareType.values().toList(),
|
||||
maxFirmwareVersion = FirmwareVersion(major = 4, minor = 52),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,47 +4,46 @@ import arrow.core.Either
|
|||
import arrow.core.EitherNel
|
||||
import arrow.core.flatMap
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.common.core.CardIdDisplayFormat
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.card.repository.ScanCardRepository
|
||||
import com.tangem.domain.core.chain.Chain
|
||||
import com.tangem.domain.core.chain.ChainProcessor
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
|
||||
/**
|
||||
* Use case responsible for scanning a card and returning a [ScanResponse] object.
|
||||
* @property scanCardRepository A repository object implementing [ScanCardRepository] interface.
|
||||
* @property tangemSdk An instance of [TangemSdk] to configure the display format of the card ID.
|
||||
* @constructor Create a new instance of [ScanCardUseCase] with the given dependencies.
|
||||
* Use case responsible for scanning a card and returning a [ScanResponse] object
|
||||
*
|
||||
* @property scanCardRepository a repository object implementing [ScanCardRepository] interface
|
||||
* @property cardSdkConfigRepository an instance of [TangemSdk] to configure the display format of the card ID
|
||||
*
|
||||
* @constructor create a new instance of [ScanCardUseCase] with the given dependencies
|
||||
*/
|
||||
class ScanCardUseCase(
|
||||
private val scanCardRepository: ScanCardRepository,
|
||||
private val tangemSdk: TangemSdk,
|
||||
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
) {
|
||||
|
||||
/**
|
||||
* A [ChainProcessor] object to launch the after-scan chains.
|
||||
*/
|
||||
/** A [ChainProcessor] object to launch the after-scan chains */
|
||||
private val scanChainProcessor by lazy {
|
||||
ChainProcessor<ScanCardException.ChainException, ScanResponse>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan a card and return a [ScanResponse] object.
|
||||
* @param cardId an optional card ID to scan. If null, can scan any card present.
|
||||
* Defaults to null.
|
||||
* @param allowRequestAccessCodeFromStorage whether to prompt the user for an access code if needed.
|
||||
* Defaults to false.
|
||||
* @param afterScanChains A list of chains that should be executed after a successful card scan operation.
|
||||
* Defaults to an empty array.
|
||||
* @return A [EitherNel] object with either a non-empty list of [ScanCardException] or a [ScanResponse].
|
||||
*
|
||||
* @param cardId an optional card ID to scan. If null, can scan any card present
|
||||
* @param allowRequestAccessCodeFromStorage whether to prompt the user for an access code if needed
|
||||
* @param afterScanChains a list of chains that should be executed after a successful card scan
|
||||
* operation. Defaults to an empty array
|
||||
*
|
||||
* @return a [EitherNel] object with either a non-empty list of [ScanCardException] or a [ScanResponse]
|
||||
*/
|
||||
suspend operator fun invoke(
|
||||
cardId: String? = null,
|
||||
allowRequestAccessCodeFromStorage: Boolean = false,
|
||||
afterScanChains: List<Chain<ScanCardException.ChainException, ScanResponse>> = emptyList(),
|
||||
): Either<ScanCardException, ScanResponse> {
|
||||
resetCardIdDisplayFormat()
|
||||
cardSdkConfigRepository.resetCardIdDisplayFormat()
|
||||
scanChainProcessor.addChains(afterScanChains)
|
||||
|
||||
return scanCardRepository.scanCard(
|
||||
|
|
@ -52,31 +51,10 @@ class ScanCardUseCase(
|
|||
allowRequestAccessCodeFromStorage = allowRequestAccessCodeFromStorage,
|
||||
)
|
||||
.onRight { scanResponse ->
|
||||
updateCardIdDisplayFormat(scanResponse.productType)
|
||||
cardSdkConfigRepository.updateCardIdDisplayFormat(scanResponse.productType)
|
||||
}
|
||||
.flatMap { response ->
|
||||
scanChainProcessor.launchChains(initial = response)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the card ID display format to [CardIdDisplayFormat.Full].
|
||||
*/
|
||||
private fun resetCardIdDisplayFormat() {
|
||||
tangemSdk.config.cardIdDisplayFormat = CardIdDisplayFormat.Full
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the card ID display format according to the [ProductType] of the scanned card.
|
||||
* @param productType The [ProductType] of the scanned card.
|
||||
*/
|
||||
private fun updateCardIdDisplayFormat(productType: ProductType) {
|
||||
tangemSdk.config.cardIdDisplayFormat = when (productType) {
|
||||
ProductType.Twins -> CardIdDisplayFormat.LastLuhn(numbers = 4)
|
||||
ProductType.Note,
|
||||
ProductType.Wallet,
|
||||
ProductType.Start2Coin,
|
||||
-> CardIdDisplayFormat.Full
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.domain.card.repository
|
||||
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
|
||||
/**
|
||||
* Repository for managing with CardSDK config
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface CardSdkConfigRepository {
|
||||
|
||||
/** Tangem SDK instance */
|
||||
@Deprecated("Use CardSdkConfigRepository's methods instead of this property")
|
||||
val sdk: TangemSdk
|
||||
|
||||
/** Set access code request policy by [isBiometricsRequestPolicy] */
|
||||
fun setAccessCodeRequestPolicy(isBiometricsRequestPolicy: Boolean)
|
||||
|
||||
/** Check if config has biometrics request policy */
|
||||
fun isBiometricsRequestPolicy(): Boolean
|
||||
|
||||
/** Reset the card ID display format to start value */
|
||||
fun resetCardIdDisplayFormat()
|
||||
|
||||
/** Update the card ID display format according to the [productType] of the scanned card */
|
||||
fun updateCardIdDisplayFormat(productType: ProductType)
|
||||
}
|
||||
|
|
@ -85,6 +85,7 @@ include(":domain:tokens")
|
|||
// endregion Domain modules
|
||||
|
||||
// region Data modules
|
||||
include(":data:card")
|
||||
include(":data:tokens")
|
||||
include(":data:source:preferences")
|
||||
// endregion Data modules
|
||||
Loading…
Add table
Add a link
Reference in a new issue