diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2791ba88f4..85ed2fdfb3 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -76,11 +76,10 @@ dependencies {
implementation(projects.data.txhistory)
implementation(projects.data.wallets)
implementation(projects.data.analytics)
+ implementation(projects.data.transaction)
/** Features */
implementation(projects.features.onboarding)
- implementation(projects.features.learn2earn.api)
- implementation(projects.features.learn2earn.impl)
implementation(projects.features.referral.presentation)
implementation(projects.features.referral.domain)
implementation(projects.features.referral.data)
@@ -99,6 +98,8 @@ dependencies {
implementation(projects.features.manageTokens.api)
implementation(projects.features.manageTokens.impl)
implementation(projects.features.send.impl)
+ implementation(projects.features.qrScanning.api)
+ implementation(projects.features.qrScanning.impl)
/** AndroidX libraries */
implementation(deps.androidx.core.ktx)
@@ -146,6 +147,7 @@ dependencies {
/** DI */
implementation(deps.hilt.android)
+
kapt(deps.hilt.kapt)
/** Other libraries */
@@ -158,7 +160,6 @@ dependencies {
implementation(deps.timber)
implementation(deps.reKotlin)
implementation(deps.zxing.qrCore)
- implementation(deps.otaliastudiosCameraView)
implementation(deps.coil)
implementation(deps.appsflyer)
implementation(deps.amplitude)
@@ -186,7 +187,9 @@ dependencies {
}
/** Testing libraries */
+ testImplementation(deps.test.coroutine)
testImplementation(deps.test.junit)
+ testImplementation(deps.test.mockk)
testImplementation(deps.test.truth)
androidTestImplementation(deps.test.junit.android)
androidTestImplementation(deps.test.espresso)
@@ -208,7 +211,7 @@ dependencies {
/** Excluded dependencies */
implementation("com.google.guava:guava:30.0-android") {
// excludes version 9999.0-empty-to-avoid-conflict-with-guava
- exclude(group="com.google.guava", module = "listenablefuture")
+ exclude(group = "com.google.guava", module = "listenablefuture")
}
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3eb4bc059b..32e44932c0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -137,14 +137,6 @@
-
-
-
-
@@ -206,6 +210,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
manageTokensRouter = manageTokensRouter,
cardSdkConfigRepository = cardSdkConfigRepository,
sendRouter = sendRouter,
+ qrScanningRouter = qrScanningRouter,
),
)
}
@@ -247,20 +252,15 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
private fun createAppThemeModeFlow(): SharedFlow {
val tapApplication = application as TapApplication
- val featureToggle = tapApplication.darkThemeFeatureToggle
- return if (featureToggle.isDarkThemeEnabled) {
- tapApplication.getAppThemeModeUseCase()
- .map { maybeMode ->
- maybeMode.getOrElse { AppThemeMode.DEFAULT }
- }
- .shareIn(
- scope = lifecycleScope + Dispatchers.IO,
- started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5_000),
- )
- } else {
- MutableStateFlow(AppThemeMode.FORCE_LIGHT)
- }
+ return tapApplication.getAppThemeModeUseCase()
+ .map { maybeMode ->
+ maybeMode.getOrElse { AppThemeMode.DEFAULT }
+ }
+ .shareIn(
+ scope = lifecycleScope + Dispatchers.IO,
+ started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5_000),
+ )
}
override fun onStart() {
@@ -454,7 +454,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
private fun checkForNotificationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
- BuildConfig.DEBUG &&
+ BuildConfig.LOG_ENABLED &&
ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) !=
PackageManager.PERMISSION_GRANTED
) {
diff --git a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt
index cef921c1d6..fefb785d4c 100644
--- a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt
+++ b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt
@@ -11,6 +11,7 @@ import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
class NavBarInsetsFragmentLifecycleCallback : FragmentLifecycleCallbacks() {
+
override fun onFragmentViewCreated(fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle?) {
if (v is ComposeView) return
diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt
index 0aecd2719a..f892dddee4 100644
--- a/app/src/main/java/com/tangem/tap/TapApplication.kt
+++ b/app/src/main/java/com/tangem/tap/TapApplication.kt
@@ -10,8 +10,6 @@ import com.orhanobut.logger.AndroidLogAdapter
import com.orhanobut.logger.Logger
import com.tangem.Log
import com.tangem.LogFormat
-import com.tangem.blockchain.common.BlockchainSdkConfig
-import com.tangem.blockchain.common.WalletManagerFactory
import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.filter.OneTimeEventFilter
@@ -30,23 +28,22 @@ import com.tangem.domain.apptheme.GetAppThemeModeUseCase
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
import com.tangem.domain.card.ScanCardProcessor
+import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.domain.common.LogConfig
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.legacy.UserWalletsListManager
-import com.tangem.domain.wallets.legacy.WalletManagersRepository
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.features.managetokens.featuretoggles.ManageTokensFeatureToggles
import com.tangem.features.send.api.featuretoggles.SendFeatureToggles
-import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
+import com.tangem.features.tester.api.TesterFeatureToggles
import com.tangem.tap.common.analytics.AnalyticsFactory
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
import com.tangem.tap.common.analytics.handlers.BlockchainExceptionHandler
import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHandler
import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler
import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
-import com.tangem.tap.common.analytics.topup.TopUpController
import com.tangem.tap.common.chat.ChatManager
import com.tangem.tap.common.feedback.AdditionalFeedbackInfo
import com.tangem.tap.common.feedback.FeedbackManager
@@ -59,24 +56,11 @@ import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.shop.TangemShopService
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
import com.tangem.tap.domain.tasks.product.DerivationsFinder
-import com.tangem.tap.domain.tokens.UserTokensRepository
-import com.tangem.tap.domain.tokens.UserTokensStorageService
-import com.tangem.tap.domain.totalBalance.TotalFiatBalanceCalculator
-import com.tangem.tap.domain.totalBalance.di.provideDefaultImplementation
import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
import com.tangem.tap.domain.userWalletList.di.provideRuntimeImplementation
-import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
-import com.tangem.tap.domain.walletCurrencies.di.provideDefaultImplementation
-import com.tangem.tap.domain.walletStores.WalletStoresManager
-import com.tangem.tap.domain.walletStores.di.provideDefaultImplementation
-import com.tangem.tap.domain.walletStores.repository.WalletAmountsRepository
-import com.tangem.tap.domain.walletStores.repository.WalletStoresRepository
-import com.tangem.tap.domain.walletStores.repository.di.provideDefaultImplementation
import com.tangem.tap.domain.walletconnect.WalletConnectRepository
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository
import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles
-import com.tangem.tap.features.details.DarkThemeFeatureToggle
-import com.tangem.tap.features.details.featuretoggles.DetailsFeatureToggles
import com.tangem.tap.proxy.AppStateHolder
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider
@@ -95,47 +79,8 @@ lateinit var activityResultCaller: ActivityResultCaller
lateinit var preferencesStorage: PreferencesDataSource
lateinit var walletConnectRepository: WalletConnectRepository
lateinit var shopService: TangemShopService
-internal lateinit var userTokensRepository: UserTokensRepository
internal lateinit var derivationsFinder: DerivationsFinder
-private val walletStoresRepository by lazy { WalletStoresRepository.provideDefaultImplementation() }
-private val walletManagersRepository by lazy {
- WalletManagersRepository.provideDefaultImplementation(
- walletManagerFactory = WalletManagerFactory(
- config = store.state.globalState.configManager
- ?.config
- ?.blockchainSdkConfig
- ?: BlockchainSdkConfig(),
- ),
- )
-}
-private val walletAmountsRepository by lazy {
- WalletAmountsRepository.provideDefaultImplementation(
- tangemTechService = store.state.domainNetworks.tangemTechService,
- )
-}
-val walletStoresManager by lazy {
- WalletStoresManager.provideDefaultImplementation(
- userTokensRepository = userTokensRepository,
- walletStoresRepository = walletStoresRepository,
- walletManagersRepository = walletManagersRepository,
- walletAmountsRepository = walletAmountsRepository,
- appCurrencyProvider = { store.state.globalState.appCurrency },
- )
-}
-val walletCurrenciesManager by lazy {
- WalletCurrenciesManager.provideDefaultImplementation(
- userTokensRepository = userTokensRepository,
- walletStoresRepository = walletStoresRepository,
- walletManagersRepository = walletManagersRepository,
- walletAmountsRepository = walletAmountsRepository,
- appCurrencyProvider = { store.state.globalState.appCurrency },
- )
-}
-val totalFiatBalanceCalculator by lazy {
- TotalFiatBalanceCalculator.provideDefaultImplementation()
-}
-
@HiltAndroidApp
internal class TapApplication : Application(), ImageLoaderFactory {
@@ -161,18 +106,12 @@ internal class TapApplication : Application(), ImageLoaderFactory {
@Inject
lateinit var preferencesDataSource: PreferencesDataSource
- @Inject
- lateinit var walletFeatureToggles: WalletFeatureToggles
-
@Inject
lateinit var walletConnect2Repository: WalletConnect2Repository
@Inject
lateinit var walletConnectSessionsRepository: WalletConnectSessionsRepository
- // @Inject
- // lateinit var learn2earnInteractor: Learn2earnInteractor
-
@Inject
lateinit var manageTokensFeatureToggles: ManageTokensFeatureToggles
@@ -200,12 +139,6 @@ internal class TapApplication : Application(), ImageLoaderFactory {
@Inject
lateinit var balanceHidingRepository: BalanceHidingRepository
- @Inject
- lateinit var detailsFeatureToggles: DetailsFeatureToggles
-
- @Inject
- lateinit var darkThemeFeatureToggle: DarkThemeFeatureToggle
-
@Inject
lateinit var userTokensStore: UserTokensStore
@@ -220,6 +153,12 @@ internal class TapApplication : Application(), ImageLoaderFactory {
@Inject
lateinit var oneTimeEventFilter: OneTimeEventFilter
+
+ @Inject
+ lateinit var derivationsRepository: DerivationsRepository
+
+ @Inject
+ lateinit var testerFeatureToggles: TesterFeatureToggles
// endregion Injected
override fun onCreate() {
@@ -227,7 +166,7 @@ internal class TapApplication : Application(), ImageLoaderFactory {
store = createReduxStore()
- if (BuildConfig.DEBUG) {
+ if (BuildConfig.LOG_ENABLED) {
Logger.addLogAdapter(AndroidLogAdapter(TimberFormatStrategy()))
Timber.plant(
object : Timber.DebugTree() {
@@ -250,7 +189,6 @@ internal class TapApplication : Application(), ImageLoaderFactory {
runBlocking {
initUserWalletsListManager()
featureTogglesManager.init()
- // learn2earnInteractor.init()
}
val configLoader = FeaturesLocalLoader(assetReader, MoshiConverter.sdkMoshi, BuildConfig.ENVIRONMENT)
@@ -266,23 +204,12 @@ internal class TapApplication : Application(), ImageLoaderFactory {
)
}
- val userTokensStorageService = UserTokensStorageService.init(context = this)
- userTokensRepository = UserTokensRepository.init(
- tangemTechService = store.state.domainNetworks.tangemTechService,
- networkConnectionManager = networkConnectionManager,
- storageService = userTokensStorageService,
- )
derivationsFinder = DerivationsFinder(
- legacyTokensStore = userTokensStorageService,
newTokensStore = userTokensStore,
- walletFeatureToggles = walletFeatureToggles,
dispatchers = AppCoroutineDispatcherProvider(),
)
appStateHolder.mainStore = store
- appStateHolder.userTokensRepository = userTokensRepository
- appStateHolder.walletStoresManager = walletStoresManager
- initTopUpController()
walletConnect2Repository.init(projectId = configManager.config.walletConnectProjectId)
}
@@ -292,10 +219,8 @@ internal class TapApplication : Application(), ImageLoaderFactory {
middleware = AppState.getMiddleware(),
state = AppState(
daggerGraphState = DaggerGraphState(
- assetReader = assetReader,
networkConnectionManager = networkConnectionManager,
customTokenFeatureToggles = customTokenFeatureToggles,
- walletFeatureToggles = walletFeatureToggles,
walletConnectRepository = walletConnect2Repository,
walletConnectSessionsRepository = walletConnectSessionsRepository,
manageTokensFeatureToggles = manageTokensFeatureToggles,
@@ -307,26 +232,15 @@ internal class TapApplication : Application(), ImageLoaderFactory {
currenciesRepository = currenciesRepository,
appThemeModeRepository = appThemeModeRepository,
balanceHidingRepository = balanceHidingRepository,
- detailsFeatureToggles = detailsFeatureToggles,
walletsRepository = walletsRepository,
sendFeatureToggles = sendFeatureToggles,
+ derivationsRepository = derivationsRepository,
+ testerFeatureToggles = testerFeatureToggles,
),
),
)
}
- private fun initTopUpController() {
- val topUpController = TopUpController(
- scanResponseProvider = {
- store.state.globalState.scanResponse
- ?: store.state.globalState.onboardingState.onboardingManager?.scanResponse
- },
- walletStoresManagerProvider = { walletStoresManager },
- topupWalletStorage = preferencesStorage.toppedUpWalletStorage,
- )
- store.dispatch(GlobalAction.SetTopUpController(topUpController))
- }
-
override fun newImageLoader(): ImageLoader {
return createCoilImageLoader(
context = this,
diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt
index 11af89cb89..a7da950412 100644
--- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt
+++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt
@@ -5,18 +5,13 @@ import android.content.Context
import com.tangem.core.navigation.StateDialog
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.common.redux.global.GlobalState
-import com.tangem.tap.common.ui.SimpleAlertDialog
-import com.tangem.tap.common.ui.SimpleCancelableAlertDialog
+import com.tangem.tap.common.ui.*
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectDialog
import com.tangem.tap.features.details.ui.walletconnect.dialogs.*
-import com.tangem.tap.features.onboarding.AddressInfoBottomSheetDialog
import com.tangem.tap.features.onboarding.OnboardingDialog
import com.tangem.tap.features.onboarding.products.twins.ui.dialog.TwinningProcessNotCompletedDialog
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupDialog
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.*
-import com.tangem.tap.features.wallet.redux.models.WalletDialog
-import com.tangem.tap.features.wallet.ui.dialogs.*
-import com.tangem.tap.features.wallet.ui.wallet.CurrencySelectionDialog
import com.tangem.tap.store
import com.tangem.wallet.R
import org.rekotlin.StoreSubscriber
@@ -50,13 +45,14 @@ class DialogManager : StoreSubscriber {
if (dialog != null) return
dialog = when (state.dialog) {
- is AppDialog.SimpleOkDialog -> SimpleOkDialog.create(state.dialog, context)
is AppDialog.SimpleOkDialogRes -> SimpleOkDialog.create(state.dialog, context)
- is AppDialog.SimpleOkErrorDialog -> SimpleOkDialog.create(state.dialog, context)
- is AppDialog.SimpleOkWarningDialog -> SimpleOkDialog.create(state.dialog, context)
is StateDialog.ScanFailsDialog -> ScanFailsDialog.create(context)
is AppDialog.AddressInfoDialog -> AddressInfoBottomSheetDialog(state.dialog, context)
is AppDialog.TestActionsDialog -> TestActionsBottomSheetDialog(state.dialog, context)
+ is AppDialog.RussianCardholdersWarningDialog -> RussianCardholdersWarningBottomSheetDialog(
+ context,
+ state.dialog.data,
+ )
is OnboardingDialog.TwinningProcessNotCompleted -> TwinningProcessNotCompletedDialog.create(context)
is OnboardingDialog.InterruptOnboarding -> InterruptOnboardingDialog.create(context, state.dialog)
is WalletConnectDialog.UnsupportedCard ->
@@ -124,6 +120,7 @@ class DialogManager : StoreSubscriber {
onReject = state.dialog.onReject,
)
}
+ is BackupDialog.AttestationFailed -> AttestationFailedDialog.create(context)
is BackupDialog.AddMoreBackupCards -> AddMoreBackupCardsDialog.create(context)
is BackupDialog.BackupInProgress -> BackupInProgressDialog.create(context)
is BackupDialog.UnfinishedBackupFound -> UnfinishedBackupFoundDialog.create(context)
@@ -132,11 +129,7 @@ class DialogManager : StoreSubscriber {
context = context,
cardId = state.dialog.cardId,
)
- is WalletDialog.CurrencySelectionDialog -> CurrencySelectionDialog.create(state.dialog, context)
- is WalletDialog.ChooseTradeActionDialog -> ChooseTradeActionBottomSheetDialog(context, state.dialog)
- is WalletDialog.SelectAmountToSendDialog -> AmountToSendBottomSheetDialog(context, state.dialog)
- is WalletDialog.SignedHashesMultiWalletDialog -> SignedHashesWarningDialog.create(context)
- is WalletDialog.TokensAreLinkedDialog -> SimpleAlertDialog.create(
+ is AppDialog.TokensAreLinkedDialog -> SimpleAlertDialog.create(
title = context.getString(state.dialog.titleRes, state.dialog.currencySymbol),
message = context.getString(
state.dialog.messageRes,
@@ -145,15 +138,13 @@ class DialogManager : StoreSubscriber {
),
context = context,
)
- is WalletDialog.RemoveWalletDialog -> SimpleCancelableAlertDialog.create(
+ is AppDialog.RemoveWalletDialog -> SimpleCancelableAlertDialog.create(
title = context.getString(state.dialog.titleRes, state.dialog.currencyTitle),
messageRes = state.dialog.messageRes,
context = context,
primaryButtonRes = state.dialog.primaryButtonRes,
primaryButtonAction = state.dialog.onOk,
)
- is WalletDialog.RussianCardholdersWarningDialog ->
- RussianCardholdersWarningBottomSheetDialog(context, state.dialog.data)
else -> null
}
dialog?.show()
diff --git a/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt b/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt
index 298bc14995..0a51404cf9 100644
--- a/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt
+++ b/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt
@@ -20,7 +20,7 @@ class GlobalLayoutStateHandler(
if (attachImmediately) attach()
}
- fun attach() {
+ private fun attach() {
if (isAttached) {
Timber.d("Already attached")
return
diff --git a/app/src/main/java/com/tangem/tap/common/Handler.kt b/app/src/main/java/com/tangem/tap/common/Handler.kt
index 37b39734cb..7842da9fbf 100644
--- a/app/src/main/java/com/tangem/tap/common/Handler.kt
+++ b/app/src/main/java/com/tangem/tap/common/Handler.kt
@@ -11,20 +11,6 @@ fun postUi(ms: Long = 0, func: Runnable) {
if (ms == 0L) uiHandler.post { func.run() } else uiHandler.postDelayed(func, ms)
}
-fun postBackground(ms: Long = 0, func: Runnable) {
- if (ms == 0L) backgroundHandler.post { func.run() } else backgroundHandler.postDelayed(func, ms)
-}
-
fun postUiDelayBg(ms: Long, func: Runnable) {
backgroundHandler.postDelayed({ uiHandler.post(func) }, ms)
-}
-
-fun post(ms: Long = 0, func: Runnable) {
- if (ms == 0L) {
- func.run()
- } else {
- val currentLooper = Looper.myLooper() ?: return
-
- Handler(currentLooper).postDelayed(func, ms)
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/ShimmerRecyclerAdapter.kt b/app/src/main/java/com/tangem/tap/common/ShimmerRecyclerAdapter.kt
deleted file mode 100644
index ff09e08de7..0000000000
--- a/app/src/main/java/com/tangem/tap/common/ShimmerRecyclerAdapter.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.tangem.tap.common
-
-import android.view.ViewGroup
-import androidx.recyclerview.widget.DiffUtil
-import androidx.recyclerview.widget.ListAdapter
-import androidx.recyclerview.widget.RecyclerView
-
-/**
-[REDACTED_AUTHOR]
- */
-open class ShimmerRecyclerAdapter(
- private val viewHolderViewFactory: (ViewGroup) -> ViewGroup,
-) : ListAdapter(DiffUtilCallback) {
-
- override fun getItemId(position: Int): Long {
- return if (currentList.isEmpty()) 0 else currentList[position].hashCode().toLong()
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShimmerVH {
- return ShimmerVH(viewHolderViewFactory.invoke(parent))
- }
-
- override fun onBindViewHolder(holder: ShimmerVH, position: Int) {}
-
- object DiffUtilCallback : DiffUtil.ItemCallback() {
- override fun areContentsTheSame(oldItem: ShimmerData, newItem: ShimmerData) = oldItem == newItem
- override fun areItemsTheSame(oldItem: ShimmerData, newItem: ShimmerData) = oldItem == newItem
- }
-}
-
-class ShimmerVH(viewGroup: ViewGroup) : RecyclerView.ViewHolder(viewGroup)
-
-@Suppress("UnusedPrivateMember")
-data class ShimmerData(private val any: String = "")
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/TestActions.kt b/app/src/main/java/com/tangem/tap/common/TestActions.kt
index b787e7a1b3..955b89e867 100644
--- a/app/src/main/java/com/tangem/tap/common/TestActions.kt
+++ b/app/src/main/java/com/tangem/tap/common/TestActions.kt
@@ -8,11 +8,8 @@ import androidx.appcompat.widget.LinearLayoutCompat
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.tangem.tap.common.extensions.dispatchDialogHide
-import com.tangem.tap.common.extensions.dispatchDialogShow
-import com.tangem.tap.common.extensions.show
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.store
-import com.tangem.wallet.BuildConfig
/**
[REDACTED_AUTHOR]
@@ -22,18 +19,6 @@ object TestActions {
// It used only for the test actions in debug or debug_beta builds
var testAmountInjectionForWalletManagerEnabled = false
-
- /**
- * @param isTestView - true must be used if you want to show or hide your view depends on BuildConfig
- */
- fun initFor(view: View, actions: List, isTestView: Boolean = false) {
- if (!BuildConfig.TEST_ACTION_ENABLED) return
- if (isTestView) view.show(BuildConfig.TEST_ACTION_ENABLED)
-
- view.setOnClickListener {
- store.dispatchDialogShow(AppDialog.TestActionsDialog(actions))
- }
- }
}
typealias TestAction = Pair Unit>
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsFactory.kt b/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsFactory.kt
index ed2e3868b5..e6383007c0 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsFactory.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsFactory.kt
@@ -22,10 +22,6 @@ class AnalyticsFactory {
filters.add(filter)
}
- fun addParamsInterceptor(interceptor: ParamsInterceptor) {
- interceptors.add(interceptor)
- }
-
fun build(analytics: Analytics, data: AnalyticsHandlerBuilder.Data) {
builders.mapNotNull { it.build(data) }.forEach { analytics.addHandler(it.id(), it) }
filters.forEach { analytics.addFilter(it) }
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/AnalyticsErrorConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/AnalyticsErrorConverter.kt
index 1e279cc84b..b8e9b2e458 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/converters/AnalyticsErrorConverter.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/AnalyticsErrorConverter.kt
@@ -1,10 +1,10 @@
package com.tangem.tap.common.analytics.converters
import com.tangem.blockchain.common.BlockchainSdkError
-import com.tangem.common.Converter
import com.tangem.common.core.TangemSdkError
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.features.demo.DemoTransactionSender
+import com.tangem.utils.converter.Converter
/**
[REDACTED_AUTHOR]
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt
index 0a7928efd5..303dcf3b25 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt
@@ -1,17 +1,18 @@
package com.tangem.tap.common.analytics.converters
import com.tangem.blockchain.common.Blockchain
-import com.tangem.common.Converter
import com.tangem.domain.common.CardTypesResolver
import com.tangem.tap.common.analytics.events.AnalyticsParam
+import com.tangem.utils.converter.Converter
+import com.tangem.core.analytics.models.AnalyticsParam as CoreAnalyticsParam
/**
[REDACTED_AUTHOR]
*/
-class ParamCardCurrencyConverter : Converter {
+class ParamCardCurrencyConverter : Converter {
- override fun convert(value: CardTypesResolver): AnalyticsParam.CardCurrency? {
- if (value.isMultiwalletAllowed()) return AnalyticsParam.CardCurrency.MultiCurrency
+ override fun convert(value: CardTypesResolver): CoreAnalyticsParam.WalletType? {
+ if (value.isMultiwalletAllowed()) return CoreAnalyticsParam.WalletType.MultiCurrency
val type = when {
value.isTangemNote() -> AnalyticsParam.CurrencyType.Blockchain(value.getBlockchain())
@@ -21,6 +22,6 @@ class ParamCardCurrencyConverter : Converter null
} ?: return null
- return AnalyticsParam.CardCurrency.SingleCurrency(type)
+ return CoreAnalyticsParam.WalletType.SingleCurrency(type.value)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt
index 6b8f903fb9..fd658029b7 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt
@@ -1,9 +1,9 @@
package com.tangem.tap.common.analytics.converters
import com.shopify.buy3.Storefront
-import com.tangem.common.Converter
import com.tangem.tap.common.analytics.events.Shop
import com.tangem.tap.features.shop.domain.models.ProductType
+import com.tangem.utils.converter.Converter
/**
[REDACTED_AUTHOR]
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/TopUpEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/TopUpEventConverter.kt
deleted file mode 100644
index ba62707b7f..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/converters/TopUpEventConverter.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.tangem.tap.common.analytics.converters
-
-import com.tangem.common.Converter
-import com.tangem.domain.common.CardTypesResolver
-import com.tangem.domain.wallets.models.UserWalletId
-import com.tangem.tap.common.analytics.events.Basic
-
-/**
-[REDACTED_AUTHOR]
- */
-class TopUpEventConverter : Converter, Basic.ToppedUp?> {
-
- override fun convert(value: Pair): Basic.ToppedUp? {
- val (userWalletId, resolver) = value
- val paramCardCurrency = ParamCardCurrencyConverter().convert(resolver) ?: return null
-
- return Basic.ToppedUp(userWalletId, paramCardCurrency)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt
index e3195c7e34..489effa20d 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt
@@ -6,42 +6,36 @@ import com.tangem.tap.features.details.redux.SecurityOption
sealed class AnalyticsParam {
sealed class CurrencyType(val value: String) {
- class Currency(currency: com.tangem.tap.features.wallet.models.Currency) : CurrencyType(currency.currencySymbol)
+ class Currency(currency: com.tangem.tap.domain.model.Currency) : CurrencyType(currency.currencySymbol)
class Blockchain(blockchain: com.tangem.blockchain.common.Blockchain) : CurrencyType(blockchain.currency)
class Token(token: com.tangem.blockchain.common.Token) : CurrencyType(token.symbol)
- class FiatCurrency(fiatCurrency: com.tangem.tap.common.entities.FiatCurrency) : CurrencyType(fiatCurrency.code)
class Amount(amount: com.tangem.blockchain.common.Amount) : CurrencyType(amount.currencySymbol)
}
- // MultiCurrency or CurrencyType
- sealed class CardCurrency(val value: String) {
- object MultiCurrency : CardCurrency(value = "Multicurrency")
- class SingleCurrency(type: CurrencyType) : CardCurrency(type.value)
- }
-
sealed class CardBalanceState(val value: String) {
object Empty : CardBalanceState("Empty")
object Full : CardBalanceState("Full")
- object CustomToken : CardBalanceState("Custom Token")
- object BlockchainError : CardBalanceState("Blockchain Error")
- object NoRate : CardBalanceState("No Rate")
companion object
}
sealed class RateApp(val value: String) {
object Liked : RateApp("Liked")
- object Disliked : RateApp("Disliked")
object Closed : RateApp("Close")
}
sealed class OnOffState(val value: String) {
+
object On : OnOffState("On")
object Off : OnOffState("Off")
+
+ companion object {
+
+ operator fun invoke(value: Boolean): OnOffState = if (value) On else Off
+ }
}
sealed class UserCode(val value: String) {
object AccessCode : UserCode("Access Code")
- object Passcode : UserCode("Passcode")
}
sealed class SecurityMode(val value: String) {
@@ -78,62 +72,6 @@ sealed class AnalyticsParam {
object BlockchainSdk : Error("Blockchain Sdk Error")
}
- sealed class ScannedFrom(val value: String) {
- object Introduction : ScannedFrom("Introduction")
- object Main : ScannedFrom("Main")
- object SignIn : ScannedFrom("Sign In")
- object MyWallets : ScannedFrom("My Wallets")
- }
-
- sealed class TxSentFrom(val value: String) {
- data class Send(
- override val blockchain: String,
- override val token: String,
- override val feeType: FeeType,
- ) : TxSentFrom("Send"), TxData
-
- data class Swap(
- override val blockchain: String,
- override val token: String,
- override val feeType: FeeType,
- ) : TxSentFrom("Swap"), TxData
-
- data class Approve(
- override val blockchain: String,
- override val token: String,
- override val feeType: FeeType,
- val permissionType: String,
- ) : TxSentFrom("Approve"), TxData
-
- object WalletConnect : TxSentFrom("WalletConnect")
- object Sell : TxSentFrom("Sell")
- }
-
- sealed interface TxData {
- val blockchain: String
- val token: String
- val feeType: FeeType
- }
-
- sealed class FeeType(val value: String) {
- object Fixed : FeeType("Fixed")
- object Min : FeeType("Min")
- object Normal : FeeType("Normal")
- object Max : FeeType("Max")
-
- companion object {
- fun fromString(feeType: String): FeeType {
- return when (feeType) {
- Min.value -> Min
- Normal.value -> Normal
- Max.value -> Max
- Fixed.value -> Fixed
- else -> Fixed
- }
- }
- }
- }
-
sealed class WalletCreationType(val value: String) {
object PrivateKey : WalletCreationType(value = "Private Key")
object NewSeed : WalletCreationType(value = "New Seed")
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt
index fbbc88c099..f97dca3a02 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt
@@ -12,23 +12,14 @@ sealed class MainScreen(
class ScreenOpened : MainScreen("Screen opened")
class ButtonScanCard : MainScreen("Button - Scan Card")
- class ButtonMyWallets : MainScreen("Button - My Wallets")
class EnableBiometrics(state: AnalyticsParam.OnOffState) : MainScreen(
event = "Enable Biometric",
params = mapOf("State" to state.value),
)
- class MainCurrencyChanged(currencyType: AnalyticsParam.CurrencyType) : MainScreen(
- event = "Main Currency Changed",
- params = mapOf("Currency Type" to currencyType.value),
- )
-
class NoticeRateAppButton(result: AnalyticsParam.RateApp) : MainScreen(
event = "Notice - Rate The App Button Tapped",
params = mapOf("Result" to result.value),
)
-
- class NoticeBackupYourWalletTapped : MainScreen("Notice - Backup Your Wallet Tapped")
- class NoticeScanYourCardTapped : MainScreen("Notice - Scan Your Card Tapped")
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt
deleted file mode 100644
index 87ba002047..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.tangem.tap.common.analytics.events
-
-import com.tangem.core.analytics.models.AnalyticsEvent
-
-sealed class MyWallets(
- event: String,
- params: Map = mapOf(),
-) : AnalyticsEvent("My Wallets", event, params) {
-
- class MyWalletsScreenOpened : MyWallets(event = "My Wallets Screen Opened")
-
- sealed class Button {
- class ScanNewCard : MyWallets(event = "Button - Scan New Card")
- class UnlockWithBiometrics : MyWallets(event = "Button - Unlock all with Face ID")
- class EditWalletTapped : MyWallets(event = "Button - Edit Wallet Tapped")
- class DeleteWalletTapped : MyWallets(event = "Button - Delete Wallet Tapped")
- class WalletUnlockTapped : MyWallets(event = "Button - Wallet Unlock Tapped")
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Portfolio.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Portfolio.kt
deleted file mode 100644
index 8270df641c..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Portfolio.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.tangem.tap.common.analytics.events
-
-import com.tangem.core.analytics.models.AnalyticsEvent
-
-/**
-[REDACTED_AUTHOR]
- */
-
-sealed class Portfolio(
- event: String,
- params: Map = mapOf(),
-) : AnalyticsEvent("Portfolio", event, params) {
-
- class Refreshed : Portfolio("Refreshed")
-
- class ButtonManageTokens : Portfolio("Button - Manage Tokens")
-
- class TokenTapped : Portfolio("Token is Tapped")
-
- class OrganizeTokens : Portfolio("Button - Organize Tokens")
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt
index b2123614eb..b9a831cb3d 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt
@@ -89,5 +89,12 @@ sealed class Settings(
event = "App Theme Switched",
params = mapOf("State" to theme.value),
)
+
+ object EnableBiometrics : AppSettings(event = "Notice - Enable Biometric")
+
+ class HideBalanceChanged(state: AnalyticsParam.OnOffState) : AppSettings(
+ event = "Hide Balance Changed",
+ params = mapOf("State" to state.value),
+ )
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt
index 9b8cecc417..3b5ae220eb 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt
@@ -1,7 +1,6 @@
package com.tangem.tap.common.analytics.events
import com.tangem.core.analytics.models.AnalyticsEvent
-import com.tangem.tap.common.analytics.events.AnalyticsParam.CurrencyType
/**
[REDACTED_AUTHOR]
@@ -13,50 +12,6 @@ sealed class Token(
error: Throwable? = null,
) : AnalyticsEvent(category, event, params, error) {
- class Refreshed : Token("Token", "Refreshed")
- class ButtonExplore : Token("Token", "Button - Explore")
-
- class ButtonRemoveToken(type: CurrencyType) : Token(
- "Token",
- "Button - Remove Token",
- params = mapOf("Token" to type.value),
- )
-
- class ButtonBuy(type: CurrencyType) : Token(
- category = "Token",
- event = "Button - Buy",
- params = mapOf("Token" to type.value),
- )
-
- class ButtonSell(type: CurrencyType) : Token(
- category = "Token",
- event = "Button - Sell",
- params = mapOf("Token" to type.value),
- )
-
- class ButtonExchange(type: CurrencyType) : Token(
- category = "Token",
- event = "Button - Exchange",
- params = mapOf("Token" to type.value),
- )
-
- class ButtonSend(type: CurrencyType) : Token(
- category = "Token",
- event = "Button - Send",
- params = mapOf("Token" to type.value),
- )
-
- class Bought(type: CurrencyType) : Token(
- category = "Token",
- event = "Token Bought",
- params = mapOf("Token" to type.value),
- )
-
- object ShowWalletAddress : Token(
- category = "Token",
- event = "Button - Show the Wallet Address",
- )
-
sealed class Receive(
event: String,
params: Map = mapOf(),
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt
index ddb27d18ff..74cec2eaf2 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt
@@ -3,8 +3,8 @@ package com.tangem.tap.common.analytics.handlers.amplitude
import android.app.Application
import com.amplitude.api.Amplitude
import com.amplitude.api.AmplitudeClient
-import com.tangem.common.Converter
import com.tangem.core.analytics.api.EventLogger
+import com.tangem.utils.converter.Converter
import org.json.JSONObject
/**
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt
index 33751b5e0a..20597e0fb9 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt
@@ -2,7 +2,6 @@ package com.tangem.tap.common.analytics.handlers.firebase
import android.os.Bundle
import androidx.core.os.bundleOf
-import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
@@ -29,8 +28,4 @@ internal class FirebaseClient : FirebaseAnalyticsClient {
}
private fun Map.toBundle(): Bundle = bundleOf(*this.toList().toTypedArray())
-
- companion object {
- const val ORDER_EVENT = FirebaseAnalytics.Event.PURCHASE
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt
index cf97ded034..6a963e544f 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt
@@ -48,6 +48,7 @@ class CardContextInterceptor(
ProductType.Wallet2 -> "Wallet 2.0"
ProductType.Ring -> "Ring"
ProductType.Start2Coin -> "Start2Coin"
+ ProductType.Visa -> "VISA"
else -> if (DemoHelper.isDemoCard(scanResponse)) {
if (DemoHelper.isTestDemoCard(scanResponse)) {
"Demo Test"
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/topup/TopUpController.kt b/app/src/main/java/com/tangem/tap/common/analytics/topup/TopUpController.kt
deleted file mode 100644
index 376143ec6b..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/topup/TopUpController.kt
+++ /dev/null
@@ -1,207 +0,0 @@
-package com.tangem.tap.common.analytics.topup
-
-import com.tangem.common.extensions.guard
-import com.tangem.common.extensions.isZero
-import com.tangem.core.analytics.Analytics
-import com.tangem.data.source.preferences.model.DataSourceTopupInfo
-import com.tangem.data.source.preferences.storage.ToppedUpWalletStorage
-import com.tangem.domain.common.BlockchainNetwork
-import com.tangem.domain.common.CardTypesResolver
-import com.tangem.domain.common.util.cardTypesResolver
-import com.tangem.domain.models.scan.ScanResponse
-import com.tangem.domain.userwallets.UserWalletIdBuilder
-import com.tangem.domain.wallets.models.UserWallet
-import com.tangem.domain.wallets.models.UserWalletId
-import com.tangem.tap.common.analytics.converters.TopUpEventConverter
-import com.tangem.tap.common.analytics.events.AnalyticsParam
-import com.tangem.tap.domain.model.TotalFiatBalance
-import com.tangem.tap.domain.model.WalletDataModel
-import com.tangem.tap.domain.model.WalletStoreModel
-import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
-import com.tangem.tap.domain.walletStores.WalletStoresManager
-import com.tangem.tap.features.wallet.models.Currency
-import com.tangem.tap.scope
-import com.tangem.utils.extensions.copy
-import kotlinx.coroutines.launch
-import java.math.BigDecimal
-
-/**
-[REDACTED_AUTHOR]
- */
-class TopUpController(
- var scanResponseProvider: (() -> ScanResponse?)? = null,
- var walletStoresManagerProvider: (() -> WalletStoresManager)? = null,
- private val topupWalletStorage: ToppedUpWalletStorage,
-) : WalletCurrenciesManager.Listener {
-
- private var hadMissedDerivations: Boolean = false
- private val addedCurrencies = mutableListOf()
-
- override fun didUpdate(userWallet: UserWallet, currency: Currency) {
- tryToSend()
- }
-
- override fun willCurrenciesAdd(userWallet: UserWallet, currenciesToAdd: List) {
- addedCurrencies.addAll(currenciesToAdd.distinct())
- }
-
- fun walletStoresChanged(walletStores: List) {
- val missedDerivations = walletStores
- .flatMap { it.walletsData }
- .map { it.status }
- .filterIsInstance()
-
- hadMissedDerivations = missedDerivations.isNotEmpty()
- }
-
- fun scanToGetDerivations() {
- hadMissedDerivations = true
- }
-
- fun addMissingDerivations(blockchains: List) {
- hadMissedDerivations = blockchains.isNotEmpty()
- }
-
- fun totalBalanceStateChanged(totalFiatBalance: TotalFiatBalance) {
- if (totalFiatBalance is TotalFiatBalance.Loaded) tryToSend()
- }
-
- fun loadDataSuccess() {
- tryToSend()
- }
-
- private fun tryToSend() {
- if (hadMissedDerivations) return
- val scanResponse = scanResponseProvider?.invoke() ?: return
- val userWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build() ?: return
- val walletStoresManager = walletStoresManagerProvider?.invoke() ?: return
-
- scope.launch {
- val walletDataModels = walletStoresManager.getSync(userWalletId).flatMap { it.walletsData }
- if (walletDataModels.isEmpty()) return@launch
-
- val isCorrectStatus = walletDataModels.any {
- it.status is WalletDataModel.Loading ||
- it.status is WalletDataModel.NoAccount ||
- it.status is WalletDataModel.Unreachable ||
- it.status is WalletDataModel.MissedDerivation ||
- it.status.isErrorStatus
- }
- if (isCorrectStatus) return@launch
-
- val isToppedUpInPast = findToppedUpCurrenciesInPast(walletDataModels).isNotEmpty()
- if (isToppedUpInPast) {
- val newWalletInfo = DataSourceTopupInfo(
- walletId = userWalletId.stringValue,
- cardBalanceState = DataSourceTopupInfo.CardBalanceState.Full,
- )
- topupWalletStorage.save(newWalletInfo)
- return@launch
- }
-
- val cardBalanceState = BalanceCalculator(walletDataModels).calculate().toCardBalanceState()
- send(userWalletId, cardBalanceState, scanResponse.cardTypesResolver)
- }
- }
-
- /**
- * A UserWalletId registration should be after creating wallets
- */
- fun registerEmptyWallet(scanResponse: ScanResponse) {
- UserWalletIdBuilder.scanResponse(scanResponse).build()?.let {
- topupWalletStorage.save(
- DataSourceTopupInfo(
- walletId = it.stringValue,
- cardBalanceState = DataSourceTopupInfo.CardBalanceState.Empty,
- ),
- )
- }
- }
-
- fun send(scanResponse: ScanResponse, cardBalanceState: AnalyticsParam.CardBalanceState) {
- UserWalletIdBuilder.scanResponse(scanResponse).build()?.let {
- send(it, cardBalanceState, scanResponse.cardTypesResolver)
- }
- }
-
- fun send(
- userWalletId: UserWalletId,
- cardBalanceState: AnalyticsParam.CardBalanceState,
- cardTypesResolver: CardTypesResolver,
- ) {
- val topupInfo = topupWalletStorage.restore(userWalletId.stringValue).guard {
- val topupInfo = DataSourceTopupInfo(
- walletId = userWalletId.stringValue,
- cardBalanceState = when (cardBalanceState) {
- AnalyticsParam.CardBalanceState.BlockchainError ->
- DataSourceTopupInfo.CardBalanceState.BlockchainError
- AnalyticsParam.CardBalanceState.CustomToken ->
- DataSourceTopupInfo.CardBalanceState.CustomToken
- AnalyticsParam.CardBalanceState.Empty ->
- DataSourceTopupInfo.CardBalanceState.Empty
- AnalyticsParam.CardBalanceState.Full ->
- DataSourceTopupInfo.CardBalanceState.Full
- AnalyticsParam.CardBalanceState.NoRate ->
- DataSourceTopupInfo.CardBalanceState.NoRate
- },
- )
- topupWalletStorage.save(topupInfo)
- return
- }
-
- val isToppedUp = topupInfo.cardBalanceState == DataSourceTopupInfo.CardBalanceState.Full
- if (isToppedUp) return
-
- if (cardBalanceState.isToppedUp()) {
- topupWalletStorage.save(topupInfo.copy(cardBalanceState = DataSourceTopupInfo.CardBalanceState.Full))
- TopUpEventConverter().convert(value = userWalletId to cardTypesResolver)?.let {
- Analytics.send(it)
- }
- }
- }
-
- private fun findToppedUpCurrenciesInPast(walletDataModels: List): List {
- val currenciesToppedUpInPast = addedCurrencies.copy()
- .mapNotNull { currency ->
- val foundCurrencyModel = walletDataModels
- .find { it.currency == currency }
- ?: return@mapNotNull null
-
- if (foundCurrencyModel.status.amount.isZero()) null else foundCurrencyModel
- }
- addedCurrencies.clear()
-
- return currenciesToppedUpInPast
- }
-
- private fun BigDecimal.toCardBalanceState(): AnalyticsParam.CardBalanceState = when {
- isZero() -> AnalyticsParam.CardBalanceState.Empty
- else -> AnalyticsParam.CardBalanceState.Full
- }
-
- private fun AnalyticsParam.CardBalanceState.isToppedUp(): Boolean = this == AnalyticsParam.CardBalanceState.Full
-}
-
-private interface IBalanceCalculator {
- fun calculate(): BigDecimal
-}
-
-private class BalanceCalculator(
- private val walletDataModels: List,
-) : IBalanceCalculator {
-
- override fun calculate(): BigDecimal {
- val singleToken = walletDataModels
- .filter { it.currency.isToken() }
- .firstOrNull { it.isCardSingleToken }
-
- val totalAmount = singleToken?.status?.amount
- ?: walletDataModels.calculateTotalCryptoAmount()
-
- return totalAmount
- }
-
- private fun List.calculateTotalCryptoAmount(): BigDecimal = this
- .map { it.status.amount }
- .reduce(BigDecimal::plus)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/AutoSizeText.kt b/app/src/main/java/com/tangem/tap/common/compose/AutoSizeText.kt
deleted file mode 100644
index 63d98b6269..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/AutoSizeText.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.material.LocalTextStyle
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawWithContent
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.unit.TextUnit
-import androidx.compose.ui.unit.sp
-
-@Suppress("MagicNumber")
-@Composable
-fun TextAutoSize(
- text: String,
- fontSizeRange: FontSizeRange,
- modifier: Modifier = Modifier,
- textStyle: TextStyle = LocalTextStyle.current,
-) {
- val fontSizeValue = remember { mutableStateOf(fontSizeRange.max.value) }
- val readyToDraw = remember { mutableStateOf(false) }
-
- val textState = remember { mutableStateOf(text) }
- if (textState.value != text) {
- readyToDraw.value = false
- fontSizeValue.value = fontSizeRange.max.value
- textState.value = text
- }
-
- Text(
- modifier = modifier.drawWithContent { if (readyToDraw.value) drawContent() },
- text = text,
- softWrap = false,
- style = textStyle,
- fontSize = fontSizeValue.value.sp,
- onTextLayout = {
- if (it.hasVisualOverflow) {
- val nextFontSizeValue = fontSizeValue.value - fontSizeRange.step.value
- if (nextFontSizeValue <= fontSizeRange.min.value) {
- fontSizeValue.value = fontSizeRange.min.value
- readyToDraw.value = true
- } else {
- fontSizeValue.value = nextFontSizeValue * 0.8f
- }
- } else {
- readyToDraw.value = true
- }
- },
- )
-}
-
-data class FontSizeRange(
- val min: TextUnit,
- val max: TextUnit,
- val step: TextUnit = DEFAULT_TEXT_STEP,
-) {
- init {
- require(min < max) { "min should be less than max, $this" }
- require(step.value > 0) { "step should be greater than 0, $this" }
- }
-
- companion object {
- private val DEFAULT_TEXT_STEP = 1.sp
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/Button.kt b/app/src/main/java/com/tangem/tap/common/compose/Button.kt
deleted file mode 100644
index ee94c8b15b..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/Button.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.material.ripple.LocalRippleTheme
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-
-/**
- * Used for disable ripple if button is enable = false
- */
-@Composable
-fun ToggledRippleTheme(isEnabled: Boolean, content: @Composable () -> Unit) {
- val theme = LocalRippleTheme provides if (isEnabled) LocalRippleTheme.current else NoRippleTheme()
- CompositionLocalProvider(theme) { content() }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/ComposableValueDebouncer.kt b/app/src/main/java/com/tangem/tap/common/compose/ComposableValueDebouncer.kt
deleted file mode 100644
index 44395f9279..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/ComposableValueDebouncer.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import com.tangem.domain.common.util.ValueDebouncer
-
-/**
-[REDACTED_AUTHOR]
- * This is an empty compose view. It just remember the ValueDebouncer inside of itself.
- */
-@Composable
-fun valueDebouncerAsState(
- initialValue: T,
- onValueChange: (T) -> Unit,
- debounce: Long = 600,
- onEmitValueReceive: (T) -> Unit = {},
-): ValueDebouncer {
- return remember {
- ValueDebouncer(
- initialValue = initialValue,
- debounceDuration = debounce,
- onEmitValueReceived = { emitValue ->
- emitValue?.let { onEmitValueReceive(it) }
- },
- onValueChanged = { changedValue ->
- changedValue?.let { onValueChange(it) }
- },
- )
- }
-}
-
-@Composable
-fun valueDebouncerNullableAsState(
- initialValue: T?,
- onValueChange: (T?) -> Unit,
- debounce: Long = 400,
- onEmitValueReceive: (T?) -> Unit = {},
-): ValueDebouncer {
- return remember {
- ValueDebouncer(
- initialValue = initialValue,
- debounceDuration = debounce,
- onEmitValueReceived = onEmitValueReceive,
- onValueChanged = onValueChange,
- )
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/ErrorViews.kt b/app/src/main/java/com/tangem/tap/common/compose/ErrorViews.kt
deleted file mode 100644
index 90928c9d15..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/ErrorViews.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material.LocalTextStyle
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-
-/**
-[REDACTED_AUTHOR]
- */
-@Composable
-fun ErrorView(text: String, modifier: Modifier = Modifier, style: TextStyle = LocalTextStyle.current) {
- Text(
- text,
- color = MaterialTheme.colors.error,
- modifier = modifier,
- style = style,
- )
-}
-
-@Preview
-@Composable
-private fun ErrorViewTest() {
- Box(Modifier.padding(16.dp)) {
- ErrorView(text = "Some error description")
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/NoRippleTheme.kt b/app/src/main/java/com/tangem/tap/common/compose/NoRippleTheme.kt
deleted file mode 100644
index f0afe076ba..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/NoRippleTheme.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.material.ripple.RippleAlpha
-import androidx.compose.material.ripple.RippleTheme
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.graphics.Color
-
-/**
-[REDACTED_AUTHOR]
- */
-class NoRippleTheme : RippleTheme {
- @Composable
- override fun defaultColor() = Color.Unspecified
-
- @Composable
- override fun rippleAlpha(): RippleAlpha = RippleAlpha(0.0f, 0.0f, 0.0f, 0.0f)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/PinCodeWidget.kt b/app/src/main/java/com/tangem/tap/common/compose/PinCodeWidget.kt
deleted file mode 100644
index 41e5637ba1..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/PinCodeWidget.kt
+++ /dev/null
@@ -1,165 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.foundation.background
-import androidx.compose.foundation.gestures.detectTapGestures
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.wrapContentSize
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.foundation.text.KeyboardActions
-import androidx.compose.foundation.text.KeyboardOptions
-import androidx.compose.material.LocalTextStyle
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Surface
-import androidx.compose.material.Text
-import androidx.compose.material.TextField
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.ExperimentalComposeUiApi
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.alpha
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.focus.FocusRequester
-import androidx.compose.ui.focus.focusRequester
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.platform.LocalSoftwareKeyboardController
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.input.ImeAction
-import androidx.compose.ui.text.input.KeyboardType
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-import androidx.core.text.isDigitsOnly
-
-/**
-[REDACTED_AUTHOR]
- */
-@OptIn(ExperimentalComposeUiApi::class)
-@Composable
-fun PinCodeWidget(
- config: PinViewConfig = tangemPinConfig,
- onPinChange: (String, Boolean) -> Unit = { pin, isLastSymbolEntered -> },
-) {
- val focusRequester = remember { FocusRequester() }
- val keyboardController = LocalSoftwareKeyboardController.current
-
- val rTextFieldValue = remember { mutableStateOf(TextFieldValue("")) }
- val indexedSymbols: List = createPinSymbolsList(config.pinsCount, rTextFieldValue.value.text)
-
- fun isLastSymbolEntered(): Boolean = rTextFieldValue.value.text.length == config.pinsCount
-
- fun handleOnTextFieldValueChanged(value: TextFieldValue) {
- if (!value.text.isDigitsOnly()) return
-
- if (value.text.length <= config.pinsCount) {
- rTextFieldValue.value = value
- onPinChange(value.text, isLastSymbolEntered())
- }
- }
-
- Box(
- modifier = config.modifier
- .pointerInput(Unit) {
- detectTapGestures {
- focusRequester.requestFocus()
- keyboardController?.show()
- }
- },
- ) {
- Row {
- for (index in 0 until config.pinsCount) {
- PinElement(
- config = config,
- pinSymbol = indexedSymbols[index] ?: "",
- )
- }
- }
- TextField(
- modifier = Modifier
- .alpha(0f)
- .size(1.dp)
- .align(Alignment.Center)
- .focusRequester(focusRequester),
- keyboardOptions = KeyboardOptions(
- keyboardType = KeyboardType.Decimal,
- imeAction = if (isLastSymbolEntered()) ImeAction.Done else ImeAction.Next,
- ),
- keyboardActions = KeyboardActions(
- onDone = { keyboardController?.hide() },
- ),
- value = rTextFieldValue.value,
- onValueChange = ::handleOnTextFieldValueChanged,
- )
- }
-
- LaunchedEffect(Unit) {
- focusRequester.requestFocus()
- }
-}
-
-@Composable
-private fun PinElement(config: PinViewConfig, pinSymbol: String) {
- Box(Modifier.padding(config.pinBoxPadding)) {
- Box(config.pinBoxModifier) {
- Text(
- text = pinSymbol,
- modifier = config.pinTextModifier.align(Alignment.Center),
- style = config.pinsTextStyle ?: LocalTextStyle.current,
- )
- }
- }
-}
-
-private fun createPinSymbolsList(size: Int, text: String): List = List(size) {
- try {
- text[it].toString()
- } catch (ex: IndexOutOfBoundsException) {
- null
- }
-}
-
-data class PinViewConfig(
- val modifier: Modifier = Modifier,
- val pinBoxModifier: Modifier = Modifier,
- val pinBoxPadding: Dp = 0.dp,
- val pinTextModifier: Modifier = Modifier,
- val pinsCount: Int = 4,
- val pinsTextStyle: TextStyle? = null,
-)
-
-private val tangemPinConfig = PinViewConfig(
- modifier = Modifier
- .wrapContentSize(),
- pinBoxModifier = Modifier
- .width(42.dp)
- .height(56.dp)
- .clip(RoundedCornerShape(8.dp))
- .background(Color(0xFFF0F0F0)),
- pinBoxPadding = 6.dp,
- pinTextModifier = Modifier,
- pinsCount = 4,
- pinsTextStyle = TextStyle(
- fontWeight = FontWeight(500),
- fontSize = 24.sp,
- ),
-)
-
-@Preview
-@Composable
-private fun PinCodeWidgetPreview() {
- Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
- PinCodeWidget(tangemPinConfig)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/Warning.kt b/app/src/main/java/com/tangem/tap/common/compose/Warning.kt
deleted file mode 100644
index 6d4a79d192..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/Warning.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Surface
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.colorResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-import com.tangem.common.module.ModuleMessage
-import com.tangem.core.ui.components.SpacerH8
-import com.tangem.tap.domain.moduleMessage.ModuleMessageConverter
-import com.tangem.wallet.R
-
-/**
-[REDACTED_AUTHOR]
- */
-@Composable
-fun AddCustomTokenWarning(warning: ModuleMessage, converter: ModuleMessageConverter, modifier: Modifier = Modifier) {
- Surface(
- modifier = modifier,
- shape = MaterialTheme.shapes.small,
- color = colorResource(id = R.color.warning_warning),
- elevation = 4.dp,
- ) {
- Column(
- modifier = Modifier.padding(16.dp),
- ) {
- Text(
- text = stringResource(id = R.string.common_warning),
- color = colorResource(id = R.color.white),
- fontSize = 14.sp,
- fontWeight = FontWeight.Bold,
- )
- SpacerH8()
- Text(
- text = converter.convert(warning).message,
- color = colorResource(id = R.color.white),
- fontSize = 13.sp,
- lineHeight = 18.sp,
- )
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/Context.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/Context.kt
deleted file mode 100644
index 719c80d0d4..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/Context.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.tangem.tap.common.compose.extensions
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.platform.LocalContext
-import com.tangem.tap.common.extensions.copyToClipboard
-import com.tangem.tap.common.extensions.getFromClipboard
-
-/**
-[REDACTED_AUTHOR]
- */
-@Suppress("ComposableFunctionName")
-@Composable
-fun copyToClipboard(value: Any, label: String = "") {
- LocalContext.current.copyToClipboard(value, label)
-}
-
-@Suppress("ComposableFunctionName")
-@Composable
-fun getFromClipboard(default: CharSequence? = null): CharSequence? {
- return LocalContext.current.getFromClipboard(default)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/Dp.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/Dp.kt
index 42acdcf306..04240d7b55 100644
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/Dp.kt
+++ b/app/src/main/java/com/tangem/tap/common/compose/extensions/Dp.kt
@@ -14,6 +14,4 @@ fun Dp.toPx(): Float {
return with(LocalDensity.current) { currentDp.toPx() }
}
-fun DpSize.halfWidth(): Dp = this.width / 2
-
fun DpSize.halfHeight(): Dp = this.height / 2
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/LazyListState.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/LazyListState.kt
deleted file mode 100644
index dab9b8f654..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/LazyListState.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.tangem.tap.common.compose.extensions
-
-import androidx.compose.foundation.lazy.LazyListState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.derivedStateOf
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalView
-import com.tangem.tap.common.extensions.hideKeyboard
-
-@Composable
-fun LazyListState.OnBottomReached(loadMoreThreshold: Int, onLoadMore: () -> Unit) {
- require(loadMoreThreshold >= 0)
- val shouldLoadMore by remember {
- derivedStateOf {
- val lastVisibleItem = layoutInfo.visibleItemsInfo.lastOrNull()
- ?: return@derivedStateOf false
- lastVisibleItem.index >= layoutInfo.totalItemsCount - 1 - loadMoreThreshold
- }
- }
-
- LaunchedEffect(shouldLoadMore) {
- if (shouldLoadMore) onLoadMore()
- }
-}
-
-@Composable
-fun LazyListState.HideKeyboardOnScroll() {
- if (isScrollInProgress) {
- LocalView.current.hideKeyboard()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/MutableState.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/MutableState.kt
deleted file mode 100644
index 459086b9c3..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/MutableState.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.tangem.tap.common.compose.extensions
-
-import androidx.compose.runtime.MutableState
-
-/**
-[REDACTED_AUTHOR]
- */
-fun MutableState>.addAndNotify(value: T) {
- this.value = this.value.toMutableList().apply { add(value) }
-}
-
-fun MutableState>.removeAndNotify(value: T) {
- this.value = this.value.toMutableList().apply { remove(value) }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/Painter.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/Painter.kt
index 32c3110ba5..dfabb2cddf 100644
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/Painter.kt
+++ b/app/src/main/java/com/tangem/tap/common/compose/extensions/Painter.kt
@@ -5,7 +5,6 @@ import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
-import com.tangem.sdk.extensions.dpToPx
import com.tangem.sdk.extensions.pxToDp
/**
@@ -17,8 +16,5 @@ fun Painter.dpSize(): DpSize = DpSize(
intrinsicSize.height.pxToDp().dp,
)
-@Composable
-private fun Float.dpToPx(): Float = LocalContext.current.dpToPx(this)
-
@Composable
private fun Float.pxToDp(): Float = LocalContext.current.pxToDp(this)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/entities/Button.kt b/app/src/main/java/com/tangem/tap/common/entities/Button.kt
index b873b7ef3e..b0aca7f994 100644
--- a/app/src/main/java/com/tangem/tap/common/entities/Button.kt
+++ b/app/src/main/java/com/tangem/tap/common/entities/Button.kt
@@ -1,7 +1,6 @@
package com.tangem.tap.common.entities
import com.tangem.tap.features.send.redux.states.ButtonState
-import com.tangem.tap.features.wallet.redux.ProgressState
open class Button(val enabled: Boolean)
diff --git a/app/src/main/java/com/tangem/tap/common/entities/FiatCurrency.kt b/app/src/main/java/com/tangem/tap/common/entities/FiatCurrency.kt
deleted file mode 100644
index c0df80eb2a..0000000000
--- a/app/src/main/java/com/tangem/tap/common/entities/FiatCurrency.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.tangem.tap.common.entities
-
-data class FiatCurrency(
- val code: String,
- val name: String,
- val symbol: String,
-) {
- val displayName: String
- get() = "${this.name} (${this.code}) - ${this.symbol}"
-
- companion object {
- val Default = FiatCurrency(
- symbol = "$",
- code = "USD",
- name = "US Dollar",
- )
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/entities/ProgressState.kt b/app/src/main/java/com/tangem/tap/common/entities/ProgressState.kt
new file mode 100644
index 0000000000..61adc5cd45
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/entities/ProgressState.kt
@@ -0,0 +1,5 @@
+package com.tangem.tap.common.entities
+
+import com.tangem.tap.common.toggleWidget.WidgetState
+
+enum class ProgressState : WidgetState { Loading, Done, Error }
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/AssetManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/AssetManager.kt
deleted file mode 100644
index 9130b6c91d..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/AssetManager.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.content.res.AssetManager
-
-fun AssetManager.readJsonFileToString(fileName: String): String =
- this.open("$fileName.json").bufferedReader().readText()
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Bitmap.kt b/app/src/main/java/com/tangem/tap/common/extensions/Bitmap.kt
index 80e756c21c..76eea0c892 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Bitmap.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Bitmap.kt
@@ -1,7 +1,6 @@
package com.tangem.tap.common.extensions
import android.graphics.Bitmap
-import android.graphics.BitmapFactory
import java.io.ByteArrayOutputStream
@Suppress("MagicNumber")
@@ -9,9 +8,4 @@ fun Bitmap.toByteArray(): ByteArray {
val stream = ByteArrayOutputStream()
this.compress(Bitmap.CompressFormat.JPEG, 20, stream)
return stream.toByteArray()
-}
-
-@Suppress("MagicNumber")
-fun ByteArray.toBitmap(): Bitmap {
- return BitmapFactory.decodeByteArray(this, 0, this.size)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Context.kt b/app/src/main/java/com/tangem/tap/common/extensions/Context.kt
index 8cdf3302b7..14f4cd0dbf 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Context.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Context.kt
@@ -7,10 +7,6 @@ import android.net.*
import androidx.annotation.*
import androidx.core.content.*
-fun Context.isPermissionGranted(permission: String): Boolean {
- return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
-}
-
/**
* Get uri to any resource type via given Resource Instance
* @param resId - resource id
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/ImageRequest.kt b/app/src/main/java/com/tangem/tap/common/extensions/ImageRequest.kt
deleted file mode 100644
index 2eb87310f9..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/ImageRequest.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import coil.request.ImageRequest
-
-/**
-[REDACTED_AUTHOR]
- */
-fun ImageRequest.Builder.cardImageData(any: Any?): ImageRequest.Builder = apply {
- data(any)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/ImageView.kt b/app/src/main/java/com/tangem/tap/common/extensions/ImageView.kt
deleted file mode 100644
index 0c3a471d54..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/ImageView.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.widget.ImageView
-import androidx.annotation.DrawableRes
-
-/**
-[REDACTED_AUTHOR]
- */
-fun ImageView.setDrawable(@DrawableRes resId: Int) {
- setImageDrawable(context.getDrawableCompat(resId))
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt
index 51ac9818c4..df5762ec97 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt
@@ -14,7 +14,6 @@ import com.tangem.tap.features.details.ui.cardsettings.coderecovery.AccessCodeRe
import com.tangem.tap.features.details.ui.details.DetailsFragment
import com.tangem.tap.features.details.ui.resetcard.ResetCardFragment
import com.tangem.tap.features.details.ui.securitymode.SecurityModeFragment
-import com.tangem.tap.features.details.ui.walletconnect.QrScanFragment
import com.tangem.tap.features.details.ui.walletconnect.WalletConnectFragment
import com.tangem.tap.features.disclaimer.ui.DisclaimerFragment
import com.tangem.tap.features.home.HomeFragment
@@ -27,9 +26,6 @@ import com.tangem.tap.features.saveWallet.ui.SaveWalletBottomSheetFragment
import com.tangem.tap.features.send.ui.SendFragment
import com.tangem.tap.features.shop.ui.ShopFragment
import com.tangem.tap.features.tokens.impl.presentation.TokensListFragment
-import com.tangem.tap.features.wallet.ui.WalletDetailsFragment
-import com.tangem.tap.features.wallet.ui.WalletFragment
-import com.tangem.tap.features.walletSelector.ui.WalletSelectorBottomSheetFragment
import com.tangem.tap.features.welcome.ui.WelcomeFragment
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.store
@@ -132,16 +128,9 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
AppScreen.OnboardingTwins -> TwinsCardsFragment()
AppScreen.OnboardingOther -> OnboardingOtherCardsFragment()
AppScreen.Wallet -> {
- val featureToggles = store.state.daggerGraphState.get(
- getDependency = DaggerGraphState::walletFeatureToggles,
- )
- if (featureToggles.isRedesignedScreenEnabled) {
- store.state.daggerGraphState
- .get(getDependency = DaggerGraphState::walletRouter)
- .getEntryFragment()
- } else {
- WalletFragment()
- }
+ store.state.daggerGraphState
+ .get(getDependency = DaggerGraphState::walletRouter)
+ .getEntryFragment()
}
AppScreen.Send -> {
val featureToggles = store.state.daggerGraphState.get(
@@ -176,24 +165,20 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
}
AppScreen.AddCustomToken -> AddCustomTokenFragment()
AppScreen.WalletDetails -> {
- val featureToggles = store.state.daggerGraphState.get(
- getDependency = DaggerGraphState::walletFeatureToggles,
- )
- if (featureToggles.isRedesignedScreenEnabled) {
- store.state.daggerGraphState
- .get(getDependency = DaggerGraphState::tokenDetailsRouter)
- .getEntryFragment()
- } else {
- WalletDetailsFragment()
- }
+ store.state.daggerGraphState
+ .get(getDependency = DaggerGraphState::tokenDetailsRouter)
+ .getEntryFragment()
}
AppScreen.WalletConnectSessions -> WalletConnectFragment()
- AppScreen.QrScan -> QrScanFragment()
+ AppScreen.QrScanning -> {
+ store.state.daggerGraphState
+ .get(getDependency = DaggerGraphState::qrScanningRouter)
+ .getEntryFragment()
+ }
AppScreen.ReferralProgram -> ReferralFragment()
AppScreen.Swap -> SwapFragment()
AppScreen.Welcome -> WelcomeFragment()
AppScreen.SaveWallet -> SaveWalletBottomSheetFragment()
- AppScreen.WalletSelector -> WalletSelectorBottomSheetFragment()
AppScreen.AppCurrencySelector -> AppCurrencySelectorFragment()
AppScreen.ModalNotification -> ModalNotificationBottomSheetFragment()
}
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt
index 5f259977e0..a2206cb3bc 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt
@@ -1,17 +1,11 @@
package com.tangem.tap.common.extensions
-import android.text.Spanned
-import android.text.SpannedString
-import android.text.style.RelativeSizeSpan
-import androidx.core.text.buildSpannedString
import com.tangem.common.extensions.isZero
-import timber.log.Timber
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
-import java.text.NumberFormat
-import java.util.*
+import java.util.Locale
// TODO: move extensions to utils
fun BigDecimal.toFormattedString(
@@ -29,105 +23,6 @@ fun BigDecimal.toFormattedString(
return df.format(this)
}
-/**
- * To formatted crypto currency string
- * Specific method because there is no crypto currency codes in Locale
- */
-@Suppress("MagicNumber")
-fun BigDecimal.toFormattedCryptoCurrencyString(
- decimals: Int,
- currency: String,
- roundingMode: RoundingMode = RoundingMode.DOWN,
- limitNumberOfDecimals: Boolean = true,
-): String {
- val decimalsForRounding = if (limitNumberOfDecimals) {
- if (decimals > 8) 8 else decimals
- } else {
- decimals
- }
- try {
- val locale = Locale.getDefault()
- val formatter = NumberFormat.getCurrencyInstance(locale)
- // first create currency instance for "USD" with Locale default to replace currency to crypto later
- Currency.getInstance("USD")?.let { currencyTmp ->
- formatter.currency = currencyTmp
- formatter.maximumFractionDigits = decimalsForRounding
- formatter.minimumFractionDigits = 0
- formatter.isGroupingUsed = true
- formatter.roundingMode = roundingMode
- // cause formatter created for USD, replace Currency with Crypto symbol on right by Locale place
- return formatter.format(this).replace(currencyTmp.getSymbol(locale), "$currency ")
- }
- } catch (e: IllegalArgumentException) {
- Timber.e(e, "can't parse currency")
- }
- // if something went wrong - use old way to format
- val formattedAmount = this.toFormattedString(
- decimals = decimalsForRounding,
- roundingMode = roundingMode,
- locale = Locale.getDefault(),
- )
- return "$formattedAmount $currency "
-}
-
-fun BigDecimal.toFiatRateString(fiatCurrencyName: String, fiatCode: String): String {
- try {
- val formatter = NumberFormat.getCurrencyInstance(Locale.getDefault())
- Currency.getInstance(fiatCode)?.let { currency ->
- formatter.currency = currency
- formatter.maximumFractionDigits = 2
- formatter.roundingMode = RoundingMode.HALF_UP
- return formatter.format(this).replace(currency.symbol, "$fiatCurrencyName ")
- }
- } catch (e: IllegalArgumentException) {
- Timber.e(e, "can't parse currency")
- }
- val value = this
- .setScale(2, RoundingMode.HALF_UP)
- .formatWithSpaces()
- return "$value $fiatCurrencyName"
-}
-
-fun BigDecimal.toFiatString(
- rateValue: BigDecimal,
- fiatCurrencyName: String,
- fiatCode: String,
- formatWithSpaces: Boolean = false,
-): String {
- val fiatValue = rateValue.multiply(this)
- return fiatValue.toFormattedFiatValue(
- fiatCurrencyName = fiatCurrencyName,
- fiatCode = fiatCode,
- formatWithSpaces = formatWithSpaces,
- )
-}
-
-fun BigDecimal.toFiatValue(rateValue: BigDecimal): BigDecimal {
- val fiatValue = rateValue.multiply(this)
- return fiatValue.setScale(2, RoundingMode.HALF_UP)
-}
-
-fun BigDecimal.toFormattedFiatValue(
- fiatCurrencyName: String,
- fiatCode: String,
- formatWithSpaces: Boolean = false,
-): String {
- try {
- val formatter = NumberFormat.getCurrencyInstance(Locale.getDefault())
- Currency.getInstance(fiatCode)?.let { currency ->
- formatter.currency = currency
- formatter.maximumFractionDigits = 2
- formatter.roundingMode = RoundingMode.HALF_UP
- return formatter.format(this).replace(currency.symbol, "$fiatCurrencyName ")
- }
- } catch (e: IllegalArgumentException) {
- Timber.e(e, "can't parse currency")
- }
- val fiatValue = this.setScale(2, RoundingMode.HALF_UP)
- .let { if (formatWithSpaces) it.formatWithSpaces() else it }
- return " $fiatValue $fiatCurrencyName"
-}
-
fun BigDecimal.stripZeroPlainString(): String = this.stripTrailingZeros().toPlainString()
// 0.00 -> 0.00
@@ -146,70 +41,4 @@ fun BigDecimal.setPrecision(precision: Int, roundingMode: RoundingMode = Roundin
return this.setScale(scale() - precision() + precision, roundingMode)
}
-fun BigDecimal.isPositive(): Boolean = this.compareTo(BigDecimal.ZERO) == 1
-fun BigDecimal.isNegative(): Boolean = this.compareTo(BigDecimal.ZERO) == -1
-fun BigDecimal.isGreaterThan(value: BigDecimal): Boolean = this.compareTo(value) == 1
-fun BigDecimal.isLessThan(value: BigDecimal): Boolean = this.compareTo(value) == -1
-
-fun BigDecimal.isGreaterThanOrEqual(value: BigDecimal): Boolean {
- val compareResult = this.compareTo(value)
- return compareResult == 1 || compareResult == 0
-}
-
-fun BigDecimal.isLessThanOrEqual(value: BigDecimal): Boolean {
- val compareResult = this.compareTo(value)
- return compareResult == -1 || compareResult == 0
-}
-
-fun BigDecimal.formatAmountAsSpannedString(
- currencySymbol: String,
- reminderPartSizeProportion: Float = 0.7f,
-): SpannedString {
- val amount = this
- .setScale(2, RoundingMode.HALF_UP)
- .formatWithSpaces()
- val integer = amount.substringBefore('.')
- val reminder = amount.substringAfter('.')
-
- // test formatter log Log.e("TEST ", BigDecimal("1234567890987654321.1234567890987654321").formatWithSpaces())
-
- return buildSpannedString {
- append(integer)
- append('.')
- append(
- "$reminder $currencySymbol",
- RelativeSizeSpan(reminderPartSizeProportion),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,
- )
- }
-}
-
-@Suppress("MagicNumber")
-fun BigDecimal.formatWithSpaces(): String {
- val str = this.toString()
- var integerStr = str.substringBefore('.')
- val reminderStr = str.substringAfter('.')
- val packets = arrayListOf()
-
- var index: Int = integerStr.length
- while (0 < index) {
- if (index <= 3) {
- packets.add(integerStr)
- break
- }
- index -= 3
- packets.add(integerStr.substring(startIndex = index))
- integerStr = integerStr.substring(startIndex = 0, endIndex = index)
- }
-
- return buildString {
- packets.reversed().forEachIndexed { index, packet ->
- append(packet)
- if (index != packets.lastIndex) append(' ')
- }
- if (reminderStr.isNotBlank()) {
- append('.')
- append(reminderStr)
- }
- }
-}
\ No newline at end of file
+fun BigDecimal.isPositive(): Boolean = this.signum() == 1
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Store.kt b/app/src/main/java/com/tangem/tap/common/extensions/Store.kt
index bcd2445a5f..79c87a7f28 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Store.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Store.kt
@@ -42,16 +42,8 @@ fun Store<*>.dispatchNotification(resId: Int) {
dispatchOnMain(GlobalAction.ShowNotification(resId))
}
-suspend fun Store.onUserWalletSelected(
- userWallet: UserWallet,
- refresh: Boolean = false,
- sendAnalyticsEvent: Boolean = false,
-) {
- state.globalState.tapWalletManager.onWalletSelected(userWallet, refresh, sendAnalyticsEvent)
-}
-
-fun Store<*>.dispatchToastNotification(resId: Int) {
- dispatchOnMain(GlobalAction.ShowToastNotification(resId))
+suspend fun Store.onUserWalletSelected(userWallet: UserWallet, sendAnalyticsEvent: Boolean = false) {
+ state.globalState.tapWalletManager.onWalletSelected(userWallet, sendAnalyticsEvent)
}
fun Store<*>.dispatchErrorNotification(error: TapError) {
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/String.kt b/app/src/main/java/com/tangem/tap/common/extensions/String.kt
index 911bd470a1..448ae3e36a 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/String.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/String.kt
@@ -1,41 +1,12 @@
package com.tangem.tap.common.extensions
-import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
-import android.net.Uri
-import android.text.Spannable
-import android.text.style.ForegroundColorSpan
-import androidx.core.content.ContextCompat
-import androidx.core.text.toSpannable
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.qrcode.QRCodeWriter
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
-import java.util.*
-
-fun String?.ellipsizeBeforeSpace(allowedSize: Int): String {
- if (this.isNullOrBlank()) return ""
- val size = this.length
- val sizeDifference = size - allowedSize
- val endIndex = this.indexOf(" ")
- val startIndex = endIndex - sizeDifference
- val newString = this.removeRange(startIndex, endIndex)
- return newString.substring(0 until startIndex) + "..." +
- newString.substring(startIndex until newString.length)
-}
-
-fun String.colorSegment(context: Context, color: Int, startIndex: Int = 0, endIndex: Int = this.length): Spannable {
- return this.toSpannable()
- .also { spannable ->
- spannable.setSpan(
- ForegroundColorSpan(ContextCompat.getColor(context, color)),
- startIndex,
- endIndex,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE,
- )
- }
-}
+import java.util.Hashtable
@Suppress("MagicNumber")
fun String.toQrCode(): Bitmap {
@@ -58,8 +29,6 @@ fun String.toQrCode(): Bitmap {
return bmp
}
-fun String.urlEncode(): String = Uri.encode(this)
-
fun String.removePrefixOrNull(prefix: String): String? = when {
startsWith(prefix) -> substring(prefix.length)
else -> null
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/StringBuilder.kt b/app/src/main/java/com/tangem/tap/common/extensions/StringBuilder.kt
index 961e77e8f7..b6101bd4d8 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/StringBuilder.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/StringBuilder.kt
@@ -1,24 +1,3 @@
package com.tangem.tap.common.extensions
-/**
-[REDACTED_AUTHOR]
- */
-fun StringBuilder.appendIf(value: String, predicate: (String) -> Boolean): StringBuilder {
- if (predicate(value)) this.append(value)
- return this
-}
-
-fun StringBuilder.appendIfNotNull(value: String?, prefix: String? = null, postfix: String? = null): StringBuilder {
- if (value == null) return this
-
- prefix?.let { append(it) }
- append(value)
- postfix?.let { append(it) }
- return this
-}
-
-fun String.appendIfNotNull(value: String?, prefix: String? = null, postfix: String? = null): String {
- return StringBuilder(this).apply { appendIfNotNull(value, prefix, postfix) }.toString()
-}
-
fun StringBuilder.breakLine(count: Int = 1): StringBuilder = append("\n".repeat(count))
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Toast.kt b/app/src/main/java/com/tangem/tap/common/extensions/Toast.kt
deleted file mode 100644
index 23d969af40..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/Toast.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.content.Context
-import android.view.View
-import android.widget.Toast
-import androidx.annotation.StringRes
-import androidx.fragment.app.Fragment
-
-fun Context.toast(message: String, length: Int = Toast.LENGTH_LONG) {
- Toast.makeText(this, message, length).show()
-}
-
-fun Context.toast(@StringRes messageRes: Int, length: Int = Toast.LENGTH_LONG) {
- Toast.makeText(this, this.getString(messageRes), length).show()
-}
-
-fun View.toast(message: String, length: Int = Toast.LENGTH_LONG) {
- context.toast(message, length)
-}
-
-fun View.toast(@StringRes messageRes: Int, length: Int = Toast.LENGTH_LONG) {
- context.toast(context.getString(messageRes), length)
-}
-
-fun Fragment.toast(message: String, length: Int = Toast.LENGTH_LONG) {
- context?.toast(message, length)
-}
-
-fun Fragment.toast(@StringRes messageRes: Int, length: Int = Toast.LENGTH_LONG) {
- context?.let { it.toast(it.getString(messageRes), length) }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Token.kt b/app/src/main/java/com/tangem/tap/common/extensions/Token.kt
deleted file mode 100644
index 7acbdfd9fb..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/Token.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.graphics.Color
-import androidx.annotation.ColorInt
-import androidx.core.graphics.luminance
-import androidx.core.graphics.toColorInt
-import com.tangem.blockchain.common.Token
-
-@Suppress("MagicNumber")
-@ColorInt
-fun Token.getColor(isTestnet: Boolean = false): Int {
- val defaultColor = "#C7C7CC".toColorInt() // equivalent to R.color.lightGray4
-
- return if (isTestnet) {
- defaultColor
- } else {
- try {
- ("#" + this.contractAddress.subSequence(2..7).toString()).toColorInt()
- } catch (exception: Exception) {
- defaultColor
- }
- }
-}
-
-@Suppress("MagicNumber")
-@ColorInt
-fun Token.getTextColor(isTestnet: Boolean = false): Int = when {
- isTestnet -> Color.WHITE
- this.getColor().luminance > 0.5 -> Color.BLACK
- else -> Color.WHITE
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Transition.kt b/app/src/main/java/com/tangem/tap/common/extensions/Transition.kt
deleted file mode 100644
index d1e6b742f5..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/Transition.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import androidx.transition.Transition
-
-/**
-[REDACTED_AUTHOR]
- */
-inline fun Transition.addListener(
- crossinline onStart: (animator: Transition) -> Unit = {},
- crossinline onEnd: (animator: Transition) -> Unit = {},
- crossinline onCancel: (animator: Transition) -> Unit = {},
- crossinline onPause: (animator: Transition) -> Unit = {},
- crossinline onRepeat: (animator: Transition) -> Unit = {},
-): Transition.TransitionListener {
- val listener = object : Transition.TransitionListener {
- override fun onTransitionStart(transition: Transition) = onStart(transition)
- override fun onTransitionEnd(transition: Transition) = onEnd(transition)
- override fun onTransitionCancel(transition: Transition) = onCancel(transition)
- override fun onTransitionPause(transition: Transition) = onPause(transition)
- override fun onTransitionResume(transition: Transition) = onRepeat(transition)
- }
- addListener(listener)
- return listener
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/UI.kt b/app/src/main/java/com/tangem/tap/common/extensions/UI.kt
index 980f206701..524edaded8 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/UI.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/UI.kt
@@ -3,25 +3,12 @@
package com.tangem.tap.common.extensions
import android.app.Activity
-import android.content.ClipData
-import android.content.ClipboardManager
-import android.content.Context
-import android.content.ContextWrapper
-import android.content.Intent
+import android.content.*
import android.graphics.drawable.Drawable
-import android.util.TypedValue
import android.view.View
-import android.view.ViewGroup
-import android.view.inputmethod.InputMethodManager
-import androidx.annotation.ColorInt
-import androidx.annotation.ColorRes
-import androidx.annotation.DrawableRes
-import androidx.annotation.PluralsRes
-import androidx.annotation.StringRes
+import androidx.annotation.*
import androidx.core.content.ContextCompat
-import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
-import com.google.android.material.card.MaterialCardView
fun Context.getDrawableCompat(@DrawableRes drawableResId: Int): Drawable? {
return ContextCompat.getDrawable(this, drawableResId)
@@ -72,48 +59,9 @@ fun View.hide(invokeBeforeStateChanged: (() -> Unit)? = null) {
this.visibility = View.GONE
}
-fun View.invisible(invisible: Boolean = true, invokeBeforeStateChanged: (() -> Unit)? = null) {
- if (invisible) {
- if (this.visibility == View.INVISIBLE) return
-
- invokeBeforeStateChanged?.invoke()
- this.visibility = View.INVISIBLE
- } else {
- this.show(invokeBeforeStateChanged)
- }
-}
-
-fun Context.dpToPixels(dp: Int): Int = TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP,
- dp.toFloat(),
- this.resources.displayMetrics,
-).toInt()
-
tailrec fun Context?.getActivity(): Activity? = this as? Activity
?: (this as? ContextWrapper)?.baseContext?.getActivity()
-fun MaterialCardView.setMargins(
- marginLeftDp: Int = 16,
- marginTopDp: Int = 8,
- marginRightDp: Int = 16,
- marginBottomDp: Int = 8,
-) {
- val params = this.layoutParams
- (params as ViewGroup.MarginLayoutParams).setMargins(
- context.dpToPixels(marginLeftDp),
- context.dpToPixels(marginTopDp),
- context.dpToPixels(marginRightDp),
- context.dpToPixels(marginBottomDp),
- )
- this.layoutParams = params
-}
-
-fun View.hideKeyboard() {
- val inputMethodManager =
- context.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
- inputMethodManager?.hideSoftInputFromWindow(this.windowToken, 0)
-}
-
fun Context.copyToClipboard(value: Any, label: String = "") {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager ?: return
@@ -140,37 +88,6 @@ fun Context.shareText(text: String) {
startActivity(shareIntent)
}
-fun Fragment.shareText(text: String) {
- requireContext().shareText(text)
-}
-
fun View.getString(resId: Int, vararg formatArgs: Any?): String {
return context.getString(resId, *formatArgs)
-}
-
-fun View.animateVisibility(
- show: Boolean,
- durationMillis: Long = SHORT_ANIMATION_DURATION,
- hiddenVisibility: Int = View.GONE,
-) {
- if (show) {
- if (this.visibility == View.VISIBLE) return
- this.animate()
- .alpha(1f)
- .setDuration(durationMillis)
- .withStartAction {
- this.alpha = 0f
- this.isVisible = true
- }
- } else {
- if (this.visibility == hiddenVisibility) return
- this.animate()
- .alpha(0f)
- .setDuration(durationMillis)
- .withStartAction {
- this.visibility = hiddenVisibility
- }
- }
-}
-
-private const val SHORT_ANIMATION_DURATION = 80L
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/ViewGroup.kt b/app/src/main/java/com/tangem/tap/common/extensions/ViewGroup.kt
index 50c90e1133..214138e5dc 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/ViewGroup.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/ViewGroup.kt
@@ -3,15 +3,9 @@ package com.tangem.tap.common.extensions
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.ViewParent
-import androidx.core.view.forEach
import androidx.transition.AutoTransition
import androidx.transition.Transition
import androidx.transition.TransitionManager
-import com.google.android.material.chip.Chip
-import com.google.android.material.chip.ChipGroup
-import com.tangem.tap.common.GlobalLayoutStateHandler
-import timber.log.Timber
/**
[REDACTED_AUTHOR]
@@ -20,30 +14,6 @@ fun ViewGroup.inflate(viewToInflate: Int, attachToRoot: Boolean = false): View {
return LayoutInflater.from(context).inflate(viewToInflate, this, attachToRoot)
}
-fun ViewParent?.beginDelayedTransition(transition: Transition = AutoTransition()) {
- if (this == null) Timber.e("Can't invoke beginDelayedTransition, because parent is NULL")
- (this as? ViewGroup)?.beginDelayedTransition(transition)
-}
-
fun ViewGroup.beginDelayedTransition(transition: Transition = AutoTransition()) {
TransitionManager.beginDelayedTransition(this, transition)
-}
-
-fun View.beginDelayedTransition(transition: Transition = AutoTransition()) {
- (this as? ViewGroup)?.beginDelayedTransition(transition)
-}
-
-fun ChipGroup.fitChipsByGroupWidth() {
- val layoutStateHandler = GlobalLayoutStateHandler(this)
- layoutStateHandler.onStateChanged = stateHandler@{
- if (it.childCount < 2) {
- layoutStateHandler.detach()
- return@stateHandler
- }
-
- val spacingBetweenViews = it.chipSpacingHorizontal * (it.childCount - 1)
- val width = (it.width - spacingBetweenViews) / it.childCount
- it.forEach { chip -> (chip as? Chip)?.width = width }
- layoutStateHandler.detach()
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt
index 0427435795..9f6ba786f0 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt
@@ -3,15 +3,14 @@ package com.tangem.tap.common.extensions
import com.tangem.blockchain.common.BlockchainSdkError
import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.common.WalletManager
+import com.tangem.blockchain.common.address.AddressType
import com.tangem.common.services.Result
import com.tangem.domain.common.extensions.amountToCreateAccount
import com.tangem.tap.common.TestActions
import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
import com.tangem.tap.domain.TapError
import com.tangem.tap.domain.getFirstToken
-import com.tangem.tap.domain.model.WalletDataModel
-import com.tangem.tap.features.demo.isDemoCard
-import com.tangem.tap.features.wallet.redux.reducers.createAddressesData
+import com.tangem.tap.domain.model.WalletAddressData
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.store
@@ -59,7 +58,7 @@ suspend fun WalletManager.safeUpdate(isDemoCard: Boolean): Result = try
}
}
-fun WalletManager.getTopUpUrl(): String? {
+internal fun WalletManager.getTopUpUrl(): String? {
val globalState = store.state.globalState
val defaultAddress = wallet.address
@@ -73,9 +72,28 @@ fun WalletManager.getTopUpUrl(): String? {
)
}
-fun WalletManager?.getAddressData(): WalletDataModel.AddressData? {
+internal fun WalletManager?.getAddressData(): WalletAddressData? {
val wallet = this?.wallet ?: return null
val addressDataList = wallet.createAddressesData()
return if (addressDataList.isEmpty()) null else addressDataList[0]
+}
+
+private fun Wallet.createAddressesData(): List {
+ val listOfAddressData = mutableListOf()
+ // put a defaultAddress at the first place
+ addresses.forEach {
+ val addressData = WalletAddressData(
+ it.value,
+ it.type,
+ getShareUri(it.value),
+ getExploreUrl(it.value),
+ )
+ if (it.type == AddressType.Default) {
+ listOfAddressData.add(0, addressData)
+ } else {
+ listOfAddressData.add(addressData)
+ }
+ }
+ return listOfAddressData
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WebView.kt b/app/src/main/java/com/tangem/tap/common/extensions/WebView.kt
index 7aa93b2bb1..1afe53b3ba 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/WebView.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/WebView.kt
@@ -2,17 +2,6 @@ package com.tangem.tap.common.extensions
import android.webkit.WebView
-/**
-[REDACTED_AUTHOR]
- */
-fun WebView.configureSettings() {
- resumeTimers()
- settings.apply {
- javaScriptEnabled = true
- domStorageEnabled = true
- }
-}
-
fun WebView.stop() {
stopLoading()
pauseTimers()
diff --git a/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt b/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt
index 860f1e3374..b588d0d641 100644
--- a/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt
+++ b/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt
@@ -3,6 +3,7 @@ package com.tangem.tap.common.feedback
import android.os.Build
import com.tangem.blockchain.common.*
import com.tangem.blockchain.common.address.Address
+import com.tangem.crypto.NetworkType
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.userwallets.UserWalletIdBuilder
@@ -35,6 +36,7 @@ class AdditionalFeedbackInfo {
var cardIssuer: String = ""
var cardBlockchain: String = ""
var userWalletId: String = ""
+ var extendedPublicKey: String = ""
// wallets
val walletsInfo = CopyOnWriteArrayList()
@@ -70,6 +72,9 @@ class AdditionalFeedbackInfo {
cardIssuer = data.card.issuer.name
signedHashesCount = formatSignedHashes(data.card.wallets)
userWalletId = UserWalletIdBuilder.scanResponse(data).build()?.stringValue ?: ""
+ extendedPublicKey = data.card.wallets.firstOrNull { it.extendedPublicKey != null }
+ ?.extendedPublicKey
+ ?.serialize(networkType = NetworkType.Mainnet).orEmpty()
}
@Deprecated("Don't use it directly")
diff --git a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackDataBuilder.kt b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackDataBuilder.kt
index 7ad4477154..33c6bba4f2 100644
--- a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackDataBuilder.kt
+++ b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackDataBuilder.kt
@@ -1,5 +1,6 @@
package com.tangem.tap.common.feedback
+import com.tangem.blockchain.common.Blockchain
import com.tangem.tap.common.extensions.breakLine
class FeedbackDataBuilder(
@@ -27,26 +28,32 @@ class FeedbackDataBuilder(
}
fun appendWalletsInfo(): FeedbackDataBuilder {
- infoHolder.walletsInfo.forEach {
+ infoHolder.walletsInfo.forEach { walletInfo ->
builder.appendDelimiter()
- builder.appendKeyValue("Blockchain", it.blockchain.fullName)
- builder.appendKeyValue("Derivation path", it.derivationPath)
- builder.appendKeyValue("Outputs count", it.outputsCount)
+ builder.appendKeyValue("Blockchain", walletInfo.blockchain.fullName)
+ builder.appendKeyValue("Derivation path", walletInfo.derivationPath)
- if (it.tokens.isNotEmpty()) {
+ if (walletInfo.blockchain == Blockchain.Bitcoin) {
+ builder.appendKeyValue("XPUB", infoHolder.extendedPublicKey)
+ }
+
+ builder.appendKeyValue("Outputs count", walletInfo.outputsCount)
+
+ if (walletInfo.tokens.isNotEmpty()) {
builder.append("Tokens:")
breakLine()
- it.tokens.forEach { token ->
+ walletInfo.tokens.forEach { token ->
builder.appendKeyValue("ID", token.id ?: "[custom token]")
builder.appendKeyValue("Name", token.name)
builder.appendKeyValue("Contract address", token.contractAddress)
}
}
- builder.appendKeyValue("Host", it.host)
- builder.appendKeyValue("Wallet address", it.addresses)
- builder.appendKeyValue("Explorer link", it.explorerLink)
+ builder.appendKeyValue("Host", walletInfo.host)
+ builder.appendKeyValue("Wallet address", walletInfo.addresses)
+ builder.appendKeyValue("Explorer link", walletInfo.explorerLink)
}
+
return this
}
diff --git a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt b/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt
deleted file mode 100644
index f49613149a..0000000000
--- a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.tangem.tap.common.qrCodeScan
-
-import android.Manifest
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
-import androidx.camera.lifecycle.ProcessCameraProvider
-import androidx.core.app.ActivityCompat
-import androidx.core.content.ContextCompat
-import by.kirich1409.viewbindingdelegate.viewBinding
-import com.google.common.util.concurrent.ListenableFuture
-import com.otaliastudios.cameraview.CameraView.PERMISSION_REQUEST_CODE
-import com.tangem.tap.features.details.ui.walletconnect.dialogs.PreviewBinder
-import com.tangem.wallet.R
-import com.tangem.wallet.databinding.LayoutQrScanningBinding
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Executors
-
-/**
-[REDACTED_AUTHOR]
- */
-class ScanQrCodeActivity : AppCompatActivity() {
-
- private val binding: LayoutQrScanningBinding by viewBinding(LayoutQrScanningBinding::bind)
-
- private var cameraProviderFuture: ListenableFuture? = null
- private var cameraExecutor: ExecutorService? = null
-
- private val binder = PreviewBinder()
-
- override fun onCreate(state: Bundle?) {
- super.onCreate(state)
-
- if (!permissionIsGranted()) requestPermission()
-
- setContentView(R.layout.layout_qr_scanning)
-
- cameraProviderFuture = ProcessCameraProvider.getInstance(this)
- cameraExecutor = Executors.newSingleThreadExecutor()
-
- cameraProviderFuture?.addListener(
- {
- val cameraProvider = cameraProviderFuture?.get()
- binder.bindPreview(
- context = this,
- binding = binding,
- lifecycleOwner = this,
- cameraProvider = requireNotNull(cameraProvider),
- cameraExecutor = requireNotNull(cameraExecutor),
- onScanned = { result ->
- setResult(SCAN_QR_REQUEST_CODE, Intent().apply { putExtra(SCAN_RESULT, result) })
- finish()
- },
- )
- },
- ContextCompat.getMainExecutor(this),
- )
-
- binding.overlay.post {
- binding.overlay.setViewFinder()
- }
- }
-
- override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
- if (requestCode != PERMISSION_REQUEST_CODE) return
-
- if (grantResults.isEmpty() || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
- finish()
- }
- }
-
- private fun permissionIsGranted(): Boolean {
- val cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
- return cameraPermission == PackageManager.PERMISSION_GRANTED
- }
-
- private fun requestPermission() {
- ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), PERMISSION_REQUEST_CODE)
- }
-
- companion object {
- const val SCAN_QR_REQUEST_CODE = 1001
- const val SCAN_RESULT = "scanResult"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ViewFinderOverlay.kt b/app/src/main/java/com/tangem/tap/common/qrCodeScan/ViewFinderOverlay.kt
deleted file mode 100644
index f4939b828f..0000000000
--- a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ViewFinderOverlay.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.tangem.tap.common.qrCodeScan
-
-import android.content.Context
-import android.graphics.*
-import android.util.AttributeSet
-import android.view.View
-import androidx.core.content.ContextCompat
-import com.tangem.wallet.R
-
-class ViewFinderOverlay(context: Context, attrs: AttributeSet) : View(context, attrs) {
-
- private val boxPaint: Paint = Paint().apply {
- color = ContextCompat.getColor(context, R.color.white)
- style = Paint.Style.STROKE
- strokeWidth = context.resources.getDimensionPixelOffset(R.dimen.qr_border_stroke_width).toFloat()
- }
-
- private val boxWidthRatio = 0.8F
- private val boxCornerRadius: Float =
- context.resources.getDimensionPixelOffset(R.dimen.qr_border_corner_radius).toFloat()
-
- private var boxRect: RectF? = null
-
- @Suppress("MagicNumber")
- fun setViewFinder() {
- val overlayWidth = width.toFloat()
- val overlayHeight = height.toFloat()
- val boxSize = overlayWidth * boxWidthRatio
- val cx = overlayWidth / 2
- val cy = overlayHeight / 2
- boxRect = RectF(cx - boxSize / 2, cy - boxSize / 2, cx + boxSize / 2, cy + boxSize / 2)
-
- invalidate()
- }
-
- override fun draw(canvas: Canvas) {
- super.draw(canvas)
- boxRect?.let {
- canvas.drawRoundRect(it, boxCornerRadius, boxCornerRadius, boxPaint)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppDialog.kt b/app/src/main/java/com/tangem/tap/common/redux/AppDialog.kt
index 38479e6a1f..fc362509c3 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/AppDialog.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/AppDialog.kt
@@ -3,16 +3,14 @@ package com.tangem.tap.common.redux
import com.tangem.common.extensions.VoidCallback
import com.tangem.core.navigation.StateDialog
import com.tangem.tap.common.TestAction
-import com.tangem.tap.domain.model.WalletDataModel
-import com.tangem.tap.features.wallet.models.Currency
+import com.tangem.tap.domain.model.Currency
+import com.tangem.tap.domain.model.WalletAddressData
+import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
sealed class AppDialog : StateDialog {
- data class SimpleOkDialog(val header: String, val message: String, val onOk: VoidCallback? = null) : AppDialog()
- data class SimpleOkErrorDialog(val message: String, val onOk: VoidCallback? = null) : AppDialog()
- data class SimpleOkWarningDialog(val message: String, val onOk: VoidCallback? = null) : AppDialog()
data class SimpleOkDialogRes(
val headerId: Int,
val messageId: Int,
@@ -20,24 +18,33 @@ sealed class AppDialog : StateDialog {
val onOk: VoidCallback? = null,
) : AppDialog()
- data class OkCancelDialogRes(
- val headerId: Int,
- val messageId: Int,
- val okButton: DialogButton,
- val cancelButton: DialogButton,
- ) : AppDialog()
-
- data class DialogButton(
- val title: Int,
- val action: VoidCallback? = null,
- )
-
- data class AddressInfoDialog(
+ internal data class AddressInfoDialog(
val currency: Currency,
- val addressData: WalletDataModel.AddressData,
+ val addressData: WalletAddressData,
) : AppDialog()
data class TestActionsDialog(
val actionsList: List,
) : AppDialog()
+
+ data class RussianCardholdersWarningDialog(val data: Data?) : AppDialog() {
+ data class Data(val topUpUrl: String)
+ }
+
+ data class RemoveWalletDialog(
+ val currencyTitle: String,
+ val onOk: () -> Unit,
+ ) : AppDialog() {
+ val messageRes: Int = R.string.token_details_hide_alert_message
+ val titleRes: Int = R.string.token_details_hide_alert_title
+ val primaryButtonRes: Int = R.string.token_details_hide_alert_hide
+ }
+
+ data class TokensAreLinkedDialog(
+ val currencyTitle: String,
+ val currencySymbol: String,
+ ) : AppDialog() {
+ val messageRes: Int = R.string.token_details_unable_hide_alert_message
+ val titleRes: Int = R.string.token_details_unable_hide_alert_title
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt
index 8175888c08..a1232dd031 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt
@@ -15,8 +15,6 @@ import com.tangem.tap.features.send.redux.reducers.SendScreenReducer
import com.tangem.tap.features.shop.redux.ShopReducer
import com.tangem.tap.features.signin.redux.SignInReducer
import com.tangem.tap.features.tokens.legacy.redux.TokensReducer
-import com.tangem.tap.features.wallet.redux.reducers.WalletReducer
-import com.tangem.tap.features.walletSelector.redux.WalletSelectorReducer
import com.tangem.tap.features.welcome.redux.WelcomeReducer
import com.tangem.tap.proxy.AppStateHolder
import com.tangem.tap.proxy.redux.DaggerGraphReducer
@@ -33,7 +31,6 @@ fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder)
onboardingNoteState = OnboardingNoteReducer.reduce(action, state),
onboardingWalletState = OnboardingWalletReducer.reduce(action, state),
onboardingOtherCardsState = OnboardingOtherCardsReducer.reduce(action, state),
- walletState = WalletReducer.reduce(action, state, appStateHolder),
twinCardsState = TwinCardsReducer.reduce(action, state),
sendState = SendScreenReducer.reduce(action, state.sendState),
detailsState = DetailsReducer.reduce(action, state),
@@ -43,7 +40,6 @@ fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder)
shopState = ShopReducer.reduce(action, state.shopState),
welcomeState = WelcomeReducer.reduce(action, state),
saveWalletState = SaveWalletReducer.reduce(action, state),
- walletSelectorState = WalletSelectorReducer.reduce(action, state),
signInState = SignInReducer.reduce(action, state),
daggerGraphState = DaggerGraphReducer.reduce(action, state),
)
diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt
index 7b9b9f2bd4..e312758a52 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt
@@ -35,10 +35,7 @@ import com.tangem.tap.features.signin.redux.SignInMiddleware
import com.tangem.tap.features.signin.redux.SignInState
import com.tangem.tap.features.tokens.legacy.redux.TokensMiddleware
import com.tangem.tap.features.tokens.legacy.redux.TokensState
-import com.tangem.tap.features.wallet.redux.WalletState
-import com.tangem.tap.features.wallet.redux.middlewares.WalletMiddleware
-import com.tangem.tap.features.walletSelector.redux.WalletSelectorMiddleware
-import com.tangem.tap.features.walletSelector.redux.WalletSelectorState
+import com.tangem.tap.features.wallet.redux.middlewares.TradeCryptoMiddleware
import com.tangem.tap.features.welcome.redux.WelcomeMiddleware
import com.tangem.tap.features.welcome.redux.WelcomeState
import com.tangem.tap.proxy.redux.DaggerGraphMiddleware
@@ -54,7 +51,6 @@ data class AppState(
val onboardingNoteState: OnboardingNoteState = OnboardingNoteState(),
val onboardingWalletState: OnboardingWalletState = OnboardingWalletState(),
val onboardingOtherCardsState: OnboardingOtherCardsState = OnboardingOtherCardsState(),
- val walletState: WalletState = WalletState(),
val twinCardsState: TwinCardsState = TwinCardsState(),
val sendState: SendState = SendState(),
val detailsState: DetailsState = DetailsState(),
@@ -64,7 +60,6 @@ data class AppState(
val shopState: ShopState = ShopState(),
val welcomeState: WelcomeState = WelcomeState(),
val saveWalletState: SaveWalletState = SaveWalletState(),
- val walletSelectorState: WalletSelectorState = WalletSelectorState(),
val signInState: SignInState = SignInState(),
val daggerGraphState: DaggerGraphState = DaggerGraphState(),
) : StateType {
@@ -72,7 +67,7 @@ data class AppState(
private val domainState: DomainState
get() = domainStore.state
- val domainNetworks: NetworkServices
+ private val domainNetworks: NetworkServices
get() = domainState.globalState.networkServices
val featureRepositoryProvider: FeatureRepositoryProvider
@@ -92,7 +87,6 @@ data class AppState(
OnboardingNoteMiddleware.handler,
OnboardingWalletMiddleware.handler,
OnboardingOtherCardsMiddleware.handler,
- WalletMiddleware().walletMiddleware,
TwinCardsMiddleware.handler,
SendMiddleware().sendMiddleware,
DetailsMiddleware().detailsMiddleware,
@@ -103,12 +97,12 @@ data class AppState(
ShopMiddleware().shopMiddleware,
WelcomeMiddleware().middleware,
SaveWalletMiddleware().middleware,
- WalletSelectorMiddleware().middleware,
LockUserWalletsTimerMiddleware().middleware,
AccessCodeRequestPolicyMiddleware().middleware,
SignInMiddleware.middleware,
DaggerGraphMiddleware.daggerGraphMiddleware,
LegacyMiddleware.legacyMiddleware,
+ TradeCryptoMiddleware.middleware,
)
}
}
diff --git a/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt b/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt
index 5794edffb9..55e4c0b653 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt
@@ -3,13 +3,9 @@ package com.tangem.tap.common.redux
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.tap.features.home.data.HomeRepositoryImpl
import com.tangem.tap.features.home.domain.HomeRepository
-import com.tangem.tap.features.wallet.data.WalletRepositoryImpl
-import com.tangem.tap.features.wallet.domain.WalletRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
class FeatureRepositoryProvider(tangemTechApi: TangemTechApi, dispatchers: CoroutineDispatcherProvider) {
- val walletRepository: WalletRepository = WalletRepositoryImpl(tangemTechApi, dispatchers)
-
val homeRepository: HomeRepository = HomeRepositoryImpl(tangemTechApi, dispatchers)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/NotificationsMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/NotificationsMiddleware.kt
index 4a7cb7b8f8..1b862e7ed4 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/NotificationsMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/NotificationsMiddleware.kt
@@ -20,22 +20,14 @@ class NotificationsHandler(coordinatorLayout: CoordinatorLayout) {
private val basicCoordinatorLayout = WeakReference(coordinatorLayout)
private var baseLayout = basicCoordinatorLayout
- fun replaceBaseLayout(coordinatorLayout: CoordinatorLayout) {
- baseLayout = WeakReference(coordinatorLayout)
- }
-
- fun returnBaseLayout() {
- baseLayout = basicCoordinatorLayout
- }
-
- fun showNotification(message: String) {
+ private fun showNotification(message: String) {
baseLayout.get()?.let { layout ->
Snackbar.make(layout, message, Snackbar.LENGTH_LONG)
.also { snackbar -> snackbar.show() }
}
}
- fun showDebugNotification(message: String) {
+ private fun showDebugNotification(message: String) {
baseLayout.get()?.let { layout ->
Snackbar.make(layout, message, Snackbar.LENGTH_LONG)
.also { snackbar ->
diff --git a/app/src/main/java/com/tangem/tap/common/redux/Request.kt b/app/src/main/java/com/tangem/tap/common/redux/Request.kt
deleted file mode 100644
index 4faae37c93..0000000000
--- a/app/src/main/java/com/tangem/tap/common/redux/Request.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.tangem.tap.common.redux
-
-import org.rekotlin.Action
-
-abstract class Request : Action {
- abstract suspend fun execute()
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt
index 13a9ee6ac8..c2bd7ec6d8 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt
@@ -5,17 +5,15 @@ import com.tangem.common.CompletionResult
import com.tangem.core.navigation.StateDialog
import com.tangem.datasource.config.ConfigManager
import com.tangem.datasource.config.models.ChatConfig
+import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.apptheme.model.AppThemeMode
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.legacy.UserWalletsListManager
-import com.tangem.tap.common.analytics.topup.TopUpController
-import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.common.feedback.FeedbackData
import com.tangem.tap.common.feedback.FeedbackManager
import com.tangem.tap.common.redux.DebugErrorAction
import com.tangem.tap.common.redux.ErrorAction
import com.tangem.tap.common.redux.NotificationAction
-import com.tangem.tap.common.redux.ToastNotificationAction
import com.tangem.tap.domain.TapError
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
@@ -26,7 +24,6 @@ sealed class GlobalAction : Action {
// notifications
data class ShowNotification(override val messageResource: Int) : GlobalAction(), NotificationAction
- data class ShowToastNotification(override val messageResource: Int) : GlobalAction(), ToastNotificationAction
data class ShowErrorNotification(override val error: TapError) : GlobalAction(), ErrorAction
data class DebugShowErrorNotification(override val error: TapError) : GlobalAction(), DebugErrorAction
@@ -61,9 +58,9 @@ sealed class GlobalAction : Action {
data class SetIfCardVerifiedOnline(val verified: Boolean) : GlobalAction()
- data class ChangeAppCurrency(val appCurrency: FiatCurrency) : GlobalAction()
+ data class ChangeAppCurrency(val appCurrency: AppCurrency) : GlobalAction()
object RestoreAppCurrency : GlobalAction() {
- data class Success(val appCurrency: FiatCurrency) : GlobalAction()
+ data class Success(val appCurrency: AppCurrency) : GlobalAction()
}
data class UpdateWalletSignedHashes(
@@ -78,7 +75,6 @@ sealed class GlobalAction : Action {
data class SetConfigManager(val configManager: ConfigManager) : GlobalAction()
data class SetWarningManager(val warningManager: WarningMessagesManager) : GlobalAction()
data class SetFeedbackManager(val feedbackManager: FeedbackManager) : GlobalAction()
- data class SetTopUpController(val topUpController: TopUpController) : GlobalAction()
data class SendEmail(val feedbackData: FeedbackData) : GlobalAction()
data class OpenChat(val feedbackData: FeedbackData, val chatConfig: ChatConfig? = null) : GlobalAction()
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt
index d20875298c..841c3ff5a4 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt
@@ -6,19 +6,18 @@ import com.tangem.common.extensions.guard
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.StateDialog
import com.tangem.datasource.config.models.Config
+import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.common.LogConfig
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
-import com.tangem.tap.*
-import com.tangem.tap.common.analytics.events.Basic
-import com.tangem.tap.common.entities.FiatCurrency
+import com.tangem.core.analytics.models.Basic
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.features.send.redux.SendAction
-import com.tangem.tap.features.wallet.redux.WalletAction
+import com.tangem.tap.mainScope
import com.tangem.tap.network.exchangeServices.BuyExchangeService
import com.tangem.tap.network.exchangeServices.CardExchangeRules
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
@@ -27,6 +26,9 @@ import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoEnvironment
import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoService
import com.tangem.tap.network.exchangeServices.moonpay.MoonPayService
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.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
@@ -67,17 +69,7 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
}
}
is GlobalAction.RestoreAppCurrency -> {
- val daggerGraphState = store.state.daggerGraphState
- val walletFeatureToggles = daggerGraphState.get(DaggerGraphState::walletFeatureToggles)
- val detailsFeatureToggles = daggerGraphState.get(DaggerGraphState::detailsFeatureToggles)
-
- if (walletFeatureToggles.isRedesignedScreenEnabled ||
- detailsFeatureToggles.isRedesignedAppCurrencySelectorEnabled
- ) {
- restoreAppCurrencyNew()
- } else {
- restoreAppCurrencyLegacy()
- }
+ restoreAppCurrency()
}
is GlobalAction.HideWarningMessage -> {
store.state.globalState.warningManager?.let {
@@ -87,7 +79,6 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
// store.dispatch(WalletAction.Warnings.CheckHashesCount.SaveCardId)
// }
- store.dispatch(WalletAction.Warnings.Update)
store.dispatch(SendAction.Warnings.Update)
}
}
@@ -115,9 +106,6 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
}
feedbackManager.openChat(chatConfig, action.feedbackData)
}
- is GlobalAction.UpdateWalletSignedHashes -> {
- store.dispatch(WalletAction.Warnings.CheckRemainingSignatures(action.remainingSignatures))
- }
is GlobalAction.UpdateFeedbackInfo -> {
store.state.globalState.feedbackManager?.infoHolder
?.setWalletsInfo(action.walletManagers)
@@ -169,9 +157,6 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
}
}
}
- is GlobalAction.SetTopUpController -> {
- walletCurrenciesManager.addListener(action.topUpController)
- }
is GlobalAction.UpdateUserWalletsListManager -> {
val walletManagersFacade = store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade)
@@ -201,23 +186,12 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
}
}
-private fun restoreAppCurrencyLegacy() {
- store.dispatch(
- GlobalAction.RestoreAppCurrency.Success(
- preferencesStorage.fiatCurrenciesPrefStorage.getAppCurrency()
- ?.run { FiatCurrency(code, name, symbol) }
- ?: FiatCurrency.Default,
- ),
- )
-}
-
-private fun restoreAppCurrencyNew() {
+private fun restoreAppCurrency() {
scope.launch {
val currency = store.state.daggerGraphState.get(DaggerGraphState::appCurrencyRepository)
.getSelectedAppCurrency()
.firstOrNull()
- ?.run { FiatCurrency(code, name, symbol) }
- ?: FiatCurrency.Default
+ ?: AppCurrency.Default
store.dispatchWithMain(GlobalAction.RestoreAppCurrency.Success(currency))
}
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt
index 2b282844d5..f6fe0f4b00 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt
@@ -52,7 +52,6 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
globalState.copy(configManager = action.configManager)
}
is GlobalAction.SetWarningManager -> globalState.copy(warningManager = action.warningManager)
- is GlobalAction.SetTopUpController -> globalState.copy(topUpController = action.topUpController)
is GlobalAction.UpdateWalletSignedHashes -> {
val card = globalState.scanResponse?.card ?: return globalState
val wallet = card.wallets
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
index c20fbea0f9..5cdc02d930 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
@@ -2,11 +2,10 @@ package com.tangem.tap.common.redux.global
import com.tangem.core.navigation.StateDialog
import com.tangem.datasource.config.ConfigManager
+import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.apptheme.model.AppThemeMode
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.legacy.UserWalletsListManager
-import com.tangem.tap.common.analytics.topup.TopUpController
-import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.common.feedback.FeedbackManager
import com.tangem.tap.domain.TapWalletManager
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
@@ -23,13 +22,12 @@ data class GlobalState(
val configManager: ConfigManager? = null,
val warningManager: WarningMessagesManager? = null,
val feedbackManager: FeedbackManager? = null,
- val appCurrency: FiatCurrency = FiatCurrency.Default,
+ val appCurrency: AppCurrency = AppCurrency.Default,
val scanCardFailsCounter: Int = 0,
val dialog: StateDialog? = null,
val exchangeManager: CurrencyExchangeManager = CurrencyExchangeManager.dummy(),
val userCountryCode: String? = null,
val userWalletsListManager: UserWalletsListManager? = null,
- val topUpController: TopUpController? = null,
val appThemeMode: AppThemeMode = AppThemeMode.DEFAULT,
) : StateType
diff --git a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt
index 97d9bd093b..1a1b5827f0 100644
--- a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt
+++ b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt
@@ -169,7 +169,7 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) {
return Result.success(products)
}
- suspend fun applyPromoCode(promoCode: String, productType: ProductType): Result {
+ private suspend fun applyPromoCode(promoCode: String, productType: ProductType): Result {
val checkout = checkouts[productType] ?: return Result.failure(Exception("No checkout"))
val result = if (promoCode.isBlank()) {
diff --git a/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt b/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt
index 0f7cfdf42b..705bd067a0 100644
--- a/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt
+++ b/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt
@@ -19,26 +19,7 @@ import kotlin.coroutines.suspendCoroutine
@Suppress("LargeClass")
class ShopifyService(private val application: Application, val shop: ShopifyShop) {
- val client: GraphClient by lazy { initClient() }
-
- suspend fun getShopName(): Result {
- val query = query { rootQuery: QueryRootQuery ->
- rootQuery
- .shop { shopQuery: ShopQuery ->
- shopQuery
- .name()
- }
- }
- return when (val result = queryAsync(query)) {
- is GraphCallResult.Success -> {
- val name = result.response.data!!.shop.name
- Result.success(name)
- }
- is GraphCallResult.Failure -> {
- Result.failure(result.error)
- }
- }
- }
+ private val client: GraphClient by lazy { initClient() }
@Suppress("MagicNumber")
suspend fun getProducts(collectionTitleFilter: String? = null): Result> {
diff --git a/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt b/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt
index b540a9d7c2..939fc17c61 100644
--- a/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt
+++ b/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt
@@ -8,9 +8,13 @@ import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updateLayoutParams
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.ContentViewCallback
import com.google.android.material.snackbar.Snackbar
+import com.tangem.sdk.extensions.dpToPx
import com.tangem.wallet.R
/**
@@ -27,15 +31,29 @@ class MaxAmountSnackbar(
val parent = view.findSuitableParent() ?: throw IllegalArgumentException(
"No suitable parent found from the given view. Please provide a valid view.",
)
- val inflater = LayoutInflater.from(view.context)
+ val inflater = LayoutInflater.from(parent.context)
val customView = inflater.inflate(R.layout.view_snackbar_max_amount, parent, false) as MaxAmountSnackbarView
customView.setOnClickListener { onClick() }
return MaxAmountSnackbar(parent, customView).apply {
+ updateBottomMargin()
duration = Snackbar.LENGTH_INDEFINITE
}
}
+ private fun MaxAmountSnackbar.updateBottomMargin() {
+ ViewCompat.setOnApplyWindowInsetsListener(this.view) { _, insets ->
+ val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
+ val bottomInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom
+
+ this.view.updateLayoutParams {
+ bottomMargin = imeInsets - bottomInsets + context.dpToPx(dp = 8f).toInt()
+ }
+
+ insets
+ }
+ }
+
private fun View?.findSuitableParent(): ViewGroup? {
var view = this
var fallback: ViewGroup? = null
diff --git a/app/src/main/java/com/tangem/tap/common/text/Truncate.kt b/app/src/main/java/com/tangem/tap/common/text/Truncate.kt
index 0aeb17d6d2..64aeea2d59 100644
--- a/app/src/main/java/com/tangem/tap/common/text/Truncate.kt
+++ b/app/src/main/java/com/tangem/tap/common/text/Truncate.kt
@@ -28,12 +28,12 @@ abstract class BaseTruncate : Truncate {
protected var hasBeenTruncated = false
override fun apply(tv: TextView, text: String, with: String): String {
- val roughLength = getRoughFitLength(tv, text, with)
+ val roughLength = getRoughFitLength(tv, text)
val fittedText = preciseFitting(tv, roughTruncate(text, roughLength), with)
return if (hasBeenTruncated) attachWith(fittedText, with) else fittedText
}
- protected fun getRoughFitLength(tv: TextView, text: String, with: String): Int {
+ private fun getRoughFitLength(tv: TextView, text: String): Int {
val existingSpace = tv.measuredWidth - (tv.paddingStart + tv.paddingEnd)
val textWillTakeSpace = tv.paint.measureText(text)
val overSizeRatio: Float = textWillTakeSpace / existingSpace
@@ -44,7 +44,7 @@ abstract class BaseTruncate : Truncate {
return maxLengthOfText.toInt()
}
- protected fun preciseFitting(tv: TextView, text: String, with: String): String {
+ private fun preciseFitting(tv: TextView, text: String, with: String): String {
if (!hasBeenTruncated) return text
val spaceForText = tv.measuredWidth - (tv.paddingStart + tv.paddingEnd)
@@ -126,11 +126,5 @@ fun TextView.truncateWith(text: String, type: TruncateType, with: String = "..."
return truncate.apply(this, text, with)
}
-fun TextView.truncateStartWith(text: String, with: String = "..."): String =
- this.truncateWith(text, TruncateType.START, with)
-
fun TextView.truncateMiddleWith(text: String, with: String = "..."): String =
- this.truncateWith(text, TruncateType.MIDDLE, with)
-
-fun TextView.truncateEndWith(text: String, with: String = "..."): String =
- this.truncateWith(text, TruncateType.END, with)
\ No newline at end of file
+ this.truncateWith(text, TruncateType.MIDDLE, with)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt b/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt
index 56f80d5d78..22817c3f93 100644
--- a/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt
+++ b/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt
@@ -3,9 +3,9 @@ package com.tangem.tap.common.toggleWidget
import android.graphics.drawable.Drawable
import android.view.View
import com.google.android.material.button.MaterialButton
+import com.tangem.tap.common.entities.ProgressState
import com.tangem.tap.common.extensions.hide
import com.tangem.tap.common.extensions.show
-import com.tangem.tap.features.wallet.redux.ProgressState
/**
[REDACTED_AUTHOR]
diff --git a/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt b/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt
index 6a5bd17f60..3996e28d5c 100644
--- a/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt
+++ b/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt
@@ -2,25 +2,16 @@ package com.tangem.tap.common.toggleWidget
import android.view.View
import android.view.ViewGroup
-import android.view.animation.AccelerateInterpolator
-import android.view.animation.AlphaAnimation
-import android.view.animation.Animation
-import android.view.animation.AnimationSet
-import android.view.animation.AnticipateOvershootInterpolator
-import android.view.animation.LinearInterpolator
-import android.view.animation.RotateAnimation
-import android.view.animation.ScaleAnimation
+import android.view.animation.*
import android.widget.ViewSwitcher
-import com.tangem.tap.features.wallet.redux.ProgressState
+import com.tangem.tap.common.entities.ProgressState
import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
@Suppress("MagicNumber")
-class RefreshBalanceWidget(
- private val root: ViewGroup,
-) : ViewStateWidget {
+class RefreshBalanceWidget(root: ViewGroup) : ViewStateWidget {
var isShowing: Boolean? = null
private set
diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/AddressInfoBottomSheetDialog.kt
similarity index 77%
rename from app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt
rename to app/src/main/java/com/tangem/tap/common/ui/AddressInfoBottomSheetDialog.kt
index 280ca66499..6a2a14d073 100644
--- a/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt
+++ b/app/src/main/java/com/tangem/tap/common/ui/AddressInfoBottomSheetDialog.kt
@@ -1,4 +1,4 @@
-package com.tangem.tap.features.onboarding
+package com.tangem.tap.common.ui
import android.content.Context
import android.os.Bundle
@@ -7,14 +7,9 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.tangem.core.analytics.Analytics
import com.tangem.tap.common.analytics.events.Token
-import com.tangem.tap.common.extensions.copyToClipboard
-import com.tangem.tap.common.extensions.dispatchDialogHide
-import com.tangem.tap.common.extensions.dispatchShare
-import com.tangem.tap.common.extensions.dispatchToastNotification
-import com.tangem.tap.common.extensions.getString
-import com.tangem.tap.common.extensions.toQrCode
+import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppDialog
-import com.tangem.tap.domain.model.WalletDataModel
+import com.tangem.tap.domain.model.WalletAddressData
import com.tangem.tap.store
import com.tangem.wallet.R
import com.tangem.wallet.databinding.DialogOnboardingAddressInfoBinding
@@ -22,7 +17,7 @@ import com.tangem.wallet.databinding.DialogOnboardingAddressInfoBinding
/**
[REDACTED_AUTHOR]
*/
-class AddressInfoBottomSheetDialog(
+internal class AddressInfoBottomSheetDialog(
private val stateDialog: AppDialog.AddressInfoDialog,
context: Context,
) : BottomSheetDialog(context) {
@@ -47,7 +42,7 @@ class AddressInfoBottomSheetDialog(
showData(data = stateDialog.addressData)
}
- private fun showData(data: WalletDataModel.AddressData) = with(binding!!) {
+ private fun showData(data: WalletAddressData) = with(binding!!) {
pseudoToolbar.imvClose.setOnClickListener {
dismissWithAnimation = true
cancel()
@@ -57,7 +52,6 @@ class AddressInfoBottomSheetDialog(
btnFlCopyAddress.setOnClickListener {
Analytics.send(Token.Receive.ButtonCopyAddress())
context.copyToClipboard(data.address)
- store.dispatchToastNotification(R.string.copy_toast_msg)
}
btnFlShare.setOnClickListener {
Analytics.send(Token.Receive.ButtonShareAddress())
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/RussianCardholdersWarningBottomSheetDialog.kt
similarity index 82%
rename from app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt
rename to app/src/main/java/com/tangem/tap/common/ui/RussianCardholdersWarningBottomSheetDialog.kt
index f4f2a4c143..64763a6216 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt
+++ b/app/src/main/java/com/tangem/tap/common/ui/RussianCardholdersWarningBottomSheetDialog.kt
@@ -1,4 +1,4 @@
-package com.tangem.tap.features.wallet.ui.dialogs
+package com.tangem.tap.common.ui
import android.content.Context
import android.os.Bundle
@@ -6,17 +6,16 @@ import android.view.LayoutInflater
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.NavigationAction
-import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.tap.common.analytics.events.Token
import com.tangem.tap.common.extensions.dispatchDialogHide
import com.tangem.tap.common.extensions.dispatchOpenUrl
-import com.tangem.tap.features.wallet.redux.models.WalletDialog
+import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.store
import com.tangem.wallet.databinding.DialogRussiansCardholdersWarningBinding
class RussianCardholdersWarningBottomSheetDialog(
context: Context,
- private val dialogData: WalletDialog.RussianCardholdersWarningDialog.Data?,
+ private val dialogData: AppDialog.RussianCardholdersWarningDialog.Data?,
) : BottomSheetDialog(context) {
private var binding: DialogRussiansCardholdersWarningBinding? = null
@@ -40,9 +39,8 @@ class RussianCardholdersWarningBottomSheetDialog(
if (dialogData != null) {
store.dispatchOpenUrl(dialogData.topUpUrl)
Analytics.send(Token.Topup.ScreenOpened())
- } else {
- store.dispatch(TradeCryptoAction.Buy(checkUserLocation = false))
}
+
dismiss()
}
binding?.btnNo?.setOnClickListener {
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/ScanFailsDialog.kt
similarity index 95%
rename from app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt
rename to app/src/main/java/com/tangem/tap/common/ui/ScanFailsDialog.kt
index 30d7d0b8e4..0034c0a08a 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt
+++ b/app/src/main/java/com/tangem/tap/common/ui/ScanFailsDialog.kt
@@ -1,4 +1,4 @@
-package com.tangem.tap.features.wallet.ui.dialogs
+package com.tangem.tap.common.ui
import android.content.Context
import androidx.appcompat.app.AlertDialog
diff --git a/app/src/main/java/com/tangem/tap/common/ui/SimpleOkDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/SimpleOkDialog.kt
new file mode 100644
index 0000000000..e0eb7acf6f
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/ui/SimpleOkDialog.kt
@@ -0,0 +1,31 @@
+package com.tangem.tap.common.ui
+
+import android.content.Context
+import androidx.appcompat.app.AlertDialog
+import com.tangem.tap.common.extensions.dispatchDialogHide
+import com.tangem.tap.common.redux.AppDialog
+import com.tangem.tap.store
+import com.tangem.wallet.R
+
+/**
+[REDACTED_AUTHOR]
+ */
+object SimpleOkDialog {
+
+ fun create(dialog: AppDialog.SimpleOkDialogRes, context: Context): AlertDialog {
+ val message = if (dialog.args.isEmpty()) {
+ context.getString(dialog.messageId)
+ } else {
+ context.getString(dialog.messageId, *dialog.args.toTypedArray())
+ }
+ return AlertDialog.Builder(context).apply {
+ setTitle(context.getString(dialog.headerId))
+ setMessage(message)
+ setPositiveButton(R.string.common_ok) { _, _ -> }
+ setOnDismissListener {
+ store.dispatchDialogHide()
+ dialog.onOk?.invoke()
+ }
+ }.create()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/utils/SafeStoreSubscriber.kt b/app/src/main/java/com/tangem/tap/common/utils/SafeStoreSubscriber.kt
deleted file mode 100644
index ac430a6ea5..0000000000
--- a/app/src/main/java/com/tangem/tap/common/utils/SafeStoreSubscriber.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.tangem.tap.common.utils
-
-import android.os.Handler
-import android.os.Looper
-import org.rekotlin.StoreSubscriber
-
-private val mainLooper by lazy { Looper.getMainLooper() }
-private val mainHandler by lazy { Handler(mainLooper) }
-
-/**
- * A subscriber interface for safely subscribing to state changes in a Store.
- *
- * @param State the type of the state in the Store
- */
-interface SafeStoreSubscriber : StoreSubscriber {
-
- /**
- * A function that will be called when the state in the Store changes.
- *
- * @param state the new state in the Store
- */
- override fun newState(state: State) {
- if (Thread.currentThread() != mainLooper.thread) {
- mainHandler.post { newStateOnMain(state) }
- } else {
- newStateOnMain(state)
- }
- }
-
- /**
- * A function that will be called on the main thread when the state in the Store changes.
- *
- * @param state the new state in the Store
- */
- fun newStateOnMain(state: State)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/data/RuntimeUserWalletsStore.kt b/app/src/main/java/com/tangem/tap/data/RuntimeUserWalletsStore.kt
index a84ddc77c6..884fa65323 100644
--- a/app/src/main/java/com/tangem/tap/data/RuntimeUserWalletsStore.kt
+++ b/app/src/main/java/com/tangem/tap/data/RuntimeUserWalletsStore.kt
@@ -21,4 +21,8 @@ internal class RuntimeUserWalletsStore(
?.firstOrNull()
?.singleOrNull { it.walletId == key }
}
+
+ override suspend fun update(userWalletId: UserWalletId, update: suspend (UserWallet) -> UserWallet) {
+ walletsStateHolder.userWalletsListManager?.update(userWalletId, update)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/data/CardDataModule.kt b/app/src/main/java/com/tangem/tap/di/data/CardDataModule.kt
new file mode 100644
index 0000000000..0f7457c20f
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/data/CardDataModule.kt
@@ -0,0 +1,27 @@
+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.TangemSdkManager
+import com.tangem.tap.domain.card.DefaultDerivationsRepository
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+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 {
+
+ @Singleton
+ @Provides
+ fun providesDerivationsRepository(
+ tangemSdkManager: TangemSdkManager,
+ userWalletsStore: UserWalletsStore,
+ dispatchers: CoroutineDispatcherProvider,
+ ): DerivationsRepository {
+ return DefaultDerivationsRepository(tangemSdkManager, userWalletsStore, dispatchers)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt
index 918b41ff04..0d32faca9a 100644
--- a/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt
+++ b/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt
@@ -3,6 +3,7 @@ package com.tangem.tap.di.domain
import com.tangem.domain.card.*
import com.tangem.domain.card.repository.CardRepository
import com.tangem.domain.card.repository.CardSdkConfigRepository
+import com.tangem.domain.card.repository.DerivationsRepository
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.wallets.legacy.WalletsStateHolder
@@ -61,8 +62,14 @@ internal object CardDomainModule {
@Provides
@ViewModelScoped
- fun provideDerivePublicKeysUseCase(tangemSdkManager: TangemSdkManager): DerivePublicKeysUseCase {
- return DefaultDerivePublicKeysUseCase(tangemSdkManager = tangemSdkManager)
+ fun provideDerivePublicKeysUseCase(
+ tangemSdkManager: TangemSdkManager,
+ derivationsRepository: DerivationsRepository,
+ ): DerivePublicKeysUseCase {
+ return DefaultDerivePublicKeysUseCase(
+ tangemSdkManager = tangemSdkManager,
+ derivationsRepository = derivationsRepository,
+ )
}
@Provides
diff --git a/app/src/main/java/com/tangem/tap/di/domain/QrScanningDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/QrScanningDomainModule.kt
new file mode 100644
index 0000000000..ba2c69965b
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/QrScanningDomainModule.kt
@@ -0,0 +1,20 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.feature.qrscanning.repo.QrScanningEventsRepository
+import com.tangem.feature.qrscanning.usecase.ListenToQrScanningUseCase
+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 QrScanningDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideListenToQrScanUseCase(repository: QrScanningEventsRepository): ListenToQrScanningUseCase {
+ return ListenToQrScanningUseCase(repository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt
index d62f5001d9..b07f25f84d 100644
--- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt
+++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt
@@ -18,6 +18,18 @@ import dagger.hilt.android.scopes.ViewModelScoped
@Suppress("TooManyFunctions")
internal object TokensDomainModule {
+ @Provides
+ @ViewModelScoped
+ fun provideAddCryptoCurrenciesUseCase(
+ currenciesRepository: CurrenciesRepository,
+ networksRepository: NetworksRepository,
+ ): AddCryptoCurrenciesUseCase {
+ return AddCryptoCurrenciesUseCase(
+ currenciesRepository = currenciesRepository,
+ networksRepository = networksRepository,
+ )
+ }
+
@Provides
@ViewModelScoped
fun provideFetchTokenListUseCase(
@@ -242,4 +254,44 @@ internal object TokensDomainModule {
fun provideGetGlobalTokenListUseCase(tokensListRepository: TokensListRepository): GetGlobalTokenListUseCase {
return GetGlobalTokenListUseCase(repository = tokensListRepository)
}
+
+ @Provides
+ @ViewModelScoped
+ fun provideCheckTokenCompatibilityUseCase(
+ repository: NetworksCompatibilityRepository,
+ ): CheckCurrencyCompatibilityUseCase {
+ return CheckCurrencyCompatibilityUseCase(repository)
+ }
+
+ @Provides
+ @ViewModelScoped
+ fun provideFindTokenByContractAddressUseCase(
+ tokensListRepository: TokensListRepository,
+ ): FindTokenByContractAddressUseCase {
+ return FindTokenByContractAddressUseCase(repository = tokensListRepository)
+ }
+
+ @Provides
+ @ViewModelScoped
+ fun provideValidateContractAddressUseCase(
+ tokensListRepository: TokensListRepository,
+ ): ValidateContractAddressUseCase {
+ return ValidateContractAddressUseCase(tokensListRepository = tokensListRepository)
+ }
+
+ @Provides
+ @ViewModelScoped
+ fun provideAreTokensSupportedByNetworkUseCase(
+ repository: NetworksCompatibilityRepository,
+ ): AreTokensSupportedByNetworkUseCase {
+ return AreTokensSupportedByNetworkUseCase(repository = repository)
+ }
+
+ @Provides
+ @ViewModelScoped
+ fun provideGetNetworksSupportedByWallet(
+ repository: NetworksCompatibilityRepository,
+ ): GetNetworksSupportedByWallet {
+ return GetNetworksSupportedByWallet(repository = repository)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt
index ead5fca293..5429ab3030 100644
--- a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt
+++ b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt
@@ -2,6 +2,8 @@ package com.tangem.tap.di.domain
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.demo.IsDemoCardUseCase
+import com.tangem.domain.transaction.TransactionRepository
+import com.tangem.domain.transaction.usecase.CreateTransactionUseCase
import com.tangem.domain.transaction.usecase.GetFeeUseCase
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
import com.tangem.domain.walletmanager.WalletManagersFacade
@@ -38,4 +40,10 @@ internal object TransactionDomainModule {
walletManagersFacade = walletManagersFacade,
)
}
+
+ @Provides
+ @ViewModelScoped
+ fun provideCreateTransactionUseCase(transactionRepository: TransactionRepository): CreateTransactionUseCase {
+ return CreateTransactionUseCase(transactionRepository)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt
index 236f6e9b8f..c7f58a8226 100644
--- a/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt
+++ b/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt
@@ -3,8 +3,10 @@ package com.tangem.tap.di.domain
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.legacy.WalletsStateHolder
+import com.tangem.domain.wallets.repository.WalletAddressServiceRepository
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.domain.wallets.usecase.*
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@@ -91,4 +93,36 @@ internal object WalletsDomainModule {
fun providesShouldSaveUserWalletsUseCase(walletsRepository: WalletsRepository): ShouldSaveUserWalletsUseCase {
return ShouldSaveUserWalletsUseCase(walletsRepository = walletsRepository)
}
+
+ @Provides
+ @ViewModelScoped
+ fun providesValidateWalletAddressUseCase(
+ walletAddressServiceRepository: WalletAddressServiceRepository,
+ dispatchers: CoroutineDispatcherProvider,
+ ): ValidateWalletAddressUseCase {
+ return ValidateWalletAddressUseCase(
+ walletAddressServiceRepository = walletAddressServiceRepository,
+ dispatchers = dispatchers,
+ )
+ }
+
+ @Provides
+ @ViewModelScoped
+ fun providesValidateWalletMemoUseCase(
+ walletAddressServiceRepository: WalletAddressServiceRepository,
+ ): ValidateWalletMemoUseCase {
+ return ValidateWalletMemoUseCase(walletAddressServiceRepository = walletAddressServiceRepository)
+ }
+
+ @Provides
+ @ViewModelScoped
+ fun providesParseSharedAddressUseCase(
+ walletAddressServiceRepository: WalletAddressServiceRepository,
+ dispatchers: CoroutineDispatcherProvider,
+ ): ParseSharedAddressUseCase {
+ return ParseSharedAddressUseCase(
+ walletAddressServiceRepository = walletAddressServiceRepository,
+ dispatchers = dispatchers,
+ )
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt
index ea5bd2e3aa..33ea89804c 100644
--- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt
+++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt
@@ -25,9 +25,8 @@ import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
import com.tangem.operations.pins.SetUserCodeCommand
import com.tangem.operations.usersetttings.SetUserCodeRecoveryAllowedTask
-import com.tangem.tap.common.analytics.events.Basic
+import com.tangem.core.analytics.models.Basic
import com.tangem.tap.derivationsFinder
-import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask
import com.tangem.tap.domain.tasks.product.CreateProductWalletTask
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
import com.tangem.tap.domain.tasks.product.ResetToFactorySettingsTask
@@ -126,15 +125,6 @@ class TangemSdkManager(
}
}
- suspend fun createWallet(cardId: String?): CompletionResult {
- return runTaskAsyncReturnOnMain(
- CreateWalletAndRescanTask(),
- cardId,
- initialMessage = Message(resources.getString(R.string.initial_message_create_wallet_body)),
- )
- .map { CardDTO(it) }
- }
-
suspend fun derivePublicKeys(
cardId: String?,
derivations: Map>,
@@ -267,6 +257,9 @@ class TangemSdkManager(
filter = CardFilter(
allowedCardTypes = FirmwareVersion.FirmwareType.values().toList(),
maxFirmwareVersion = FirmwareVersion(major = 6, minor = 33),
+ batchIdFilter = CardFilter.Companion.ItemFilter.Deny(
+ items = setOf("0027", "0030", "0031", "0035", "DA88"),
+ ),
),
)
}
diff --git a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt
index 8ac459bf2b..70b2540317 100644
--- a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt
+++ b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt
@@ -26,7 +26,6 @@ sealed class TapError(
val stateError: String,
) : TapError(R.string.common_custom_string, listOf("Unsupported state: $stateError"))
- object UnknownBlockchain : TapError(R.string.wallet_error_unsupported_blockchain_subtitle)
object NoInternetConnection : TapError(R.string.wallet_notification_no_internet)
object AmountExceedsBalance : TapError(R.string.send_validation_amount_exceeds_balance)
data class AmountLowerExistentialDeposit(
@@ -41,7 +40,6 @@ sealed class TapError(
object DustChange : TapError(R.string.send_error_dust_change)
sealed class WalletManager {
- object CreationError : CustomError(customMessage = "Can't create wallet manager")
class NoAccountError(amountToCreateAccount: String) : CustomError(amountToCreateAccount)
class InternalError(message: String) : CustomError(message)
object BlockchainIsUnreachableTryLater : TapError(R.string.wallet_balance_blockchain_unreachable_try_later)
diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
index 9edc4ee417..8d9ba42e6a 100644
--- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
+++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
@@ -4,39 +4,27 @@ import com.tangem.blockchain.common.BlockchainSdkConfig
import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.common.WalletManagerFactory
-import com.tangem.common.doOnFailure
-import com.tangem.common.doOnSuccess
import com.tangem.core.analytics.Analytics
import com.tangem.datasource.config.ConfigManager
-import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.operations.attestation.Attestation
-import com.tangem.tap.*
-import com.tangem.tap.common.analytics.events.Basic
-import com.tangem.tap.common.extensions.dispatchOnMain
-import com.tangem.tap.common.extensions.dispatchWithMain
+import com.tangem.core.analytics.models.Basic
import com.tangem.tap.common.extensions.setContext
-import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
-import com.tangem.tap.domain.walletStores.WalletStoresError
-import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
-import com.tangem.tap.domain.walletconnect2.domain.models.Account
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
import com.tangem.tap.features.disclaimer.createDisclaimer
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
-import com.tangem.tap.features.wallet.redux.WalletAction
-import com.tangem.tap.proxy.redux.DaggerGraphState
+import com.tangem.tap.store
+import com.tangem.tap.tangemSdkManager
import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
-import org.rekotlin.Store
-import timber.log.Timber
class TapWalletManager(
private val dispatchers: CoroutineDispatcherProvider = AppCoroutineDispatcherProvider(),
@@ -55,15 +43,15 @@ class TapWalletManager(
val walletManagerFactory: WalletManagerFactory
by lazy { WalletManagerFactory(blockchainSdkConfig) }
- suspend fun onWalletSelected(userWallet: UserWallet, refresh: Boolean, sendAnalyticsEvent: Boolean) {
+ suspend fun onWalletSelected(userWallet: UserWallet, sendAnalyticsEvent: Boolean) {
// If a previous job was running, it gets cancelled before the new one starts,
// ensuring that only one job is active at any given time.
loadUserWalletDataJob = CoroutineScope(dispatchers.io)
- .launch { loadUserWalletData(userWallet, refresh, sendAnalyticsEvent) }
+ .launch { loadUserWalletData(userWallet, sendAnalyticsEvent) }
.also { it.join() }
}
- private suspend fun loadUserWalletData(userWallet: UserWallet, refresh: Boolean, sendAnalyticsEvent: Boolean) {
+ private suspend fun loadUserWalletData(userWallet: UserWallet, sendAnalyticsEvent: Boolean) {
Analytics.setContext(userWallet.scanResponse)
if (sendAnalyticsEvent) {
Analytics.send(Basic.WalletOpened())
@@ -78,114 +66,11 @@ class TapWalletManager(
withMainContext {
// Order is important
store.dispatch(DisclaimerAction.SetDisclaimer(card.createDisclaimer()))
- store.dispatchWalletAction(action = WalletAction.UserWalletChanged(userWallet))
- store.dispatchWalletAction(
- action = WalletAction.UpdateCanSaveUserWallets(
- canSaveUserWallets = store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
- .shouldSaveUserWalletsSync(),
- ),
- )
store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse))
store.dispatch(WalletConnectAction.ResetState)
store.dispatch(GlobalAction.SaveScanResponse(scanResponse))
store.dispatch(WalletConnectAction.RestoreSessions(scanResponse))
store.dispatch(GlobalAction.SetIfCardVerifiedOnline(!attestationFailed))
- store.dispatchWalletAction(action = WalletAction.Warnings.CheckIfNeeded)
- }
-
- val walletFeatureToggles = store.state.daggerGraphState.get(DaggerGraphState::walletFeatureToggles)
- if (!walletFeatureToggles.isRedesignedScreenEnabled) {
- setupWalletConnectV2(userWallet)
- loadData(userWallet = userWallet, refresh = refresh)
- }
- }
-
- private fun Store.dispatchWalletAction(action: WalletAction) {
- val walletFeatureToggles = state.daggerGraphState.get(DaggerGraphState::walletFeatureToggles)
-
- if (!walletFeatureToggles.isRedesignedScreenEnabled) {
- dispatch(action = action)
- }
- }
-
- private fun setupWalletConnectV2(userWallet: UserWallet) {
- val cardId = if (userWallet.scanResponse.card.backupStatus?.isActive != true) {
- userWallet.cardId
- } else { // if wallet has backup, any card from wallet can be used to sign
- null
- }
- scope.launch {
- val wcInteractor = store.state.daggerGraphState.walletConnectInteractor ?: return@launch
- wcInteractor.startListening(
- userWalletId = userWallet.walletId.stringValue,
- cardId = cardId,
- )
- }
- }
-
- suspend fun loadData(userWallet: UserWallet, refresh: Boolean = false) {
- walletStoresManager.fetch(userWallet, refresh)
- .doOnSuccess {
- Timber.d("Wallet stores fetched for ${userWallet.walletId}")
- store.dispatchOnMain(WalletAction.LoadData.Success)
- store.state.globalState.topUpController?.loadDataSuccess()
- store.dispatchWithMain(WalletAction.Warnings.CheckHashesCount.VerifyOnlineIfNeeded)
-
- val wcInteractor = store.state.daggerGraphState.walletConnectInteractor
- wcInteractor?.setUserChains(getAccountsForWc(wcInteractor))
- }
- .doOnFailure { error ->
- val errorAction = when (error) {
- is WalletStoresError -> when (error) {
- is WalletStoresError.FetchFiatRatesError -> WalletAction.LoadData.Failure(error = null)
- is WalletStoresError.UpdateWalletManagerTokensError -> WalletAction.LoadData.Failure(
- error = TapError.WalletManager.InternalError(
- message = error.cause.localizedMessage ?: error.customMessage,
- ),
- )
- is WalletStoresError.WalletManagerNotCreated -> WalletAction.LoadData.Failure(
- error = TapError.WalletManager.CreationError,
- )
- is WalletStoresError.UnknownBlockchain -> WalletAction.LoadData.Failure(
- error = TapError.UnknownBlockchain,
- )
- is WalletStoresError.NoInternetConnection -> WalletAction.LoadData.Failure(
- error = TapError.NoInternetConnection,
- )
- }
- else -> WalletAction.LoadData.Failure(error = null)
- }
-
- Timber.e(error, "Wallet stores fetching failed for ${userWallet.walletId}")
-
- store.dispatchOnMain(errorAction)
- }
- }
-
- private suspend fun getAccountsForWc(wcInteractor: WalletConnectInteractor): List {
- val walletManagerToggles = store.state.daggerGraphState
- .get(DaggerGraphState::walletFeatureToggles)
- val walletManagers = if (walletManagerToggles.isRedesignedScreenEnabled) {
- val walletManagerFacade = store.state.daggerGraphState
- .get(DaggerGraphState::walletManagersFacade)
- val userWallet = userWalletsListManager.selectedUserWalletSync ?: return emptyList()
- walletManagerFacade.getStoredWalletManagers(userWallet.walletId)
- } else {
- store.state.walletState.walletManagers
- }
-
- return walletManagers.mapNotNull {
- val wallet = it.wallet
- val chainId = wcInteractor.blockchainHelper.networkIdToChainIdOrNull(
- wallet.blockchain.toNetworkId(),
- )
- chainId?.let {
- Account(
- chainId,
- wallet.address,
- wallet.publicKey.derivationPath?.rawPath,
- )
- }
}
}
diff --git a/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivationsRepository.kt b/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivationsRepository.kt
new file mode 100644
index 0000000000..4b2f3852b6
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivationsRepository.kt
@@ -0,0 +1,80 @@
+package com.tangem.tap.domain.card
+
+import com.tangem.common.doOnFailure
+import com.tangem.common.doOnSuccess
+import com.tangem.common.extensions.ByteArrayKey
+import com.tangem.crypto.hdWallet.DerivationPath
+import com.tangem.datasource.local.userwallet.UserWalletsStore
+import com.tangem.domain.card.repository.DerivationsRepository
+import com.tangem.domain.tokens.model.CryptoCurrency
+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.TangemSdkManager
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import com.tangem.utils.coroutines.runCatching
+import timber.log.Timber
+
+internal typealias Derivations = Map>
+private typealias DerivedKeys = Map
+
+internal class DefaultDerivationsRepository(
+ private val tangemSdkManager: TangemSdkManager,
+ private val userWalletsStore: UserWalletsStore,
+ private val dispatchers: CoroutineDispatcherProvider,
+) : DerivationsRepository {
+
+ override suspend fun derivePublicKeys(userWalletId: UserWalletId, currencies: List) {
+ val userWallet = userWalletsStore.getSyncOrNull(userWalletId) ?: error("User wallet not found")
+
+ if (!userWallet.scanResponse.card.settings.isHDWalletAllowed) {
+ Timber.d("Nothing to derive")
+ return
+ }
+
+ val derivations = MissedDerivationsFinder(scanResponse = userWallet.scanResponse)
+ .find(currencies)
+ .ifEmpty {
+ Timber.d("Nothing to derive")
+ return
+ }
+
+ tangemSdkManager.derivePublicKeys(cardId = null, derivations = derivations)
+ .doOnSuccess { response ->
+ updatePublicKeys(userWalletId = userWalletId, keys = response.entries).fold(
+ onSuccess = { return },
+ onFailure = { throw it },
+ )
+ }
+ .doOnFailure { throw it }
+
+ error("This code should never be reached")
+ }
+
+ private suspend fun updatePublicKeys(userWalletId: UserWalletId, keys: DerivedKeys): Result {
+ return runCatching(dispatchers.io) {
+ userWalletsStore.update(
+ userWalletId = userWalletId,
+ update = { userWallet -> userWallet.updateDerivedKeys(keys) },
+ )
+ }
+ }
+
+ private fun UserWallet.updateDerivedKeys(keys: DerivedKeys): UserWallet {
+ return copy(
+ scanResponse = scanResponse.copy(
+ derivedKeys = getUpdatedDerivedKeys(oldKeys = scanResponse.derivedKeys, newKeys = keys),
+ ),
+ )
+ }
+
+ private fun getUpdatedDerivedKeys(oldKeys: DerivedKeys, newKeys: DerivedKeys): DerivedKeys {
+ return (oldKeys.keys + newKeys.keys).toSet()
+ .associateWith { walletKey ->
+ val oldDerivations = ExtendedPublicKeysMap(oldKeys[walletKey] ?: emptyMap())
+ val newDerivations = newKeys[walletKey] ?: ExtendedPublicKeysMap(emptyMap())
+
+ ExtendedPublicKeysMap(oldDerivations + newDerivations)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivePublicKeysUseCase.kt b/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivePublicKeysUseCase.kt
index d402c97a7c..a09df2969a 100644
--- a/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivePublicKeysUseCase.kt
+++ b/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivePublicKeysUseCase.kt
@@ -8,12 +8,15 @@ import com.tangem.common.doOnSuccess
import com.tangem.common.extensions.ByteArrayKey
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.domain.card.DerivePublicKeysUseCase
+import com.tangem.domain.card.repository.DerivationsRepository
+import com.tangem.domain.tokens.model.CryptoCurrency
+import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.tap.domain.TangemSdkManager
-// TODO: [REDACTED_JIRA]
internal class DefaultDerivePublicKeysUseCase(
private val tangemSdkManager: TangemSdkManager,
+ private val derivationsRepository: DerivationsRepository,
) : DerivePublicKeysUseCase {
override suspend fun invoke(
@@ -26,4 +29,13 @@ internal class DefaultDerivePublicKeysUseCase(
return Unit.left()
}
+
+ override suspend fun invoke(
+ userWalletId: UserWalletId,
+ currencies: List,
+ ): Either {
+ return Either.catch {
+ derivationsRepository.derivePublicKeys(userWalletId, currencies)
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/card/MissedDerivationsFinder.kt b/app/src/main/java/com/tangem/tap/domain/card/MissedDerivationsFinder.kt
new file mode 100644
index 0000000000..97c0a7bf8f
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/domain/card/MissedDerivationsFinder.kt
@@ -0,0 +1,118 @@
+package com.tangem.tap.domain.card
+
+import com.tangem.blockchain.blockchains.cardano.CardanoUtils
+import com.tangem.blockchain.common.Blockchain
+import com.tangem.common.card.EllipticCurve
+import com.tangem.common.extensions.ByteArrayKey
+import com.tangem.common.extensions.toMapKey
+import com.tangem.crypto.hdWallet.DerivationPath
+import com.tangem.domain.common.configs.CardConfig
+import com.tangem.domain.common.util.derivationStyleProvider
+import com.tangem.domain.models.scan.KeyWalletPublicKey
+import com.tangem.domain.models.scan.ScanResponse
+import com.tangem.domain.tokens.model.CryptoCurrency
+import com.tangem.operations.derivation.ExtendedPublicKeysMap
+
+private typealias DerivationData = Pair>
+
+/**
+ * Finder of missed derivations
+ *
+ * @property scanResponse scanning response
+ *
+[REDACTED_AUTHOR]
+ */
+internal class MissedDerivationsFinder(private val scanResponse: ScanResponse) {
+
+ /** Find missed derivations for given currencies [currencies] */
+ fun find(currencies: List): Derivations {
+ return buildMap> {
+ currencies
+ .mapToNewDerivations()
+ .forEach { data ->
+ val current = this[data.first]
+ if (current != null) {
+ current.addAll(data.second)
+ current.distinct()
+ } else {
+ this[data.first] = data.second.toMutableList()
+ }
+ }
+ }
+ }
+
+ private fun List.mapToNewDerivations(): List {
+ val config = CardConfig.createConfig(scanResponse.card)
+ return mapNotNull { currency ->
+ val blockchain = Blockchain.fromId(id = currency.network.id.value)
+ val curve = config.primaryCurve(blockchain) ?: return@mapNotNull null
+
+ findNewDerivations(curve = curve, scanResponse = scanResponse, currency = currency)
+ }
+ }
+
+ private fun findNewDerivations(
+ curve: EllipticCurve,
+ scanResponse: ScanResponse,
+ currency: CryptoCurrency,
+ ): DerivationData? {
+ val wallet = scanResponse.card.wallets.firstOrNull { it.curve == curve } ?: return null
+ val publicKey = wallet.publicKey.toMapKey()
+
+ val derivationCandidates = currency
+ .getDerivationCandidates(curve)
+ .ifEmpty { return null }
+ .filterAlreadyDerivedKeys(publicKey)
+ .ifEmpty { return null }
+
+ return publicKey to derivationCandidates
+ }
+
+ private fun CryptoCurrency.getDerivationCandidates(curve: EllipticCurve): List {
+ val blockchain = Blockchain.fromId(id = network.id.value)
+
+ return buildList {
+ add(blockchain.getDerivationPath(curve = curve))
+ add(blockchain.getCustomDerivationPath(curve = curve, currency = this@getDerivationCandidates))
+ add(blockchain.getCardanoDerivationPathIfNeeded(currency = this@getDerivationCandidates))
+ }
+ .filterNotNull()
+ .distinct()
+ }
+
+ private fun Blockchain.getDerivationPath(curve: EllipticCurve): DerivationPath? {
+ return if (getSupportedCurves().contains(curve)) {
+ derivationPath(style = scanResponse.derivationStyleProvider.getDerivationStyle())
+ } else {
+ null
+ }
+ }
+
+ private fun Blockchain.getCustomDerivationPath(curve: EllipticCurve, currency: CryptoCurrency): DerivationPath? {
+ return if (getSupportedCurves().contains(curve)) {
+ currency.network.derivationPath.value?.let(::DerivationPath)
+ } else {
+ null
+ }
+ }
+
+ private fun Blockchain.getCardanoDerivationPathIfNeeded(currency: CryptoCurrency): DerivationPath? {
+ return if (currency is CryptoCurrency.Coin && this == Blockchain.Cardano) {
+ currency.network.derivationPath.value?.let {
+ CardanoUtils.extendedDerivationPath(derivationPath = DerivationPath(it))
+ }
+ } else {
+ null
+ }
+ }
+
+ private fun List.filterAlreadyDerivedKeys(publicKey: KeyWalletPublicKey): List {
+ val alreadyDerivedPaths = getAlreadyDerivedKeys(publicKey)
+ return filterNot(alreadyDerivedPaths::contains)
+ }
+
+ private fun getAlreadyDerivedKeys(publicKey: KeyWalletPublicKey): List {
+ val extendedPublicKeysMap = scanResponse.derivedKeys[publicKey] ?: ExtendedPublicKeysMap(emptyMap())
+ return extendedPublicKeysMap.keys.toList()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt
index a36e254ee7..2f8f892e51 100644
--- a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt
+++ b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt
@@ -51,14 +51,12 @@ data class WarningMessage(
}
enum class Location {
- @Json(name = "main")
- MainScreen,
@Json(name = "send")
SendScreen,
}
enum class Origin {
- Local, Remote
+ Remote,
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt
index f1345d6989..caa4125ff7 100644
--- a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt
+++ b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt
@@ -1,26 +1,17 @@
package com.tangem.tap.domain.configurable.warningMessage
import com.tangem.blockchain.common.Blockchain
-import com.tangem.utils.extensions.removeBy
-import com.tangem.wallet.R
import java.util.concurrent.CopyOnWriteArrayList
/**
[REDACTED_AUTHOR]
*/
-// TODO: Delete with WalletFeatureToggles
-@Deprecated(message = "Used only in old wallet screen")
+// TODO: Delete with SendFeatureToggles
+@Deprecated(message = "Used only in old send screen")
class WarningMessagesManager {
private val warningsList = CopyOnWriteArrayList()
- fun addWarning(warning: WarningMessage) {
- if (findWarning(warning) == null) {
- warningsList.add(warning)
- sortByPriority()
- }
- }
-
fun getWarnings(location: WarningMessage.Location, blockchains: List): List {
return warningsList.filter { message ->
val messageBlockchains = message.blockchainList
@@ -45,131 +36,7 @@ class WarningMessagesManager {
}
}
- fun removeWarnings(origin: WarningMessage.Origin) {
- warningsList.removeBy { it.origin == origin }
- sortByPriority()
- }
-
- fun removeWarnings(messageRes: Int) {
- warningsList.removeBy { it.messageResId == messageRes }
- }
-
- fun containsWarning(warning: WarningMessage) = warning in warningsList
-
- private fun sortByPriority() {
- warningsList.sortBy { it.priority.ordinal }
- }
-
private fun findWarning(warning: WarningMessage): WarningMessage? {
return warningsList.firstOrNull { it == warning }
}
-
- companion object {
- const val REMAINING_SIGNATURES_WARNING = 10
-
- val devCardWarning = WarningMessage(
- title = "",
- message = "",
- type = WarningMessage.Type.Permanent,
- priority = WarningMessage.Priority.Critical,
- location = listOf(WarningMessage.Location.MainScreen),
- blockchains = null,
- titleResId = R.string.common_warning,
- // messageResId = R.string.alert_developer_card,
- origin = WarningMessage.Origin.Local,
- )
-
- val alreadySignedHashesWarning = WarningMessage(
- title = "",
- message = "",
- type = WarningMessage.Type.Temporary,
- priority = WarningMessage.Priority.Info,
- location = listOf(WarningMessage.Location.MainScreen),
- blockchains = null,
- titleResId = R.string.common_warning,
- // messageResId = R.string.alert_card_signed_transactions,
- origin = WarningMessage.Origin.Local,
- )
-
- val signedHashesMultiWalletWarning = WarningMessage(
- title = "",
- message = "",
- type = WarningMessage.Type.Temporary,
- priority = WarningMessage.Priority.Info,
- location = listOf(WarningMessage.Location.MainScreen),
- blockchains = null,
- // titleResId = R.string.warning_important_security_info,
- // messageResId = R.string.warning_signed_tx_previously,
- origin = WarningMessage.Origin.Local,
- buttonTextId = R.string.warning_button_learn_more,
- titleFormatArg = "\u26A0",
- )
-
- val appRatingWarning = WarningMessage(
- title = "",
- message = "",
- type = WarningMessage.Type.AppRating,
- priority = WarningMessage.Priority.Info,
- location = listOf(WarningMessage.Location.MainScreen),
- blockchains = null,
- titleResId = R.string.warning_rate_app_title,
- messageResId = R.string.warning_rate_app_message,
- origin = WarningMessage.Origin.Local,
- )
-
- val onlineVerificationFailed = WarningMessage(
- title = "",
- message = "",
- type = WarningMessage.Type.Permanent,
- priority = WarningMessage.Priority.Critical,
- location = listOf(WarningMessage.Location.MainScreen),
- blockchains = null,
- titleResId = R.string.warning_failed_to_verify_card_title,
- messageResId = R.string.warning_failed_to_verify_card_message,
- origin = WarningMessage.Origin.Local,
- )
-
- val testCardWarning = WarningMessage(
- title = "",
- message = "",
- type = WarningMessage.Type.TestCard,
- priority = WarningMessage.Priority.Critical,
- location = listOf(WarningMessage.Location.MainScreen, WarningMessage.Location.SendScreen),
- blockchains = null,
- titleResId = R.string.common_warning,
- messageResId = R.string.warning_testnet_card_message,
- origin = WarningMessage.Origin.Local,
- )
-
- val demoCardWarning = WarningMessage(
- title = "",
- message = "",
- type = WarningMessage.Type.Permanent,
- priority = WarningMessage.Priority.Critical,
- location = listOf(WarningMessage.Location.MainScreen),
- blockchains = null,
- titleResId = R.string.common_warning,
- // messageResId = R.string.alert_demo_message,
- origin = WarningMessage.Origin.Local,
- )
-
- fun remainingSignaturesNotEnough(remainingSignatures: Int): WarningMessage {
- return WarningMessage(
- title = "",
- message = "",
- type = WarningMessage.Type.Permanent,
- priority = WarningMessage.Priority.Critical,
- location = listOf(WarningMessage.Location.MainScreen),
- blockchains = null,
- titleResId = R.string.common_warning,
- // messageResId = R.string.warning_low_signatures_format,
- origin = WarningMessage.Origin.Local,
- messageFormatArg = remainingSignatures.toString(),
- )
- }
-
- // fun isAlreadySignedHashesWarning(warning: WarningMessage): Boolean {
- // return warning.messageResId == R.string.alert_card_signed_transactions
- // }
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt b/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt
index 363565bf3e..c71548c0bd 100644
--- a/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt
+++ b/app/src/main/java/com/tangem/tap/domain/extensions/Card.kt
@@ -9,17 +9,6 @@ import com.tangem.domain.userwallets.Artwork
import com.tangem.operations.attestation.CardVerifyAndGetInfo
import com.tangem.operations.attestation.OnlineCardVerifier
-val CardDTO.remainingSignatures: Int?
- get() = this.wallets.firstOrNull()?.remainingSignatures
-
-val CardDTO.isHdWalletAllowedByApp: Boolean
- get() = settings.isHDWalletAllowed
-
-@Suppress("UnnecessaryParentheses")
-fun CardDTO.hasSignedHashes(): Boolean {
- return wallets.any { (it.totalSignedHashes ?: 0) > 0 }
-}
-
fun CardDTO.signedHashesCount(): Int {
return wallets.sumOf { it.totalSignedHashes ?: 0 }
}
diff --git a/app/src/main/java/com/tangem/tap/domain/extensions/Token.kt b/app/src/main/java/com/tangem/tap/domain/extensions/Token.kt
deleted file mode 100644
index 6963ed3682..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/extensions/Token.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.tangem.tap.domain.extensions
-
-import com.tangem.blockchain.common.Token
-
-/**
-[REDACTED_AUTHOR]
- */
-
-private val tokenCustomIconUrls = mutableMapOf()
-
-fun Token.getCustomIconUrl(): String? {
- return tokenCustomIconUrls[this.contractAddress]
-}
-
-fun Token.setCustomIconUrl(url: String) {
- tokenCustomIconUrls[this.contractAddress] = url
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/model/Currency.kt b/app/src/main/java/com/tangem/tap/domain/model/Currency.kt
new file mode 100644
index 0000000000..5992c61d6a
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/domain/model/Currency.kt
@@ -0,0 +1,64 @@
+package com.tangem.tap.domain.model
+
+import com.tangem.domain.common.BlockchainNetwork
+import com.tangem.domain.features.addCustomToken.CustomCurrency
+import com.tangem.tap.common.redux.global.CryptoCurrencyName
+import com.tangem.blockchain.common.Blockchain as SdkBlockchain
+import com.tangem.blockchain.common.Token as SdkToken
+
+sealed interface Currency {
+ val blockchain: SdkBlockchain
+ val currencySymbol: CryptoCurrencyName
+ val derivationPath: String?
+ val decimals
+ get() = when (this) {
+ is Blockchain -> blockchain.decimals()
+ is Token -> token.decimals
+ }
+
+ data class Token(
+ val token: SdkToken,
+ override val blockchain: SdkBlockchain,
+ override val derivationPath: String?,
+ ) : Currency {
+ override val currencySymbol = token.symbol
+ }
+
+ data class Blockchain(
+ override val blockchain: SdkBlockchain,
+ override val derivationPath: String?,
+ ) : Currency {
+ override val currencySymbol: CryptoCurrencyName = blockchain.currency
+ }
+
+ companion object {
+ fun fromBlockchainNetwork(blockchainNetwork: BlockchainNetwork, token: SdkToken? = null): Currency {
+ return if (token != null) {
+ Token(
+ token = token,
+ blockchain = blockchainNetwork.blockchain,
+ derivationPath = blockchainNetwork.derivationPath,
+ )
+ } else {
+ Blockchain(
+ blockchain = blockchainNetwork.blockchain,
+ derivationPath = blockchainNetwork.derivationPath,
+ )
+ }
+ }
+
+ fun fromCustomCurrency(customCurrency: CustomCurrency): Currency {
+ return when (customCurrency) {
+ is CustomCurrency.CustomBlockchain -> Blockchain(
+ blockchain = customCurrency.network,
+ derivationPath = customCurrency.derivationPath?.rawPath,
+ )
+ is CustomCurrency.CustomToken -> Token(
+ token = customCurrency.token,
+ blockchain = customCurrency.network,
+ derivationPath = customCurrency.derivationPath?.rawPath,
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt b/app/src/main/java/com/tangem/tap/domain/model/PendingTransaction.kt
similarity index 55%
rename from app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt
rename to app/src/main/java/com/tangem/tap/domain/model/PendingTransaction.kt
index e2b74e5ebd..c4a810e12e 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt
+++ b/app/src/main/java/com/tangem/tap/domain/model/PendingTransaction.kt
@@ -1,14 +1,8 @@
-package com.tangem.tap.features.wallet.models
+package com.tangem.tap.domain.model
-import com.tangem.blockchain.common.Amount
-import com.tangem.blockchain.common.AmountType
-import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.TransactionData
import com.tangem.blockchain.common.TransactionStatus
import com.tangem.blockchain.common.Wallet
-import com.tangem.blockchain.extensions.isAboveZero
-import com.tangem.tap.common.extensions.toFormattedString
-import java.math.BigDecimal
data class PendingTransaction(
val transactionData: TransactionData,
@@ -20,10 +14,6 @@ data class PendingTransaction(
PendingTransactionType.Unknown -> null
}
- val amountValue: BigDecimal? = transactionData.amount.value
-
- val amountValueUi: String? = amountValue?.toFormattedString(transactionData.amount.decimals)
-
val currency: String = transactionData.amount.currencySymbol
private fun nullIfUnknown(address: String): String? = if (address == "unknown") null else address
@@ -46,15 +36,6 @@ fun List.toPendingTransactions(walletAddress: String): List.filterByCoin(): List {
- return this.filter { it.transactionData.amount.type == AmountType.Coin }
-}
-
-fun TransactionData.toPendingTransactionForToken(token: Token, walletAddress: String): PendingTransaction? {
- if (this.amount.currencySymbol != token.symbol) return null
- return this.toPendingTransaction(walletAddress)
-}
-
fun Wallet.getPendingTransactions(type: PendingTransactionType? = null): List {
val txs = recentTransactions.toPendingTransactions(address)
return when (type) {
@@ -63,24 +44,6 @@ fun Wallet.getPendingTransactions(type: PendingTransactionType? = null): List {
- return recentTransactions.mapNotNull { it.toPendingTransactionForToken(token, address) }
-}
-
fun Wallet.hasPendingTransactions(): Boolean {
return getPendingTransactions().isNotEmpty()
-}
-
-fun Wallet.getSendableAmounts(): List {
- return amounts.values
- .filter { it.type != AmountType.Reserve }
- .filter { it.isAboveZero() }
-}
-
-fun Wallet.hasSendableAmounts(): Boolean {
- return getSendableAmounts().isNotEmpty()
-}
-
-fun Wallet.isSendableAmount(type: AmountType): Boolean {
- return amounts[type]?.isAboveZero() == true
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/model/TotalFiatBalance.kt b/app/src/main/java/com/tangem/tap/domain/model/TotalFiatBalance.kt
deleted file mode 100644
index 0180d85435..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/model/TotalFiatBalance.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.tangem.tap.domain.model
-
-import java.math.BigDecimal
-
-/**
- * Represents fiat balance of [WalletStoreModel] list
- * @property amount Amount of the total balance
- * */
-sealed interface TotalFiatBalance {
- val amount: BigDecimal?
-
- object Loading : TotalFiatBalance {
- override val amount: BigDecimal? = null
- }
-
- object Failed : TotalFiatBalance {
- override val amount: BigDecimal? = null
- }
-
- data class Loaded(
- override val amount: BigDecimal,
- val isWarning: Boolean,
- ) : TotalFiatBalance
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/model/WalletAddressData.kt b/app/src/main/java/com/tangem/tap/domain/model/WalletAddressData.kt
new file mode 100644
index 0000000000..a24fe98346
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/domain/model/WalletAddressData.kt
@@ -0,0 +1,10 @@
+package com.tangem.tap.domain.model
+
+import com.tangem.blockchain.common.address.AddressType
+
+internal data class WalletAddressData(
+ val address: String,
+ val type: AddressType,
+ val shareUrl: String,
+ val exploreUrl: String,
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/model/WalletDataModel.kt b/app/src/main/java/com/tangem/tap/domain/model/WalletDataModel.kt
deleted file mode 100644
index fc0acca07c..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/model/WalletDataModel.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.tangem.tap.domain.model
-
-import com.tangem.blockchain.common.address.AddressType
-import com.tangem.tap.domain.model.WalletDataModel.AddressData
-import com.tangem.tap.domain.model.WalletDataModel.Status
-import com.tangem.tap.features.wallet.models.Currency
-import com.tangem.tap.features.wallet.models.PendingTransaction
-import java.math.BigDecimal
-
-/**
- * Contains info about wallet store currency
- * @param currency Wallet's [Currency]
- * @param status Wallet's [Status], represents current status of that currency
- * @param walletAddresses List of wallet data [AddressData]
- * @param existentialDeposit Amount that must be held on currency's balance, if balance is below that amount all
- * founds will be destroyed. Null if currency don't have existential deposit
- * @param fiatRate Wallet's fiat rate, used to calculate fiat balance. Null if not provided
- * @param isCardSingleToken shows that [Currency] is a card token
- * @param isCustom shows that currency is a custom
- * */
-data class WalletDataModel(
- val currency: Currency,
- val status: Status,
- // FIXME: Left only selected wallet address here and move list of wallet addresses to WalletStoreModel
- val walletAddresses: WalletAddresses?,
- val existentialDeposit: BigDecimal?,
- val fiatRate: BigDecimal?,
- val isCardSingleToken: Boolean,
- val isCustom: Boolean,
-) {
-
- data class WalletAddresses(
- val selectedAddress: AddressData,
- val list: List,
- )
-
- data class AddressData(
- val address: String,
- val type: AddressType,
- val shareUrl: String,
- val exploreUrl: String,
- )
-
- /**
- * Represent current status of currency
- * @property amount Currency amount
- * @property pendingTransactions List of currency [PendingTransaction] sent in currency's blockchain
- * @property errorMessage Status error message, null if not provided
- * @property isErrorStatus true if current status is error status, false otherwise
- * */
- sealed class Status {
- open val amount: BigDecimal = BigDecimal.ZERO
- open val pendingTransactions: List = emptyList()
- open val errorMessage: String? = null
- open val isErrorStatus: Boolean = false
- }
-
- object Loading : Status()
-
- data class VerifiedOnline(
- override val amount: BigDecimal,
- ) : Status()
-
- data class TransactionInProgress(
- override val amount: BigDecimal,
- override val pendingTransactions: List,
- ) : Status()
-
- data class SameCurrencyTransactionInProgress(
- override val amount: BigDecimal,
- override val pendingTransactions: List,
- ) : Status()
-
- data class NoAccount(
- val amountToCreateAccount: BigDecimal?,
- ) : Status()
-
- data class Unreachable(
- override val errorMessage: String?,
- override val amount: BigDecimal = BigDecimal.ZERO,
- ) : Status() {
- override val isErrorStatus: Boolean = true
- }
-
- object MissedDerivation : Status() {
- override val isErrorStatus: Boolean = true
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/model/WalletStoreModel.kt b/app/src/main/java/com/tangem/tap/domain/model/WalletStoreModel.kt
deleted file mode 100644
index 99282954dc..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/model/WalletStoreModel.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.tangem.tap.domain.model
-
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.blockchain.common.WalletManager
-import com.tangem.crypto.hdWallet.DerivationPath
-import com.tangem.domain.common.BlockchainNetwork
-import com.tangem.domain.wallets.models.UserWalletId
-import com.tangem.tap.domain.model.WalletStoreModel.WalletRent
-import com.tangem.tap.features.wallet.models.Currency
-import java.math.BigDecimal
-
-// FIXME: Move list of wallet addresses from WalletDataModel to this class
-/**
- * Contains info about the blockchain and its currencies
- *
- * @param userWalletId ID of the associated [UserWallet]
- * @param blockchain [Blockchain] of this WalletStore
- * @param derivationPath [DerivationPath] of this store, null if the card does not support the
- * [HD Wallet](https://coinsutra.com/hd-wallets-deterministic-wallet/)
- * @param walletsData List of [WalletDataModel] which represents store's blockchain currency and tokens currencies
- * @param walletRent [WalletRent], null if store has no rent or currency balance is greater then
- * [WalletRent.exemptionAmount]
- * @param blockchainNetwork [BlockchainNetwork].
- * TODO: Remove after WalletMiddleware refactoring
- * @param walletManager [WalletManager], may be null if it fails to create this manager.
- * TODO: Remove after WalletMiddleware refactoring
- *
- * @property blockchainWalletData Returns the [WalletDataModel] of the blockchain of this wallet store
- * or throw [NoSuchElementException] if this wallet store not contains [WalletDataModel] of the blockchain
- * */
-data class WalletStoreModel(
- val userWalletId: UserWalletId,
- val blockchain: Blockchain,
- val derivationPath: DerivationPath?,
- val walletsData: List,
- val walletRent: WalletRent?,
- @Deprecated("Don't use it, will be removed")
- val blockchainNetwork: BlockchainNetwork,
- @Deprecated("Don't use it, will be removed")
- val walletManager: WalletManager?,
-) {
-
- val blockchainWalletData: WalletDataModel
- get() = walletsData.first { it.currency is Currency.Blockchain }
-
- /**
- * Represents wallet blockchain rent
- * @param rent Amount that will be charged in overtime if the blockchain does not have an amount greater than
- * the [WalletRent.exemptionAmount]
- * @param exemptionAmount Amount that should be on the blockchain balance not to pay rent
- * */
- data class WalletRent(
- val rent: BigDecimal,
- val exemptionAmount: BigDecimal,
- )
-
- // TODO: Remove the generated methods after blockchainNetwork and walletManager are removed from the model
- // region Generated
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is WalletStoreModel) return false
-
- if (userWalletId != other.userWalletId) return false
- if (blockchain != other.blockchain) return false
- if (derivationPath != other.derivationPath) return false
- if (walletsData != other.walletsData) return false
- if (walletRent != other.walletRent) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = userWalletId.hashCode()
- result = 31 * result + blockchain.hashCode()
- result = 31 * result + (derivationPath?.hashCode() ?: 0)
- result = 31 * result + walletsData.hashCode()
- result = 31 * result + (walletRent?.hashCode() ?: 0)
- return result
- }
-
- override fun toString(): String {
- return "WalletStoreModel(userWalletId=$userWalletId, blockchain=$blockchain, derivationPath=$derivationPath, " +
- "walletsData=$walletsData, walletRent=$walletRent)"
- }
- // endregion Generated
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt
deleted file mode 100644
index 7bd2f77fe1..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt
+++ /dev/null
@@ -1,188 +0,0 @@
-package com.tangem.tap.domain.model.builders
-
-import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.blockchain.common.Token
-import com.tangem.blockchain.common.Wallet
-import com.tangem.blockchain.common.WalletManager
-import com.tangem.blockchain.common.derivation.DerivationStyle
-import com.tangem.crypto.hdWallet.DerivationPath
-import com.tangem.domain.common.BlockchainNetwork
-import com.tangem.domain.common.util.cardTypesResolver
-import com.tangem.domain.common.util.derivationStyleProvider
-import com.tangem.domain.wallets.models.UserWallet
-import com.tangem.tap.domain.model.WalletDataModel
-import com.tangem.tap.domain.model.WalletStoreModel
-import com.tangem.tap.features.wallet.models.Currency
-import com.tangem.tap.features.wallet.redux.reducers.createAddressesData
-import java.math.BigDecimal
-
-interface WalletStoreBuilder {
- fun build(): WalletStoreModel
-
- interface BlockchainNetworkWalletStoreBuilder : WalletStoreBuilder {
- fun walletManager(walletManager: WalletManager?): WalletStoreBuilder
- }
-
- interface WalletMangerWalletStoreBuilder : WalletStoreBuilder
-
- companion object {
- operator fun invoke(
- userWallet: UserWallet,
- blockchainNetwork: BlockchainNetwork,
- ): BlockchainNetworkWalletStoreBuilder {
- return BlockchainNetworkWalletStoreBuilderImpl(userWallet, blockchainNetwork)
- }
-
- operator fun invoke(userWallet: UserWallet, walletManager: WalletManager): WalletMangerWalletStoreBuilder {
- return WalletMangerWalletStoreBuilderImpl(userWallet, walletManager)
- }
- }
-}
-
-private class BlockchainNetworkWalletStoreBuilderImpl(
- private val userWallet: UserWallet,
- private val blockchainNetwork: BlockchainNetwork,
-) : WalletStoreBuilder.BlockchainNetworkWalletStoreBuilder {
- private var walletManager: WalletManager? = null
-
- override fun walletManager(walletManager: WalletManager?) = this.apply {
- this.walletManager = walletManager
- }
-
- override fun build(): WalletStoreModel {
- val cardDerivationStyle = userWallet.scanResponse.derivationStyleProvider.getDerivationStyle()
- val blockchainWalletData = blockchainNetwork.getBlockchainWalletData(walletManager, cardDerivationStyle)
- val tokensWalletsData = blockchainNetwork.getTokensWalletsData(
- walletManager = walletManager,
- cardDerivationStyle = cardDerivationStyle,
- primaryToken = userWallet.scanResponse.cardTypesResolver.getPrimaryToken(),
- )
-
- return WalletStoreModel(
- userWalletId = userWallet.walletId,
- blockchain = blockchainNetwork.blockchain,
- derivationPath = blockchainNetwork.derivationPath?.let { DerivationPath(it) },
- walletsData = listOf(blockchainWalletData) + tokensWalletsData,
- walletRent = null,
- walletManager = walletManager,
- blockchainNetwork = blockchainNetwork,
- )
- }
-}
-
-private class WalletMangerWalletStoreBuilderImpl(
- private val userWallet: UserWallet,
- private val walletManager: WalletManager,
-) : WalletStoreBuilder.WalletMangerWalletStoreBuilder {
-
- override fun build(): WalletStoreModel {
- val wallet = walletManager.wallet
- val blockchainWalletData = wallet.blockchain.toBlockchainWalletData(walletManager)
- val tokenWalletsData = wallet.getTokens().firstOrNull()?.toTokenWalletData(
- walletManager = walletManager,
- primaryToken = userWallet.scanResponse.cardTypesResolver.getPrimaryToken(),
- )
-
- return WalletStoreModel(
- userWalletId = userWallet.walletId,
- blockchain = wallet.blockchain,
- derivationPath = wallet.publicKey.derivationPath,
- walletsData = listOf(blockchainWalletData) + listOfNotNull(tokenWalletsData),
- walletRent = null,
- walletManager = walletManager,
- blockchainNetwork = BlockchainNetwork.fromWalletManager(walletManager),
- )
- }
-}
-
-private fun BlockchainNetwork.getBlockchainWalletData(
- walletManager: WalletManager?,
- cardDerivationStyle: DerivationStyle?,
-): WalletDataModel {
- val currency = Currency.Blockchain(
- blockchain = blockchain,
- derivationPath = derivationPath,
- )
- return WalletDataModel(
- currency = currency,
- status = WalletDataModel.Loading,
- walletAddresses = walletManager?.wallet?.getWalletAddresses(),
- existentialDeposit = getExistentialDeposit(walletManager),
- fiatRate = null,
- isCardSingleToken = false,
- isCustom = currency.isCustomCurrency(cardDerivationStyle),
- )
-}
-
-private fun BlockchainNetwork.getTokensWalletsData(
- walletManager: WalletManager?,
- cardDerivationStyle: DerivationStyle?,
- primaryToken: Token?,
-): List {
- return this.tokens
- .map { token ->
- val currency = Currency.Token(
- token = token,
- blockchain = blockchain,
- derivationPath = derivationPath,
- )
- WalletDataModel(
- currency = currency,
- status = WalletDataModel.Loading,
- walletAddresses = walletManager?.wallet?.getWalletAddresses(),
- existentialDeposit = getExistentialDeposit(walletManager),
- fiatRate = null,
- isCardSingleToken = token == primaryToken,
- isCustom = currency.isCustomCurrency(cardDerivationStyle),
- )
- }
-}
-
-private fun Blockchain.toBlockchainWalletData(walletManager: WalletManager): WalletDataModel {
- val wallet = walletManager.wallet
- return WalletDataModel(
- currency = Currency.Blockchain(
- blockchain = this,
- derivationPath = wallet.publicKey.derivationPath?.rawPath,
- ),
- status = WalletDataModel.Loading,
- walletAddresses = wallet.getWalletAddresses(),
- existentialDeposit = getExistentialDeposit(walletManager),
- fiatRate = null,
- isCardSingleToken = false,
- isCustom = false,
- )
-}
-
-private fun Token.toTokenWalletData(walletManager: WalletManager, primaryToken: Token?): WalletDataModel {
- val wallet = walletManager.wallet
- return WalletDataModel(
- currency = Currency.Token(
- token = this,
- blockchain = wallet.blockchain,
- derivationPath = wallet.publicKey.derivationPath?.rawPath,
- ),
- status = WalletDataModel.Loading,
- walletAddresses = wallet.getWalletAddresses(),
- existentialDeposit = getExistentialDeposit(walletManager),
- fiatRate = null,
- isCardSingleToken = this == primaryToken,
- isCustom = false,
- )
-}
-
-private fun getExistentialDeposit(walletManager: WalletManager?): BigDecimal? {
- return (walletManager as? ExistentialDepositProvider)?.getExistentialDeposit()
-}
-
-private fun Wallet.getWalletAddresses(): WalletDataModel.WalletAddresses? {
- return this.createAddressesData()
- .takeIf { it.isNotEmpty() }
- ?.let { addresses ->
- WalletDataModel.WalletAddresses(
- list = addresses,
- selectedAddress = addresses.first(),
- )
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/moduleMessage/ConvertedMessage.kt b/app/src/main/java/com/tangem/tap/domain/moduleMessage/ConvertedMessage.kt
deleted file mode 100644
index a8add4f2a5..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/moduleMessage/ConvertedMessage.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.tangem.tap.domain.moduleMessage
-
-/**
-[REDACTED_AUTHOR]
- * Base interface for conversion outputs from ModuleMessageConverter
- */
-interface ConvertedMessage {
- val message: String
-}
-
-/**
- * Dialog message used to construct a android.Dialog
- */
-interface DialogMessage : ConvertedMessage {
- val title: String
- override val message: String
- val onPositive: String?
- val onNegative: String?
- val onNeutral: String?
-}
-
-data class ConvertedStringMessage(
- override val message: String,
-) : ConvertedMessage
-
-data class ConvertedDialogMessage(
- override val title: String,
- override val message: String,
- override val onPositive: String? = null,
- override val onNegative: String? = null,
- override val onNeutral: String? = null,
-) : DialogMessage
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/moduleMessage/ModuleMessageConverter.kt b/app/src/main/java/com/tangem/tap/domain/moduleMessage/ModuleMessageConverter.kt
deleted file mode 100644
index efca92a6e8..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/moduleMessage/ModuleMessageConverter.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.tangem.tap.domain.moduleMessage
-
-import android.content.Context
-import com.tangem.common.module.ModuleMessage
-import com.tangem.common.module.ModuleMessageConverter
-import com.tangem.domain.DomainModuleMessage
-import com.tangem.tap.domain.moduleMessage.domain.DomainMessageConverter
-
-class ModuleMessageConverter(
- private val context: Context,
-) : ModuleMessageConverter {
-
- override fun convert(message: ModuleMessage): ConvertedMessage {
- val convertedMessage = when (message) {
- is DomainModuleMessage -> DomainMessageConverter(context).convert(message)
- else -> null
- }
- return convertedMessage ?: convertUnknownMessage(message)
- }
-
- private fun convertUnknownMessage(message: ModuleMessage): ConvertedMessage {
- return ConvertedStringMessage("Unknown message: ${message::class.java.simpleName}")
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/moduleMessage/domain/DomainMessageConverter.kt b/app/src/main/java/com/tangem/tap/domain/moduleMessage/domain/DomainMessageConverter.kt
deleted file mode 100644
index 67c58be34a..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/moduleMessage/domain/DomainMessageConverter.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.tangem.tap.domain.moduleMessage.domain
-
-import android.content.Context
-import com.tangem.common.module.ModuleMessageConverter
-import com.tangem.domain.AddCustomTokenError
-import com.tangem.domain.DomainModuleError
-import com.tangem.domain.DomainModuleMessage
-import com.tangem.tap.domain.moduleMessage.ConvertedMessage
-import com.tangem.tap.domain.moduleMessage.domain.converter.AddCustomTokenErrorConverter
-
-/**
-[REDACTED_AUTHOR]
- */
-class DomainMessageConverter(
- private val context: Context,
-) : ModuleMessageConverter {
-
- override fun convert(message: DomainModuleMessage): ConvertedMessage? {
- return when (message) {
- is DomainModuleError -> DomainErrorConverter(context).convert(message)
- else -> null
- }
- }
-}
-
-class DomainErrorConverter(
- private val context: Context,
-) : ModuleMessageConverter {
-
- override fun convert(message: DomainModuleError): ConvertedMessage? = when (message) {
- is AddCustomTokenError -> AddCustomTokenErrorConverter(context).convert(message)
- else -> null
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/moduleMessage/domain/converter/AddCustomTokenErrorConverter.kt b/app/src/main/java/com/tangem/tap/domain/moduleMessage/domain/converter/AddCustomTokenErrorConverter.kt
deleted file mode 100644
index daa0901b14..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/moduleMessage/domain/converter/AddCustomTokenErrorConverter.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.tangem.tap.domain.moduleMessage.domain.converter
-
-import android.content.Context
-import com.tangem.common.module.ModuleMessageConverter
-import com.tangem.domain.AddCustomTokenError
-import com.tangem.domain.DomainModuleError
-import com.tangem.tap.domain.moduleMessage.ConvertedMessage
-import com.tangem.tap.domain.moduleMessage.ConvertedStringMessage
-import com.tangem.wallet.R
-
-/**
-[REDACTED_AUTHOR]
- */
-internal class AddCustomTokenErrorConverter(
- private val context: Context,
-) : ModuleMessageConverter {
-
- @Suppress("MagicNumber")
- override fun convert(message: DomainModuleError): ConvertedMessage? {
- val customTokenError = message as? AddCustomTokenError ?: throw UnsupportedOperationException()
-
- val rawMessage = when (customTokenError) {
- AddCustomTokenError.Warning.PotentialScamToken -> R.string.custom_token_validation_error_not_found
- AddCustomTokenError.Warning.TokenAlreadyAdded -> R.string.custom_token_validation_error_already_added
- AddCustomTokenError.Warning.UnsupportedSolanaToken -> R.string.alert_manage_tokens_unsupported_message
- AddCustomTokenError.InvalidContractAddress -> R.string.custom_token_creation_error_invalid_contract_address
- AddCustomTokenError.NetworkIsNotSelected -> R.string.custom_token_creation_error_network_not_selected
- AddCustomTokenError.InvalidDerivationPath -> R.string.custom_token_creation_error_invalid_derivation_path
- AddCustomTokenError.InvalidDecimalsCount -> {
- context.getString(R.string.custom_token_creation_error_wrong_decimals, 30)
- }
- AddCustomTokenError.FieldIsEmpty -> R.string.custom_token_creation_error_required_field
- else -> null
- }
-
- return when (rawMessage) {
- is Int -> ConvertedStringMessage(context.getString(rawMessage))
- is String -> ConvertedStringMessage(rawMessage)
- else -> null
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/statePrinter/OnboardingWalletStateConverter.kt b/app/src/main/java/com/tangem/tap/domain/statePrinter/OnboardingWalletStateConverter.kt
deleted file mode 100644
index 3e98a50996..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/statePrinter/OnboardingWalletStateConverter.kt
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.tangem.tap.domain.statePrinter
-
-import com.squareup.moshi.FromJson
-import com.squareup.moshi.ToJson
-import com.tangem.common.json.MoshiJsonConverter
-import com.tangem.domain.redux.state.StringStateConverter
-import com.tangem.tap.common.redux.AppState
-import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStep
-import com.tangem.tap.store
-import timber.log.Timber
-import java.math.BigInteger
-
-/**
-[REDACTED_AUTHOR]
- */
-class OnboardingWalletStateConverter : StringStateConverter {
- private val converter = MoshiJsonConverter(
- MoshiJsonConverter.getTangemSdkAdapters() + internalAdapters(),
- MoshiJsonConverter.getTangemSdkTypedAdapters(),
- )
-
- private fun internalAdapters(): List {
- return listOf(
- BackupStepAdapter(),
- BigIntegerAdapter(),
-
- )
- }
-
- override fun convert(stateHolder: AppState): String {
- val model = stateHolder.onboardingWalletState
- val json = converter.prettyPrint(model)
-
- return json
- }
-}
-
-fun printOnboardingWalletState() {
- val stringState = OnboardingWalletStateConverter().convert(store.state)
- Timber.d(stringState)
-}
-
-class BackupStepAdapter {
- @ToJson
- fun toJson(src: BackupStep): String {
- return when (src) {
- BackupStep.AddBackupCards -> "AddBackupCards"
- BackupStep.EnterAccessCode -> "EnterAccessCode"
- BackupStep.Finished -> "Finished"
- BackupStep.InitBackup -> "InitBackup"
- BackupStep.ReenterAccessCode -> "ReenterAccessCode"
- BackupStep.ScanOriginCard -> "ScanOriginCard"
- BackupStep.SetAccessCode -> "SetAccessCode"
- is BackupStep.WriteBackupCard -> "WriteBackupCard[${src.cardNumber}]"
- BackupStep.WritePrimaryCard -> "WritePrimaryCard"
- }
- }
-
- @Suppress("MagicNumber")
- @FromJson
- fun fromJson(json: String): BackupStep {
- return when (json) {
- "AddBackupCards" -> BackupStep.AddBackupCards
- "EnterAccessCode" -> BackupStep.EnterAccessCode
- "Finished" -> BackupStep.Finished
- "InitBackup" -> BackupStep.InitBackup
- "ReenterAccessCode" -> BackupStep.ReenterAccessCode
- "ScanOriginCard" -> BackupStep.ScanOriginCard
- "SetAccessCode" -> BackupStep.SetAccessCode
- "WriteBackupCard[1]" -> BackupStep.WriteBackupCard(1)
- "WriteBackupCard[2]" -> BackupStep.WriteBackupCard(2)
- "WriteBackupCard[3]" -> BackupStep.WriteBackupCard(3)
- "WritePrimaryCard" -> BackupStep.WritePrimaryCard
- else -> throw UnsupportedOperationException()
- }
- }
-}
-
-class BigIntegerAdapter {
- @ToJson
- fun toJson(src: BigInteger): String {
- return src.toString()
- }
-
- @FromJson
- fun fromJson(json: String): BigInteger {
- return BigInteger(json)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/statePrinter/ScanResponseConverter.kt b/app/src/main/java/com/tangem/tap/domain/statePrinter/ScanResponseConverter.kt
deleted file mode 100644
index e59536ab1e..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/statePrinter/ScanResponseConverter.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.tangem.tap.domain.statePrinter
-
-import com.tangem.common.extensions.toHexString
-import com.tangem.common.json.MoshiJsonConverter
-import com.tangem.domain.redux.state.StringStateConverter
-import com.tangem.tap.common.redux.AppState
-import com.tangem.tap.store
-import timber.log.Timber
-
-/**
-[REDACTED_AUTHOR]
- */
-class ScanResponseConverter : StringStateConverter {
- private val converter = MoshiJsonConverter.INSTANCE
-
- override fun convert(stateHolder: AppState): String {
- val scanResponse = stateHolder.globalState.scanResponse ?: return "NULL"
-
- val scanResponseMap = mutableMapOf()
- val derivedKeysMap = mutableMapOf()
- scanResponse.derivedKeys.forEach { (keyWalletPubKey, mapExPubKeys) ->
- val exPubKeysMap = mapExPubKeys.entries.map { (derivationPath, exPubKey) ->
- mapOf(
- "derivationPath" to derivationPath.rawPath,
- "extendedPublicKey" to mapOf(
- "publicKey" to exPubKey.publicKey.toHexString(),
- "chainCode" to exPubKey.chainCode.toHexString(),
- ),
- )
- }
- derivedKeysMap[keyWalletPubKey.bytes.toHexString()] = exPubKeysMap
- }
- scanResponseMap["derivedKeys"] = derivedKeysMap
-
- val json = converter.prettyPrint(scanResponseMap)
-
- return json
- }
-}
-
-fun printScanResponseState() {
- val stringState = ScanResponseConverter().convert(store.state)
- Timber.d(stringState)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/statePrinter/WalletStateConverter.kt b/app/src/main/java/com/tangem/tap/domain/statePrinter/WalletStateConverter.kt
deleted file mode 100644
index 57762aaf51..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/statePrinter/WalletStateConverter.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.tangem.tap.domain.statePrinter
-
-import com.tangem.blockchain.common.Wallet
-import com.tangem.common.json.MoshiJsonConverter
-import com.tangem.domain.redux.state.StringStateConverter
-import com.tangem.tap.common.redux.AppState
-import com.tangem.tap.store
-import timber.log.Timber
-
-/**
-[REDACTED_AUTHOR]
- */
-class WalletStateConverter : StringStateConverter {
- private val converter = MoshiJsonConverter.INSTANCE
-
- override fun convert(stateHolder: AppState): String {
- val walletState = stateHolder.walletState
-
- val walletManagers = mutableListOf