Updated on 2026-08-14
This commit is contained in:
commit
ea661f55ab
250 changed files with 6169 additions and 949 deletions
|
|
@ -25,11 +25,13 @@ dependencies {
|
||||||
implementation(project(":domain:legacy"))
|
implementation(project(":domain:legacy"))
|
||||||
implementation(project(":domain:models"))
|
implementation(project(":domain:models"))
|
||||||
implementation(project(":domain:core"))
|
implementation(project(":domain:core"))
|
||||||
implementation(project(":domain:card"))
|
implementation(projects.domain.card)
|
||||||
implementation(project(":domain:wallets"))
|
implementation(project(":domain:wallets"))
|
||||||
implementation(project(":domain:wallets:models"))
|
implementation(project(":domain:wallets:models"))
|
||||||
|
implementation(projects.domain.tokens)
|
||||||
implementation(project(":common"))
|
implementation(project(":common"))
|
||||||
implementation(project(":core:analytics"))
|
implementation(project(":core:analytics"))
|
||||||
|
implementation(projects.core.analytics.models)
|
||||||
implementation(project(":core:navigation"))
|
implementation(project(":core:navigation"))
|
||||||
implementation(project(":core:featuretoggles"))
|
implementation(project(":core:featuretoggles"))
|
||||||
implementation(project(":core:res"))
|
implementation(project(":core:res"))
|
||||||
|
|
@ -39,6 +41,9 @@ dependencies {
|
||||||
implementation(project(":libs:crypto"))
|
implementation(project(":libs:crypto"))
|
||||||
implementation(project(":libs:auth"))
|
implementation(project(":libs:auth"))
|
||||||
implementation(project(":data:source:preferences"))
|
implementation(project(":data:source:preferences"))
|
||||||
|
implementation(projects.data.card)
|
||||||
|
implementation(projects.data.tokens)
|
||||||
|
implementation(projects.data.common)
|
||||||
|
|
||||||
/** Features */
|
/** Features */
|
||||||
implementation(project(":features:onboarding"))
|
implementation(project(":features:onboarding"))
|
||||||
|
|
@ -119,13 +124,6 @@ dependencies {
|
||||||
implementation(deps.appsflyer)
|
implementation(deps.appsflyer)
|
||||||
implementation(deps.amplitude)
|
implementation(deps.amplitude)
|
||||||
implementation(deps.kotsonGson)
|
implementation(deps.kotsonGson)
|
||||||
//TODO: refactoring: remove it when all network services moved to the datasource module
|
|
||||||
implementation(deps.retrofit)
|
|
||||||
implementation(deps.retrofit.moshi)
|
|
||||||
implementation(deps.moshi)
|
|
||||||
implementation(deps.moshi.kotlin)
|
|
||||||
implementation(deps.okHttp)
|
|
||||||
implementation(deps.okHttp.logging)
|
|
||||||
implementation(deps.zendesk.chat)
|
implementation(deps.zendesk.chat)
|
||||||
implementation(deps.zendesk.messaging)
|
implementation(deps.zendesk.messaging)
|
||||||
implementation(deps.spongecastle.core)
|
implementation(deps.spongecastle.core)
|
||||||
|
|
@ -144,6 +142,7 @@ dependencies {
|
||||||
implementation(deps.kotlin.serialization)
|
implementation(deps.kotlin.serialization)
|
||||||
implementation(deps.walletConnectCore)
|
implementation(deps.walletConnectCore)
|
||||||
implementation(deps.walletConnectWeb3)
|
implementation(deps.walletConnectWeb3)
|
||||||
|
implementation(deps.prettyLogger)
|
||||||
|
|
||||||
/** Testing libraries */
|
/** Testing libraries */
|
||||||
testImplementation(deps.test.junit)
|
testImplementation(deps.test.junit)
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,11 @@ import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.tangem.TangemSdk
|
|
||||||
import com.tangem.core.navigation.AppScreen
|
import com.tangem.core.navigation.AppScreen
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
|
import com.tangem.data.card.sdk.CardSdkLifecycleObserver
|
||||||
import com.tangem.domain.card.ScanCardUseCase
|
import com.tangem.domain.card.ScanCardUseCase
|
||||||
|
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||||
import com.tangem.features.tester.api.TesterRouter
|
import com.tangem.features.tester.api.TesterRouter
|
||||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||||
|
|
@ -56,7 +57,6 @@ import java.lang.ref.WeakReference
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
lateinit var tangemSdk: TangemSdk
|
|
||||||
lateinit var tangemSdkManager: TangemSdkManager
|
lateinit var tangemSdkManager: TangemSdkManager
|
||||||
lateinit var backupService: BackupService
|
lateinit var backupService: BackupService
|
||||||
internal var lockUserWalletsTimer: LockUserWalletsTimer? = null
|
internal var lockUserWalletsTimer: LockUserWalletsTimer? = null
|
||||||
|
|
@ -88,7 +88,10 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
||||||
lateinit var testerRouter: TesterRouter
|
lateinit var testerRouter: TesterRouter
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var injectedTangemSdk: TangemSdk
|
lateinit var cardSdkLifecycleObserver: CardSdkLifecycleObserver
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var cardSdkConfigRepository: CardSdkConfigRepository
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var injectedTangemSdkManager: TangemSdkManager
|
lateinit var injectedTangemSdkManager: TangemSdkManager
|
||||||
|
|
@ -122,11 +125,11 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
||||||
systemActions()
|
systemActions()
|
||||||
store.dispatch(NavigationAction.ActivityCreated(WeakReference(this)))
|
store.dispatch(NavigationAction.ActivityCreated(WeakReference(this)))
|
||||||
|
|
||||||
tangemSdk = injectedTangemSdk
|
cardSdkLifecycleObserver.onCreate(context = this)
|
||||||
|
|
||||||
tangemSdkManager = injectedTangemSdkManager
|
tangemSdkManager = injectedTangemSdkManager
|
||||||
appStateHolder.tangemSdkManager = tangemSdkManager
|
appStateHolder.tangemSdkManager = tangemSdkManager
|
||||||
appStateHolder.tangemSdk = tangemSdk
|
backupService = BackupService.init(cardSdkConfigRepository.sdk, this)
|
||||||
backupService = BackupService.init(tangemSdk, this)
|
|
||||||
lockUserWalletsTimer = LockUserWalletsTimer(owner = this)
|
lockUserWalletsTimer = LockUserWalletsTimer(owner = this)
|
||||||
|
|
||||||
initUserWalletsListManager()
|
initUserWalletsListManager()
|
||||||
|
|
@ -144,10 +147,37 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
||||||
walletRouter = walletRouter,
|
walletRouter = walletRouter,
|
||||||
walletConnectInteractor = walletConnectInteractor,
|
walletConnectInteractor = walletConnectInteractor,
|
||||||
tokenDetailsRouter = tokenDetailsRouter,
|
tokenDetailsRouter = tokenDetailsRouter,
|
||||||
|
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
dialogManager.onStart(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
// TODO: RESEARCH! NotificationsHandler is created in onResume and destroyed in onStop
|
||||||
|
notificationsHandler = NotificationsHandler(binding.fragmentContainer)
|
||||||
|
|
||||||
|
navigateToInitialScreenIfNeededOnResume(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
notificationsHandler = null
|
||||||
|
dialogManager.onStop()
|
||||||
|
super.onStop()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
store.dispatch(NavigationAction.ActivityDestroyed(WeakReference(this)))
|
||||||
|
intentProcessor.removeAll()
|
||||||
|
cardSdkLifecycleObserver.onDestroy()
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
private fun initIntentHandlers() {
|
private fun initIntentHandlers() {
|
||||||
val hasSavedWalletsProvider = { store.state.globalState.userWalletsListManager?.hasUserWallets == true }
|
val hasSavedWalletsProvider = { store.state.globalState.userWalletsListManager?.hasUserWallets == true }
|
||||||
intentProcessor.addHandler(BackgroundScanIntentHandler(hasSavedWalletsProvider))
|
intentProcessor.addHandler(BackgroundScanIntentHandler(hasSavedWalletsProvider))
|
||||||
|
|
@ -183,13 +213,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
||||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
notificationsHandler = NotificationsHandler(binding.fragmentContainer)
|
|
||||||
|
|
||||||
navigateToInitialScreenIfNeededOnResume(intent)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent?) {
|
override fun onNewIntent(intent: Intent?) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
|
@ -197,23 +220,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
dialogManager.onStart(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStop() {
|
|
||||||
notificationsHandler = null
|
|
||||||
dialogManager.onStop()
|
|
||||||
super.onStop()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
store.dispatch(NavigationAction.ActivityDestroyed(WeakReference(this)))
|
|
||||||
intentProcessor.removeAll()
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showSnackbar(text: Int, buttonTitle: Int?, action: View.OnClickListener?) {
|
override fun showSnackbar(text: Int, buttonTitle: Int?, action: View.OnClickListener?) {
|
||||||
if (snackbar != null) return
|
if (snackbar != null) return
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.ImageLoaderFactory
|
import coil.ImageLoaderFactory
|
||||||
|
import com.orhanobut.logger.AndroidLogAdapter
|
||||||
|
import com.orhanobut.logger.Logger
|
||||||
import com.tangem.Log
|
import com.tangem.Log
|
||||||
import com.tangem.LogFormat
|
import com.tangem.LogFormat
|
||||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||||
|
|
@ -14,12 +16,14 @@ import com.tangem.core.analytics.Analytics
|
||||||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||||
import com.tangem.data.source.preferences.PreferencesDataSource
|
import com.tangem.data.source.preferences.PreferencesDataSource
|
||||||
import com.tangem.datasource.api.common.MoshiConverter
|
import com.tangem.datasource.api.common.MoshiConverter
|
||||||
|
import com.tangem.datasource.api.common.createNetworkLoggingInterceptor
|
||||||
import com.tangem.datasource.asset.AssetReader
|
import com.tangem.datasource.asset.AssetReader
|
||||||
import com.tangem.datasource.config.ConfigManager
|
import com.tangem.datasource.config.ConfigManager
|
||||||
import com.tangem.datasource.config.FeaturesLocalLoader
|
import com.tangem.datasource.config.FeaturesLocalLoader
|
||||||
import com.tangem.datasource.config.models.Config
|
import com.tangem.datasource.config.models.Config
|
||||||
import com.tangem.datasource.connection.NetworkConnectionManager
|
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||||
import com.tangem.domain.DomainLayer
|
import com.tangem.domain.DomainLayer
|
||||||
|
import com.tangem.domain.card.ScanCardProcessor
|
||||||
import com.tangem.domain.common.LogConfig
|
import com.tangem.domain.common.LogConfig
|
||||||
import com.tangem.domain.wallets.legacy.WalletManagersRepository
|
import com.tangem.domain.wallets.legacy.WalletManagersRepository
|
||||||
import com.tangem.feature.learn2earn.domain.api.Learn2earnInteractor
|
import com.tangem.feature.learn2earn.domain.api.Learn2earnInteractor
|
||||||
|
|
@ -59,7 +63,6 @@ import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import com.tangem.wallet.BuildConfig
|
import com.tangem.wallet.BuildConfig
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
|
||||||
import org.rekotlin.Store
|
import org.rekotlin.Store
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -151,6 +154,9 @@ class TapApplication : Application(), ImageLoaderFactory {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var tokenDetailsFeatureToggles: TokenDetailsFeatureToggles
|
lateinit var tokenDetailsFeatureToggles: TokenDetailsFeatureToggles
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var scanCardProcessor: ScanCardProcessor
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
|
|
@ -168,12 +174,20 @@ class TapApplication : Application(), ImageLoaderFactory {
|
||||||
walletConnectRepository = walletConnect2Repository,
|
walletConnectRepository = walletConnect2Repository,
|
||||||
walletConnectSessionsRepository = walletConnectSessionsRepository,
|
walletConnectSessionsRepository = walletConnectSessionsRepository,
|
||||||
tokenDetailsFeatureToggles = tokenDetailsFeatureToggles,
|
tokenDetailsFeatureToggles = tokenDetailsFeatureToggles,
|
||||||
|
scanCardProcessor = scanCardProcessor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
Timber.plant(Timber.DebugTree())
|
Logger.addLogAdapter(AndroidLogAdapter())
|
||||||
|
Timber.plant(
|
||||||
|
object : Timber.DebugTree() {
|
||||||
|
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||||
|
Logger.log(priority, tag, message, t)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
foregroundActivityObserver = ForegroundActivityObserver()
|
foregroundActivityObserver = ForegroundActivityObserver()
|
||||||
|
|
@ -192,7 +206,7 @@ class TapApplication : Application(), ImageLoaderFactory {
|
||||||
|
|
||||||
if (LogConfig.network.blockchainSdkNetwork) {
|
if (LogConfig.network.blockchainSdkNetwork) {
|
||||||
BlockchainSdkRetrofitBuilder.interceptors = listOf(
|
BlockchainSdkRetrofitBuilder.interceptors = listOf(
|
||||||
HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY },
|
createNetworkLoggingInterceptor(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
@ -13,7 +13,6 @@ sealed class MainScreen(
|
||||||
class ScreenOpened : MainScreen("Screen opened")
|
class ScreenOpened : MainScreen("Screen opened")
|
||||||
class ButtonScanCard : MainScreen("Button - Scan Card")
|
class ButtonScanCard : MainScreen("Button - Scan Card")
|
||||||
class ButtonMyWallets : MainScreen("Button - My Wallets")
|
class ButtonMyWallets : MainScreen("Button - My Wallets")
|
||||||
class ButtonBuy : MainScreen("Button - Buy")
|
|
||||||
|
|
||||||
class EnableBiometrics(state: AnalyticsParam.OnOffState) : MainScreen(
|
class EnableBiometrics(state: AnalyticsParam.OnOffState) : MainScreen(
|
||||||
event = "Enable Biometric",
|
event = "Enable Biometric",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.domain.common.extensions.toNetworkId
|
import com.tangem.domain.common.extensions.toNetworkId
|
||||||
import com.tangem.domain.features.addCustomToken.CustomCurrency
|
import com.tangem.domain.features.addCustomToken.CustomCurrency
|
||||||
import com.tangem.tap.common.extensions.filterNotNull
|
import com.tangem.tap.common.extensions.filterNotNull
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
sealed class MyWallets(
|
sealed class MyWallets(
|
||||||
event: String,
|
event: String,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
@ -72,26 +72,8 @@ sealed class Onboarding(
|
||||||
class SetupFinished : Twins("Twin Setup Finished")
|
class SetupFinished : Twins("Twin Setup Finished")
|
||||||
}
|
}
|
||||||
|
|
||||||
class PinScreenOpened : Onboarding("Onboarding", "PIN screen opened")
|
|
||||||
class ButtonSetPinCode : Onboarding("Onboarding", "Button - Set PIN Code")
|
|
||||||
class CardConnectionScreenOpened : Onboarding("Onboarding", "Card Connection Screen Opened")
|
|
||||||
class ButtonConnect : Onboarding("Onboarding", "Button - Connect")
|
|
||||||
class PinCodeSet : Onboarding("Onboarding", "PIN Code Set")
|
|
||||||
|
|
||||||
class KYCScreenOpened : Onboarding("Onboarding", "KYC screen opened")
|
|
||||||
class KYCStarted : Onboarding("Onboarding", "KYC Started")
|
|
||||||
class KYCInProgress : Onboarding("Onboarding", "KYC In Progress")
|
|
||||||
class KYCRejected : Onboarding("Onboarding", "KYC Rejected")
|
|
||||||
|
|
||||||
class ClaimScreenOpened : Onboarding("Onboarding", "Claim Screen Opened")
|
|
||||||
class ButtonClaim : Onboarding("Onboarding", "Button - Claim")
|
|
||||||
class ClaimWasSuccessfully : Onboarding("Onboarding", "Claim Was Successfully")
|
|
||||||
|
|
||||||
class ButtonChat : Onboarding("Onboarding", "Button - Chat")
|
class ButtonChat : Onboarding("Onboarding", "Button - Chat")
|
||||||
|
|
||||||
class NotEnoughGasError : Onboarding("Onboarding", "Not Enough Gas Error")
|
|
||||||
class CardNotPassedError : Onboarding("Onboarding", "Card Not Passed Error")
|
|
||||||
|
|
||||||
class EnableBiometrics(state: AnalyticsParam.OnOffState) : Onboarding(
|
class EnableBiometrics(state: AnalyticsParam.OnOffState) : Onboarding(
|
||||||
category = "Onboarding / Biometric",
|
category = "Onboarding / Biometric",
|
||||||
event = "Enable Biometric",
|
event = "Enable Biometric",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.tap.features.details.ui.details.SocialNetwork
|
import com.tangem.tap.features.details.ui.details.SocialNetwork
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.tap.common.extensions.filterNotNull
|
import com.tangem.tap.common.extensions.filterNotNull
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.tap.common.analytics.events.AnalyticsParam.CurrencyType
|
import com.tangem.tap.common.analytics.events.AnalyticsParam.CurrencyType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.common.analytics.events
|
package com.tangem.tap.common.analytics.events
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package com.tangem.tap.common.analytics.handlers.appsFlyer
|
package com.tangem.tap.common.analytics.handlers.appsFlyer
|
||||||
|
|
||||||
import com.appsflyer.AFInAppEventType
|
import com.appsflyer.AFInAppEventType
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
|
||||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||||
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||||
import com.tangem.tap.common.analytics.events.Shop
|
import com.tangem.tap.common.analytics.events.Shop
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package com.tangem.tap.common.analytics.handlers.firebase
|
package com.tangem.tap.common.analytics.handlers.firebase
|
||||||
|
|
||||||
import com.google.firebase.analytics.FirebaseAnalytics
|
import com.google.firebase.analytics.FirebaseAnalytics
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
|
||||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||||
import com.tangem.core.analytics.api.ErrorEventHandler
|
import com.tangem.core.analytics.api.ErrorEventHandler
|
||||||
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||||
import com.tangem.tap.common.analytics.converters.AnalyticsErrorConverter
|
import com.tangem.tap.common.analytics.converters.AnalyticsErrorConverter
|
||||||
import com.tangem.tap.common.analytics.events.Shop
|
import com.tangem.tap.common.analytics.events.Shop
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.tangem.tap.common.analytics.paramsInterceptor
|
package com.tangem.tap.common.analytics.paramsInterceptor
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
|
||||||
import com.tangem.core.analytics.api.ParamsInterceptor
|
import com.tangem.core.analytics.api.ParamsInterceptor
|
||||||
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.domain.common.util.cardTypesResolver
|
import com.tangem.domain.common.util.cardTypesResolver
|
||||||
import com.tangem.domain.models.scan.ProductType
|
import com.tangem.domain.models.scan.ProductType
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
package com.tangem.tap.common.analytics.paramsInterceptor
|
package com.tangem.tap.common.analytics.paramsInterceptor
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
|
||||||
import com.tangem.core.analytics.api.ParamsInterceptor
|
import com.tangem.core.analytics.api.ParamsInterceptor
|
||||||
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
class LinkedCardContextInterceptor(
|
class LinkedCardContextInterceptor(
|
||||||
private val scanResponse: ScanResponse,
|
scanResponse: ScanResponse,
|
||||||
val parent: LinkedCardContextInterceptor? = null,
|
val parent: LinkedCardContextInterceptor? = null,
|
||||||
) : ParamsInterceptor {
|
) : ParamsInterceptor {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import com.tangem.domain.common.BlockchainNetwork
|
||||||
import com.tangem.domain.common.CardTypesResolver
|
import com.tangem.domain.common.CardTypesResolver
|
||||||
import com.tangem.domain.common.util.cardTypesResolver
|
import com.tangem.domain.common.util.cardTypesResolver
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
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.UserWallet
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
import com.tangem.tap.common.analytics.converters.TopUpEventConverter
|
import com.tangem.tap.common.analytics.converters.TopUpEventConverter
|
||||||
|
|
@ -17,7 +18,6 @@ import com.tangem.tap.common.extensions.copy
|
||||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
import com.tangem.tap.domain.model.WalletDataModel
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.domain.model.WalletStoreModel
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
|
|
||||||
import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
|
import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
|
||||||
import com.tangem.tap.domain.walletStores.WalletStoresManager
|
import com.tangem.tap.domain.walletStores.WalletStoresManager
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import com.tangem.tap.common.chat.opener.implementation.SprinklrChatOpener
|
||||||
import com.tangem.tap.common.chat.opener.implementation.ZendeskChatOpener
|
import com.tangem.tap.common.chat.opener.implementation.ZendeskChatOpener
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import org.rekotlin.Store
|
import org.rekotlin.Store
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class ChatManager(
|
class ChatManager(
|
||||||
private val preferencesStorage: PreferencesDataSource,
|
private val preferencesStorage: PreferencesDataSource,
|
||||||
|
|
@ -20,7 +21,7 @@ class ChatManager(
|
||||||
) {
|
) {
|
||||||
private val openers = mutableMapOf<ChatConfig, ChatOpener>()
|
private val openers = mutableMapOf<ChatConfig, ChatOpener>()
|
||||||
|
|
||||||
fun open(config: ChatConfig, feedbackDataBuilder: (Context) -> String) {
|
fun open(config: ChatConfig, createLogsFile: (Context) -> File?, createFeedbackFile: (Context) -> File?) {
|
||||||
val opener = openers.getOrPut(config) {
|
val opener = openers.getOrPut(config) {
|
||||||
when (config) {
|
when (config) {
|
||||||
is SprinklrConfig -> SprinklrChatOpener(getSprinklrUserId(), config, store, foregroundActivityObserver)
|
is SprinklrConfig -> SprinklrChatOpener(getSprinklrUserId(), config, store, foregroundActivityObserver)
|
||||||
|
|
@ -28,7 +29,10 @@ class ChatManager(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opener.open(feedbackDataBuilder)
|
opener.open(
|
||||||
|
createFeedbackFile = createFeedbackFile,
|
||||||
|
createLogsFile = createLogsFile,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getZendeskUserId(): String {
|
private fun getZendeskUserId(): String {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
package com.tangem.tap.common.chat.opener
|
package com.tangem.tap.common.chat.opener
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
internal interface ChatOpener {
|
internal interface ChatOpener {
|
||||||
fun open(feedbackDataBuilder: (Context) -> String)
|
fun open(createFeedbackFile: (Context) -> File?, createLogsFile: (Context) -> File?)
|
||||||
}
|
}
|
||||||
|
|
@ -2,14 +2,15 @@ package com.tangem.tap.common.chat.opener.implementation
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import com.tangem.datasource.config.models.SprinklrConfig
|
||||||
import com.tangem.tap.ForegroundActivityObserver
|
import com.tangem.tap.ForegroundActivityObserver
|
||||||
import com.tangem.tap.common.chat.opener.ChatOpener
|
import com.tangem.tap.common.chat.opener.ChatOpener
|
||||||
import com.tangem.datasource.config.models.SprinklrConfig
|
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import com.tangem.tap.features.sprinklr.redux.SprinklrAction
|
import com.tangem.tap.features.sprinklr.redux.SprinklrAction
|
||||||
import com.tangem.tap.features.sprinklr.ui.SprinklrActivity
|
import com.tangem.tap.features.sprinklr.ui.SprinklrActivity
|
||||||
import com.tangem.tap.withForegroundActivity
|
import com.tangem.tap.withForegroundActivity
|
||||||
import org.rekotlin.Store
|
import org.rekotlin.Store
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
internal class SprinklrChatOpener(
|
internal class SprinklrChatOpener(
|
||||||
private val userId: String,
|
private val userId: String,
|
||||||
|
|
@ -17,7 +18,7 @@ internal class SprinklrChatOpener(
|
||||||
private val store: Store<AppState>,
|
private val store: Store<AppState>,
|
||||||
private val foregroundActivityObserver: ForegroundActivityObserver,
|
private val foregroundActivityObserver: ForegroundActivityObserver,
|
||||||
) : ChatOpener {
|
) : ChatOpener {
|
||||||
override fun open(feedbackDataBuilder: (Context) -> String) {
|
override fun open(createFeedbackFile: (Context) -> File?, createLogsFile: (Context) -> File?) {
|
||||||
store.dispatch(SprinklrAction.Init(userId, config))
|
store.dispatch(SprinklrAction.Init(userId, config))
|
||||||
foregroundActivityObserver.withForegroundActivity { activity ->
|
foregroundActivityObserver.withForegroundActivity { activity ->
|
||||||
val intent = Intent(activity, SprinklrActivity::class.java)
|
val intent = Intent(activity, SprinklrActivity::class.java)
|
||||||
|
|
|
||||||
|
|
@ -2,34 +2,34 @@ package com.tangem.tap.common.chat.opener.implementation
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.tangem.core.analytics.Analytics
|
import com.tangem.core.analytics.Analytics
|
||||||
|
import com.tangem.datasource.config.models.ZendeskConfig
|
||||||
import com.tangem.domain.common.LogConfig
|
import com.tangem.domain.common.LogConfig
|
||||||
import com.tangem.tap.ForegroundActivityObserver
|
import com.tangem.tap.ForegroundActivityObserver
|
||||||
import com.tangem.tap.common.chat.opener.ChatOpener
|
import com.tangem.tap.common.chat.opener.ChatOpener
|
||||||
import com.tangem.datasource.config.models.ZendeskConfig
|
|
||||||
import com.tangem.tap.withForegroundActivity
|
import com.tangem.tap.withForegroundActivity
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import com.zendesk.logger.Logger
|
import com.zendesk.logger.Logger
|
||||||
import zendesk.chat.Chat
|
import timber.log.Timber
|
||||||
import zendesk.chat.ChatConfiguration
|
import zendesk.chat.*
|
||||||
import zendesk.chat.ChatEngine
|
|
||||||
import zendesk.chat.ChatProvidersConfiguration
|
|
||||||
import zendesk.chat.VisitorInfo
|
|
||||||
import zendesk.configurations.Configuration
|
import zendesk.configurations.Configuration
|
||||||
import zendesk.messaging.MessagingActivity
|
import zendesk.messaging.MessagingActivity
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
internal class ZendeskChatOpener(
|
internal class ZendeskChatOpener(
|
||||||
private val userId: String,
|
private val userId: String,
|
||||||
private val config: ZendeskConfig,
|
private val config: ZendeskConfig,
|
||||||
private val foregroundActivityObserver: ForegroundActivityObserver,
|
private val foregroundActivityObserver: ForegroundActivityObserver,
|
||||||
) : ChatOpener {
|
) : ChatOpener {
|
||||||
|
|
||||||
private var isInitialized = false
|
private var isInitialized = false
|
||||||
|
|
||||||
override fun open(feedbackDataBuilder: (Context) -> String) {
|
override fun open(createFeedbackFile: (Context) -> File?, createLogsFile: (Context) -> File?) {
|
||||||
foregroundActivityObserver.withForegroundActivity { activity ->
|
foregroundActivityObserver.withForegroundActivity { activity ->
|
||||||
initZendeskIfNeeded(activity.applicationContext)
|
initZendeskIfNeeded(activity.applicationContext)
|
||||||
setChatVisitorInfo()
|
setChatVisitorInfo()
|
||||||
setChatVisitorNote(feedbackDataBuilder(activity))
|
|
||||||
showMessagingActivity(activity)
|
showMessagingActivity(activity)
|
||||||
|
sendFeedbackFile(createFeedbackFile(activity))
|
||||||
|
sendLogsFile(createLogsFile(activity))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,8 +48,20 @@ internal class ZendeskChatOpener(
|
||||||
ChatProvidersConfiguration.builder().withVisitorInfo(visitorInfo).build()
|
ChatProvidersConfiguration.builder().withVisitorInfo(visitorInfo).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setChatVisitorNote(note: String) {
|
private fun sendFeedbackFile(feedbackFile: File?) {
|
||||||
Chat.INSTANCE.providers()?.profileProvider()?.setVisitorNote(note)
|
if (isInitialized && feedbackFile != null) {
|
||||||
|
Chat.INSTANCE.providers()?.chatProvider()?.sendFile(feedbackFile) { _, bytesUploaded, _ ->
|
||||||
|
Timber.d("Log file sent", "bytesUploaded: $bytesUploaded")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendLogsFile(logsFile: File?) {
|
||||||
|
if (isInitialized && logsFile != null) {
|
||||||
|
Chat.INSTANCE.providers()?.chatProvider()?.sendFile(logsFile) { _, bytesUploaded, _ ->
|
||||||
|
Timber.d("Log file sent", "bytesUploaded: $bytesUploaded")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showMessagingActivity(context: Context) {
|
private fun showMessagingActivity(context: Context) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.common.di.domain.wallets
|
||||||
|
|
||||||
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
||||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||||
|
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
|
|
@ -17,4 +18,10 @@ object WalletsDomainModule {
|
||||||
fun providesGetWalletsUseCase(walletsStateHolder: WalletsStateHolder): GetWalletsUseCase {
|
fun providesGetWalletsUseCase(walletsStateHolder: WalletsStateHolder): GetWalletsUseCase {
|
||||||
return GetWalletsUseCase(walletsStateHolder = walletsStateHolder)
|
return GetWalletsUseCase(walletsStateHolder = walletsStateHolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@ViewModelScoped
|
||||||
|
fun providesSaveWalletUseCase(walletsStateHolder: WalletsStateHolder): SaveWalletUseCase {
|
||||||
|
return SaveWalletUseCase(walletsStateHolder = walletsStateHolder)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -24,13 +24,17 @@ fun BigDecimal.toFormattedString(
|
||||||
df.decimalFormatSymbols = symbols
|
df.decimalFormatSymbols = symbols
|
||||||
df.maximumFractionDigits = decimals
|
df.maximumFractionDigits = decimals
|
||||||
df.minimumFractionDigits = 0
|
df.minimumFractionDigits = 0
|
||||||
df.isGroupingUsed = false
|
df.isGroupingUsed = true
|
||||||
df.roundingMode = roundingMode
|
df.roundingMode = roundingMode
|
||||||
return df.format(this)
|
return df.format(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To formatted crypto currency string
|
||||||
|
* Specific method because there is no crypto currency codes in Locale
|
||||||
|
*/
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
fun BigDecimal.toFormattedCurrencyString(
|
fun BigDecimal.toFormattedCryptoCurrencyString(
|
||||||
decimals: Int,
|
decimals: Int,
|
||||||
currency: String,
|
currency: String,
|
||||||
roundingMode: RoundingMode = RoundingMode.DOWN,
|
roundingMode: RoundingMode = RoundingMode.DOWN,
|
||||||
|
|
@ -41,16 +45,34 @@ fun BigDecimal.toFormattedCurrencyString(
|
||||||
} else {
|
} else {
|
||||||
decimals
|
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(
|
val formattedAmount = this.toFormattedString(
|
||||||
decimals = decimalsForRounding,
|
decimals = decimalsForRounding,
|
||||||
roundingMode = roundingMode,
|
roundingMode = roundingMode,
|
||||||
|
locale = Locale.getDefault(),
|
||||||
)
|
)
|
||||||
return "$formattedAmount $currency"
|
return "$formattedAmount $currency "
|
||||||
}
|
}
|
||||||
|
|
||||||
fun BigDecimal.toFiatRateString(fiatCurrencyName: String, fiatCode: String): String {
|
fun BigDecimal.toFiatRateString(fiatCurrencyName: String, fiatCode: String): String {
|
||||||
try {
|
try {
|
||||||
val formatter = NumberFormat.getCurrencyInstance()
|
val formatter = NumberFormat.getCurrencyInstance(Locale.getDefault())
|
||||||
Currency.getInstance(fiatCode)?.let { currency ->
|
Currency.getInstance(fiatCode)?.let { currency ->
|
||||||
formatter.currency = currency
|
formatter.currency = currency
|
||||||
formatter.maximumFractionDigits = 2
|
formatter.maximumFractionDigits = 2
|
||||||
|
|
@ -91,7 +113,7 @@ fun BigDecimal.toFormattedFiatValue(
|
||||||
formatWithSpaces: Boolean = false,
|
formatWithSpaces: Boolean = false,
|
||||||
): String {
|
): String {
|
||||||
try {
|
try {
|
||||||
val formatter = NumberFormat.getCurrencyInstance()
|
val formatter = NumberFormat.getCurrencyInstance(Locale.getDefault())
|
||||||
Currency.getInstance(fiatCode)?.let { currency ->
|
Currency.getInstance(fiatCode)?.let { currency ->
|
||||||
formatter.currency = currency
|
formatter.currency = currency
|
||||||
formatter.maximumFractionDigits = 2
|
formatter.maximumFractionDigits = 2
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,12 @@
|
||||||
package com.tangem.tap.common.feedback
|
package com.tangem.tap.common.feedback
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import com.tangem.blockchain.common.Amount
|
import com.tangem.blockchain.common.*
|
||||||
import com.tangem.blockchain.common.AmountType
|
|
||||||
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.address.Address
|
import com.tangem.blockchain.common.address.Address
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
import com.tangem.domain.models.scan.CardDTO
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
import com.tangem.domain.userwallets.UserWalletIdBuilder
|
||||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
|
|
||||||
|
|
||||||
class AdditionalFeedbackInfo {
|
class AdditionalFeedbackInfo {
|
||||||
class EmailWalletInfo(
|
class EmailWalletInfo(
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package com.tangem.tap.common.feedback
|
package com.tangem.tap.common.feedback
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.tangem.datasource.config.models.ChatConfig
|
||||||
import com.tangem.domain.common.TapWorkarounds
|
import com.tangem.domain.common.TapWorkarounds
|
||||||
import com.tangem.tap.common.chat.ChatManager
|
import com.tangem.tap.common.chat.ChatManager
|
||||||
import com.tangem.datasource.config.models.ChatConfig
|
|
||||||
import com.tangem.tap.common.extensions.sendEmail
|
import com.tangem.tap.common.extensions.sendEmail
|
||||||
import com.tangem.tap.common.log.TangemLogCollector
|
import com.tangem.tap.common.log.TangemLogCollector
|
||||||
import com.tangem.tap.foregroundActivityObserver
|
import com.tangem.tap.foregroundActivityObserver
|
||||||
|
|
@ -22,32 +22,61 @@ class FeedbackManager(
|
||||||
private val chatManager: ChatManager,
|
private val chatManager: ChatManager,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
private var sessionFeedbackFile: File? = null
|
||||||
|
private var sessionLogsFile: File? = null
|
||||||
|
|
||||||
fun sendEmail(feedbackData: FeedbackData, onFail: ((Exception) -> Unit)? = null) {
|
fun sendEmail(feedbackData: FeedbackData, onFail: ((Exception) -> Unit)? = null) {
|
||||||
feedbackData.prepare(infoHolder)
|
feedbackData.prepare(infoHolder)
|
||||||
foregroundActivityObserver.withForegroundActivity { activity ->
|
foregroundActivityObserver.withForegroundActivity { activity ->
|
||||||
val fileLog = createLogFile(activity)
|
|
||||||
activity.sendEmail(
|
activity.sendEmail(
|
||||||
email = getSupportEmail(),
|
email = getSupportEmail(),
|
||||||
subject = activity.getString(feedbackData.subjectResId),
|
subject = activity.getString(feedbackData.subjectResId),
|
||||||
message = feedbackData.joinTogether(activity, infoHolder),
|
message = feedbackData.joinTogether(activity, infoHolder),
|
||||||
file = fileLog,
|
file = getLogFile(activity),
|
||||||
onFail = onFail,
|
onFail = onFail,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openChat(config: ChatConfig, feedbackData: FeedbackData) {
|
fun openChat(config: ChatConfig, feedbackData: FeedbackData) {
|
||||||
chatManager.open(config) { context ->
|
chatManager.open(
|
||||||
feedbackData.run {
|
config = config,
|
||||||
|
createLogsFile = ::getLogFile,
|
||||||
|
createFeedbackFile = { context -> getFeedbackFile(context, feedbackData) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFeedbackFile(context: Context, feedbackData: FeedbackData): File? {
|
||||||
|
return try {
|
||||||
|
if (sessionFeedbackFile != null) {
|
||||||
|
return sessionFeedbackFile
|
||||||
|
}
|
||||||
|
val file = File(context.filesDir, FEEDBACK_FILE)
|
||||||
|
file.delete()
|
||||||
|
file.createNewFile()
|
||||||
|
|
||||||
|
val feedback = feedbackData.run {
|
||||||
prepare(infoHolder)
|
prepare(infoHolder)
|
||||||
joinTogether(context, infoHolder)
|
joinTogether(context, infoHolder)
|
||||||
}
|
}
|
||||||
|
val fileWriter = FileWriter(file)
|
||||||
|
fileWriter.write(feedback)
|
||||||
|
fileWriter.close()
|
||||||
|
|
||||||
|
sessionFeedbackFile = file
|
||||||
|
sessionFeedbackFile
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Timber.e(ex, "Can't create the logs file")
|
||||||
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createLogFile(context: Context): File? {
|
private fun getLogFile(context: Context): File? {
|
||||||
return try {
|
return try {
|
||||||
val file = File(context.filesDir, "logs.txt")
|
if (sessionLogsFile != null) {
|
||||||
|
return sessionLogsFile
|
||||||
|
}
|
||||||
|
val file = File(context.filesDir, LOGS_FILE)
|
||||||
file.delete()
|
file.delete()
|
||||||
file.createNewFile()
|
file.createNewFile()
|
||||||
|
|
||||||
|
|
@ -57,7 +86,8 @@ class FeedbackManager(
|
||||||
fileWriter.write(stringWriter.toString())
|
fileWriter.write(stringWriter.toString())
|
||||||
fileWriter.close()
|
fileWriter.close()
|
||||||
logCollector.clearLogs()
|
logCollector.clearLogs()
|
||||||
file
|
sessionLogsFile = file
|
||||||
|
sessionLogsFile
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
Timber.e(ex, "Can't create the logs file")
|
Timber.e(ex, "Can't create the logs file")
|
||||||
null
|
null
|
||||||
|
|
@ -75,5 +105,7 @@ class FeedbackManager(
|
||||||
companion object {
|
companion object {
|
||||||
const val DEFAULT_SUPPORT_EMAIL = "support@tangem.com"
|
const val DEFAULT_SUPPORT_EMAIL = "support@tangem.com"
|
||||||
const val S2C_SUPPORT_EMAIL = "cardsupport@start2coin.com"
|
const val S2C_SUPPORT_EMAIL = "cardsupport@start2coin.com"
|
||||||
|
const val FEEDBACK_FILE = "feedback.txt"
|
||||||
|
const val LOGS_FILE = "logs.txt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,8 +4,8 @@ import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.util.Logger
|
import coil.util.Logger
|
||||||
|
import com.tangem.datasource.api.common.createNetworkLoggingInterceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
private const val COIL_LOG_TAG = "COIL"
|
private const val COIL_LOG_TAG = "COIL"
|
||||||
|
|
@ -18,14 +18,7 @@ fun createCoilImageLoader(context: Context, logEnabled: Boolean = false): ImageL
|
||||||
logger(CoilTimberLogger())
|
logger(CoilTimberLogger())
|
||||||
okHttpClient {
|
okHttpClient {
|
||||||
OkHttpClient.Builder()
|
OkHttpClient.Builder()
|
||||||
.addNetworkInterceptor(
|
.addNetworkInterceptor(createNetworkLoggingInterceptor())
|
||||||
HttpLoggingInterceptor { message ->
|
|
||||||
Timber.tag(COIL_LOG_TAG).d(message)
|
|
||||||
}
|
|
||||||
.apply {
|
|
||||||
level = HttpLoggingInterceptor.Level.BODY
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.google.zxing.BarcodeFormat
|
||||||
import com.google.zxing.Result
|
import com.google.zxing.Result
|
||||||
import com.otaliastudios.cameraview.CameraView.PERMISSION_REQUEST_CODE
|
import com.otaliastudios.cameraview.CameraView.PERMISSION_REQUEST_CODE
|
||||||
import me.dm7.barcodescanner.zxing.ZXingScannerView
|
import me.dm7.barcodescanner.zxing.ZXingScannerView
|
||||||
|
|
@ -16,11 +17,15 @@ import me.dm7.barcodescanner.zxing.ZXingScannerView
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
class ScanQrCodeActivity : AppCompatActivity(), ZXingScannerView.ResultHandler {
|
class ScanQrCodeActivity : AppCompatActivity(), ZXingScannerView.ResultHandler {
|
||||||
|
|
||||||
private lateinit var mScannerView: ZXingScannerView
|
private lateinit var mScannerView: ZXingScannerView
|
||||||
|
|
||||||
override fun onCreate(state: Bundle?) {
|
override fun onCreate(state: Bundle?) {
|
||||||
super.onCreate(state)
|
super.onCreate(state)
|
||||||
mScannerView = ZXingScannerView(this)
|
|
||||||
|
mScannerView = ZXingScannerView(this).apply {
|
||||||
|
setFormats(listOf(BarcodeFormat.QR_CODE))
|
||||||
|
}
|
||||||
setContentView(mScannerView)
|
setContentView(mScannerView)
|
||||||
|
|
||||||
if (!permissionIsGranted()) requestPermission()
|
if (!permissionIsGranted()) requestPermission()
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ package com.tangem.tap.common.redux
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
import com.tangem.tap.common.redux.global.GlobalAction
|
import com.tangem.tap.common.redux.global.GlobalAction
|
||||||
import com.tangem.tap.preferencesStorage
|
import com.tangem.tap.preferencesStorage
|
||||||
import com.tangem.tap.tangemSdkManager
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
|
import com.tangem.tap.store
|
||||||
import org.rekotlin.Middleware
|
import org.rekotlin.Middleware
|
||||||
|
|
||||||
class AccessCodeRequestPolicyMiddleware {
|
class AccessCodeRequestPolicyMiddleware {
|
||||||
|
|
@ -19,9 +20,8 @@ class AccessCodeRequestPolicyMiddleware {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateAccessCodeRequestPolicy(scanResponse: ScanResponse) {
|
private fun updateAccessCodeRequestPolicy(scanResponse: ScanResponse) {
|
||||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes &&
|
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes && scanResponse.card.isAccessCodeSet,
|
||||||
scanResponse.card.isAccessCodeSet,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,42 +1,43 @@
|
||||||
package com.tangem.tap.di
|
package com.tangem.tap.di
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.fragment.app.FragmentActivity
|
|
||||||
import com.tangem.TangemSdk
|
|
||||||
import com.tangem.domain.card.ScanCardUseCase
|
import com.tangem.domain.card.ScanCardUseCase
|
||||||
import com.tangem.sdk.extensions.initWithBiometrics
|
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||||
import com.tangem.tap.domain.TangemSdkManager
|
import com.tangem.tap.domain.TangemSdkManager
|
||||||
import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository
|
import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository
|
||||||
import com.tangem.tap.userTokensRepository
|
import com.tangem.tap.userTokensRepository
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.android.components.ActivityComponent
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.android.qualifiers.ActivityContext
|
import dagger.hilt.components.SingletonComponent
|
||||||
import dagger.hilt.android.scopes.ActivityScoped
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(ActivityComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
internal object ActivityModule {
|
internal object ActivityModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@ActivityScoped
|
@Singleton
|
||||||
fun provideTangemSdk(@ActivityContext context: Context): TangemSdk {
|
fun provideTangemSdkManager(
|
||||||
return TangemSdk.initWithBiometrics(context as FragmentActivity, TangemSdkManager.config)
|
@ApplicationContext context: Context,
|
||||||
|
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||||
|
): TangemSdkManager {
|
||||||
|
return TangemSdkManager(cardSdkConfigRepository = cardSdkConfigRepository, resources = context.resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@ActivityScoped
|
@Singleton
|
||||||
fun provideTangemSdkManager(@ActivityContext context: Context, tangemSdk: TangemSdk): TangemSdkManager {
|
fun provideScanCardUseCase(
|
||||||
return TangemSdkManager(tangemSdk, context)
|
tangemSdkManager: TangemSdkManager,
|
||||||
}
|
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||||
|
): ScanCardUseCase {
|
||||||
@Provides
|
|
||||||
@ActivityScoped
|
|
||||||
fun provideScanCardUseCase(tangemSdk: TangemSdk, tangemSdkManager: TangemSdkManager): ScanCardUseCase {
|
|
||||||
return ScanCardUseCase(
|
return ScanCardUseCase(
|
||||||
tangemSdk = tangemSdk,
|
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||||
scanCardRepository = DefaultScanCardRepository(userTokensRepository, tangemSdkManager),
|
scanCardRepository = DefaultScanCardRepository(
|
||||||
|
userTokensRepository = userTokensRepository,
|
||||||
|
tangemSdkManager = tangemSdkManager,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.tangem.tap.di.domain
|
||||||
|
|
||||||
|
import com.tangem.domain.card.GetAccessCodeSavingStatusUseCase
|
||||||
|
import com.tangem.domain.card.GetBiometricsStatusUseCase
|
||||||
|
import com.tangem.domain.card.ScanCardProcessor
|
||||||
|
import com.tangem.domain.card.SetAccessCodeRequestPolicyUseCase
|
||||||
|
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||||
|
import com.tangem.tap.domain.scanCard.DefaultScanCardProcessor
|
||||||
|
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 CardDomainModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideScanCardUseCase(): ScanCardProcessor = DefaultScanCardProcessor()
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideGetBiometricsStatusUseCase(
|
||||||
|
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||||
|
): GetBiometricsStatusUseCase {
|
||||||
|
return GetBiometricsStatusUseCase(cardSdkConfigRepository = cardSdkConfigRepository)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideSetAccessCodeRequestPolicyUseCase(
|
||||||
|
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||||
|
): SetAccessCodeRequestPolicyUseCase {
|
||||||
|
return SetAccessCodeRequestPolicyUseCase(cardSdkConfigRepository = cardSdkConfigRepository)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideGetAccessCodeSavingStatusUseCase(
|
||||||
|
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||||
|
): GetAccessCodeSavingStatusUseCase {
|
||||||
|
return GetAccessCodeSavingStatusUseCase(cardSdkConfigRepository = cardSdkConfigRepository)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.tangem.tap.di.domain
|
||||||
|
|
||||||
|
import com.tangem.domain.tokens.*
|
||||||
|
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||||
|
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||||
|
import com.tangem.domain.tokens.repository.TokensRepository
|
||||||
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.android.components.ViewModelComponent
|
||||||
|
import dagger.hilt.android.scopes.ViewModelScoped
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(ViewModelComponent::class)
|
||||||
|
internal object TokensDomainModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@ViewModelScoped
|
||||||
|
fun provideGetTokenListUseCase(
|
||||||
|
tokensRepository: TokensRepository,
|
||||||
|
quotesRepository: QuotesRepository,
|
||||||
|
networksRepository: NetworksRepository,
|
||||||
|
dispatchers: CoroutineDispatcherProvider,
|
||||||
|
): GetTokenListUseCase {
|
||||||
|
return GetTokenListUseCase(tokensRepository, quotesRepository, networksRepository, dispatchers)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@ViewModelScoped
|
||||||
|
fun provideToggleTokenListSortingUseCase(dispatchers: CoroutineDispatcherProvider): ToggleTokenListSortingUseCase {
|
||||||
|
return ToggleTokenListSortingUseCase(dispatchers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,27 +1,25 @@
|
||||||
package com.tangem.tap.domain
|
package com.tangem.tap.domain
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.res.Resources
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import com.tangem.Message
|
import com.tangem.Message
|
||||||
import com.tangem.TangemSdk
|
import com.tangem.TangemSdk
|
||||||
import com.tangem.blockchain.common.Blockchain
|
import com.tangem.blockchain.common.Blockchain
|
||||||
import com.tangem.common.*
|
import com.tangem.common.*
|
||||||
import com.tangem.common.biometric.BiometricManager
|
import com.tangem.common.biometric.BiometricManager
|
||||||
import com.tangem.common.card.FirmwareVersion
|
|
||||||
import com.tangem.common.core.*
|
import com.tangem.common.core.*
|
||||||
import com.tangem.common.extensions.ByteArrayKey
|
import com.tangem.common.extensions.ByteArrayKey
|
||||||
import com.tangem.common.usersCode.UserCodeRepository
|
import com.tangem.common.usersCode.UserCodeRepository
|
||||||
import com.tangem.core.analytics.Analytics
|
import com.tangem.core.analytics.Analytics
|
||||||
import com.tangem.crypto.bip39.DefaultMnemonic
|
import com.tangem.crypto.bip39.DefaultMnemonic
|
||||||
import com.tangem.crypto.hdWallet.DerivationPath
|
import com.tangem.crypto.hdWallet.DerivationPath
|
||||||
|
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||||
import com.tangem.domain.common.util.cardTypesResolver
|
import com.tangem.domain.common.util.cardTypesResolver
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
import com.tangem.domain.models.scan.CardDTO
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
import com.tangem.operations.ScanTask
|
import com.tangem.operations.ScanTask
|
||||||
import com.tangem.operations.derivation.DerivationTaskResponse
|
import com.tangem.operations.derivation.DerivationTaskResponse
|
||||||
import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
|
import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
|
||||||
import com.tangem.operations.pins.CheckUserCodesCommand
|
|
||||||
import com.tangem.operations.pins.CheckUserCodesResponse
|
|
||||||
import com.tangem.operations.pins.SetUserCodeCommand
|
import com.tangem.operations.pins.SetUserCodeCommand
|
||||||
import com.tangem.operations.usersetttings.SetUserCodeRecoveryAllowedTask
|
import com.tangem.operations.usersetttings.SetUserCodeRecoveryAllowedTask
|
||||||
import com.tangem.tap.common.analytics.events.Basic
|
import com.tangem.tap.common.analytics.events.Basic
|
||||||
|
|
@ -38,7 +36,10 @@ import kotlinx.coroutines.withContext
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
@Suppress("TooManyFunctions")
|
@Suppress("TooManyFunctions")
|
||||||
class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Context) {
|
class TangemSdkManager(private val cardSdkConfigRepository: CardSdkConfigRepository, private val resources: Resources) {
|
||||||
|
|
||||||
|
private val tangemSdk: TangemSdk
|
||||||
|
get() = cardSdkConfigRepository.sdk
|
||||||
|
|
||||||
private val userCodeRepository by lazy {
|
private val userCodeRepository by lazy {
|
||||||
UserCodeRepository(
|
UserCodeRepository(
|
||||||
|
|
@ -63,7 +64,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
messageRes: Int? = null,
|
messageRes: Int? = null,
|
||||||
allowsRequestAccessCodeFromRepository: Boolean = false,
|
allowsRequestAccessCodeFromRepository: Boolean = false,
|
||||||
): CompletionResult<ScanResponse> {
|
): CompletionResult<ScanResponse> {
|
||||||
val message = Message(context.getString(messageRes ?: R.string.initial_message_scan_header))
|
val message = Message(resources.getString(messageRes ?: R.string.initial_message_scan_header))
|
||||||
return runTaskAsyncReturnOnMain(
|
return runTaskAsyncReturnOnMain(
|
||||||
runnable = ScanProductTask(
|
runnable = ScanProductTask(
|
||||||
card = null,
|
card = null,
|
||||||
|
|
@ -80,7 +81,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
return runTaskAsync(
|
return runTaskAsync(
|
||||||
CreateProductWalletTask(scanResponse.cardTypesResolver),
|
CreateProductWalletTask(scanResponse.cardTypesResolver),
|
||||||
scanResponse.card.cardId,
|
scanResponse.card.cardId,
|
||||||
Message(context.getString(R.string.initial_message_create_wallet_body)),
|
Message(resources.getString(R.string.initial_message_create_wallet_body)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +93,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
is CompletionResult.Success -> runTaskAsync(
|
is CompletionResult.Success -> runTaskAsync(
|
||||||
CreateProductWalletTask(scanResponse.cardTypesResolver, seedResult.data),
|
CreateProductWalletTask(scanResponse.cardTypesResolver, seedResult.data),
|
||||||
scanResponse.card.cardId,
|
scanResponse.card.cardId,
|
||||||
Message(context.getString(R.string.initial_message_create_wallet_body)),
|
Message(resources.getString(R.string.initial_message_create_wallet_body)),
|
||||||
)
|
)
|
||||||
|
|
||||||
is CompletionResult.Failure -> CompletionResult.Failure(seedResult.error)
|
is CompletionResult.Failure -> CompletionResult.Failure(seedResult.error)
|
||||||
|
|
@ -111,7 +112,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
return runTaskAsyncReturnOnMain(
|
return runTaskAsyncReturnOnMain(
|
||||||
CreateWalletAndRescanTask(),
|
CreateWalletAndRescanTask(),
|
||||||
cardId,
|
cardId,
|
||||||
initialMessage = Message(context.getString(R.string.initial_message_create_wallet_body)),
|
initialMessage = Message(resources.getString(R.string.initial_message_create_wallet_body)),
|
||||||
)
|
)
|
||||||
.map { CardDTO(it) }
|
.map { CardDTO(it) }
|
||||||
}
|
}
|
||||||
|
|
@ -127,7 +128,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
return runTaskAsyncReturnOnMain(
|
return runTaskAsyncReturnOnMain(
|
||||||
runnable = ResetToFactorySettingsTask(),
|
runnable = ResetToFactorySettingsTask(),
|
||||||
cardId = cardId,
|
cardId = cardId,
|
||||||
initialMessage = Message(context.getString(R.string.card_settings_reset_card_to_factory)),
|
initialMessage = Message(resources.getString(R.string.card_settings_reset_card_to_factory)),
|
||||||
)
|
)
|
||||||
.map { CardDTO(it) }
|
.map { CardDTO(it) }
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +155,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
return runTaskAsyncReturnOnMain(
|
return runTaskAsyncReturnOnMain(
|
||||||
SetUserCodeCommand.changePasscode(null),
|
SetUserCodeCommand.changePasscode(null),
|
||||||
cardId,
|
cardId,
|
||||||
initialMessage = Message(context.getString(R.string.initial_message_change_passcode_body)),
|
initialMessage = Message(resources.getString(R.string.initial_message_change_passcode_body)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,7 +163,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
return runTaskAsyncReturnOnMain(
|
return runTaskAsyncReturnOnMain(
|
||||||
SetUserCodeCommand.changeAccessCode(null),
|
SetUserCodeCommand.changeAccessCode(null),
|
||||||
cardId,
|
cardId,
|
||||||
initialMessage = Message(context.getString(R.string.initial_message_change_access_code_body)),
|
initialMessage = Message(resources.getString(R.string.initial_message_change_access_code_body)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,15 +171,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
return runTaskAsyncReturnOnMain(
|
return runTaskAsyncReturnOnMain(
|
||||||
SetUserCodeCommand.resetUserCodes(),
|
SetUserCodeCommand.resetUserCodes(),
|
||||||
cardId,
|
cardId,
|
||||||
initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
|
initialMessage = Message(resources.getString(R.string.initial_message_tap_header)),
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun checkUserCodes(cardId: String?): CompletionResult<CheckUserCodesResponse> {
|
|
||||||
return runTaskAsyncReturnOnMain(
|
|
||||||
CheckUserCodesCommand(),
|
|
||||||
cardId,
|
|
||||||
initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,7 +179,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
return runTaskAsyncReturnOnMain(
|
return runTaskAsyncReturnOnMain(
|
||||||
SetUserCodeRecoveryAllowedTask(enabled),
|
SetUserCodeRecoveryAllowedTask(enabled),
|
||||||
cardId,
|
cardId,
|
||||||
initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
|
initialMessage = Message(resources.getString(R.string.initial_message_tap_header)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,7 +190,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
return runTaskAsyncReturnOnMain(
|
return runTaskAsyncReturnOnMain(
|
||||||
runnable = ScanTask(allowRequestAccessCodeFromRepository),
|
runnable = ScanTask(allowRequestAccessCodeFromRepository),
|
||||||
cardId = cardId,
|
cardId = cardId,
|
||||||
initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
|
initialMessage = Message(resources.getString(R.string.initial_message_tap_header)),
|
||||||
)
|
)
|
||||||
.map { CardDTO(it) }
|
.map { CardDTO(it) }
|
||||||
}
|
}
|
||||||
|
|
@ -233,8 +226,9 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("TangemSdkManager shouldn't returns a string from resources")
|
||||||
fun getString(@StringRes stringResId: Int, vararg formatArgs: Any?): String {
|
fun getString(@StringRes stringResId: Int, vararg formatArgs: Any?): String {
|
||||||
return context.getString(stringResId, *formatArgs)
|
return resources.getString(stringResId, *formatArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setAccessCodeRequestPolicy(useBiometricsForAccessCode: Boolean) {
|
fun setAccessCodeRequestPolicy(useBiometricsForAccessCode: Boolean) {
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,17 @@
|
||||||
package com.tangem.tap.domain.extensions
|
package com.tangem.tap.domain.extensions
|
||||||
|
|
||||||
import com.tangem.common.card.FirmwareVersion
|
|
||||||
import com.tangem.common.extensions.toHexString
|
import com.tangem.common.extensions.toHexString
|
||||||
import com.tangem.common.services.Result
|
import com.tangem.common.services.Result
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
|
||||||
import com.tangem.domain.common.TwinCardNumber
|
import com.tangem.domain.common.TwinCardNumber
|
||||||
import com.tangem.domain.common.getTwinCardNumber
|
import com.tangem.domain.common.getTwinCardNumber
|
||||||
|
import com.tangem.domain.models.scan.CardDTO
|
||||||
|
import com.tangem.domain.userwallets.Artwork
|
||||||
import com.tangem.operations.attestation.CardVerifyAndGetInfo
|
import com.tangem.operations.attestation.CardVerifyAndGetInfo
|
||||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||||
import com.tangem.tap.features.wallet.redux.Artwork
|
|
||||||
|
|
||||||
val CardDTO.remainingSignatures: Int?
|
val CardDTO.remainingSignatures: Int?
|
||||||
get() = this.wallets.firstOrNull()?.remainingSignatures
|
get() = this.wallets.firstOrNull()?.remainingSignatures
|
||||||
|
|
||||||
val CardDTO.isWalletDataSupported: Boolean
|
|
||||||
get() = this.firmwareVersion.major >= 4
|
|
||||||
|
|
||||||
val CardDTO.isFirmwareMultiwalletAllowed: Boolean
|
|
||||||
get() = firmwareVersion >= FirmwareVersion.MultiWalletAvailable && settings.maxWalletsCount > 1
|
|
||||||
|
|
||||||
val CardDTO.isHdWalletAllowedByApp: Boolean
|
val CardDTO.isHdWalletAllowedByApp: Boolean
|
||||||
get() = settings.isHDWalletAllowed
|
get() = settings.isHDWalletAllowed
|
||||||
|
|
||||||
|
|
@ -58,16 +51,4 @@ suspend fun CardDTO.getOrLoadCardArtworkUrl(cardInfo: Result<CardVerifyAndGetInf
|
||||||
|
|
||||||
is Result.Failure -> ifAnyError()
|
is Result.Failure -> ifAnyError()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun CardDTO.getArtworkUrl(artworkId: String?): String? {
|
|
||||||
return when {
|
|
||||||
artworkId != null -> {
|
|
||||||
OnlineCardVerifier.getUrlForArtwork(cardId, cardPublicKey.toHexString(), artworkId)
|
|
||||||
}
|
|
||||||
|
|
||||||
cardId.startsWith(Artwork.SERGIO_CARD_ID) -> Artwork.SERGIO_CARD_URL
|
|
||||||
cardId.startsWith(Artwork.MARTA_CARD_ID) -> Artwork.MARTA_CARD_URL
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ fun WalletManagerFactory.makeWalletManagerForApp(
|
||||||
val seedKey = wallet.extendedPublicKey
|
val seedKey = wallet.extendedPublicKey
|
||||||
return when {
|
return when {
|
||||||
scanResponse.cardTypesResolver.isTangemTwins() && scanResponse.secondTwinPublicKey != null -> {
|
scanResponse.cardTypesResolver.isTangemTwins() && scanResponse.secondTwinPublicKey != null -> {
|
||||||
makeTwinWalletManager(
|
createTwinWalletManager(
|
||||||
walletPublicKey = wallet.publicKey,
|
walletPublicKey = wallet.publicKey,
|
||||||
pairPublicKey = scanResponse.secondTwinPublicKey!!.hexToBytes(),
|
pairPublicKey = scanResponse.secondTwinPublicKey!!.hexToBytes(),
|
||||||
blockchain = environmentBlockchain,
|
blockchain = environmentBlockchain,
|
||||||
|
|
@ -47,7 +47,7 @@ fun WalletManagerFactory.makeWalletManagerForApp(
|
||||||
val derivedKey = derivedKeys?.get(derivationPath)
|
val derivedKey = derivedKeys?.get(derivationPath)
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
makeWalletManager(
|
createWalletManager(
|
||||||
blockchain = environmentBlockchain,
|
blockchain = environmentBlockchain,
|
||||||
seedKey = wallet.publicKey,
|
seedKey = wallet.publicKey,
|
||||||
derivedKey = derivedKey,
|
derivedKey = derivedKey,
|
||||||
|
|
@ -55,7 +55,7 @@ fun WalletManagerFactory.makeWalletManagerForApp(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
makeWalletManager(
|
createLegacyWalletManager(
|
||||||
blockchain = environmentBlockchain,
|
blockchain = environmentBlockchain,
|
||||||
walletPublicKey = wallet.publicKey,
|
walletPublicKey = wallet.publicKey,
|
||||||
curve = wallet.curve,
|
curve = wallet.curve,
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,22 @@ package com.tangem.tap.domain.scanCard
|
||||||
|
|
||||||
import com.tangem.common.CompletionResult
|
import com.tangem.common.CompletionResult
|
||||||
import com.tangem.common.core.TangemError
|
import com.tangem.common.core.TangemError
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
import com.tangem.domain.card.ScanCardProcessor
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
|
|
||||||
// TODO: Remove this object after feature toggle was removed and use ScanCardUseCase instead
|
// TODO: Remove this object after feature toggle was removed and use ScanCardUseCase instead
|
||||||
internal object ScanCardProcessor {
|
internal class DefaultScanCardProcessor : ScanCardProcessor {
|
||||||
private val isNewCardScanningEnabled: Boolean
|
private val isNewCardScanningEnabled: Boolean
|
||||||
get() = store.state.daggerGraphState
|
get() = store.state.daggerGraphState
|
||||||
.get(DaggerGraphState::customTokenFeatureToggles)
|
.get(DaggerGraphState::customTokenFeatureToggles)
|
||||||
.isNewCardScanningEnabled
|
.isNewCardScanningEnabled
|
||||||
|
|
||||||
suspend fun scan(
|
override suspend fun scan(
|
||||||
cardId: String? = null,
|
cardId: String?,
|
||||||
allowsRequestAccessCodeFromRepository: Boolean = false,
|
allowsRequestAccessCodeFromRepository: Boolean,
|
||||||
): CompletionResult<ScanResponse> {
|
): CompletionResult<ScanResponse> {
|
||||||
return if (isNewCardScanningEnabled) {
|
return if (isNewCardScanningEnabled) {
|
||||||
UseCaseScanProcessor.scan(cardId, allowsRequestAccessCodeFromRepository)
|
UseCaseScanProcessor.scan(cardId, allowsRequestAccessCodeFromRepository)
|
||||||
|
|
@ -26,15 +27,15 @@ internal object ScanCardProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
suspend fun scan(
|
override suspend fun scan(
|
||||||
analyticsEvent: AnalyticsEvent? = null,
|
analyticsEvent: AnalyticsEvent?,
|
||||||
cardId: String? = null,
|
cardId: String?,
|
||||||
onProgressStateChange: suspend (showProgress: Boolean) -> Unit = {},
|
onProgressStateChange: suspend (showProgress: Boolean) -> Unit,
|
||||||
onScanStateChange: suspend (scanInProgress: Boolean) -> Unit = {},
|
onScanStateChange: suspend (scanInProgress: Boolean) -> Unit,
|
||||||
onWalletNotCreated: suspend () -> Unit = {},
|
onWalletNotCreated: suspend () -> Unit,
|
||||||
disclaimerWillShow: () -> Unit = {},
|
disclaimerWillShow: () -> Unit,
|
||||||
onFailure: suspend (error: TangemError) -> Unit = {},
|
onFailure: suspend (error: TangemError) -> Unit,
|
||||||
onSuccess: suspend (scanResponse: ScanResponse) -> Unit = {},
|
onSuccess: suspend (scanResponse: ScanResponse) -> Unit,
|
||||||
) {
|
) {
|
||||||
if (isNewCardScanningEnabled) {
|
if (isNewCardScanningEnabled) {
|
||||||
UseCaseScanProcessor.scan(
|
UseCaseScanProcessor.scan(
|
||||||
|
|
@ -6,7 +6,7 @@ import com.tangem.common.core.TangemSdkError
|
||||||
import com.tangem.common.doOnFailure
|
import com.tangem.common.doOnFailure
|
||||||
import com.tangem.common.doOnSuccess
|
import com.tangem.common.doOnSuccess
|
||||||
import com.tangem.core.analytics.Analytics
|
import com.tangem.core.analytics.Analytics
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.core.navigation.AppScreen
|
import com.tangem.core.navigation.AppScreen
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.domain.common.TapWorkarounds.canSkipBackup
|
import com.tangem.domain.common.TapWorkarounds.canSkipBackup
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package com.tangem.tap.domain.scanCard
|
||||||
import arrow.fx.coroutines.resourceScope
|
import arrow.fx.coroutines.resourceScope
|
||||||
import com.tangem.common.CompletionResult
|
import com.tangem.common.CompletionResult
|
||||||
import com.tangem.common.core.TangemError
|
import com.tangem.common.core.TangemError
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.core.navigation.AppScreen
|
import com.tangem.core.navigation.AppScreen
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.domain.card.ScanCardException
|
import com.tangem.domain.card.ScanCardException
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package com.tangem.tap.domain.scanCard.chains
|
||||||
import arrow.core.Either
|
import arrow.core.Either
|
||||||
import arrow.core.right
|
import arrow.core.right
|
||||||
import com.tangem.core.analytics.Analytics
|
import com.tangem.core.analytics.Analytics
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.domain.card.ScanCardException
|
import com.tangem.domain.card.ScanCardException
|
||||||
import com.tangem.domain.core.chain.Chain
|
import com.tangem.domain.core.chain.Chain
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,7 @@ class ResetToFactorySettingsTask : CardSessionRunnable<Card> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetBackup(session: CardSession, callback: (result: CompletionResult<Card>) -> Unit) {
|
private fun resetBackup(session: CardSession, callback: (result: CompletionResult<Card>) -> Unit) {
|
||||||
val backupStatus = session.environment.card?.backupStatus
|
if (session.environment.card?.backupStatus?.isActive != true) {
|
||||||
if (backupStatus == null || backupStatus == Card.BackupStatus.NoBackup) {
|
|
||||||
callback(CompletionResult.Success(session.environment.card!!))
|
callback(CompletionResult.Success(session.environment.card!!))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import com.tangem.datasource.connection.NetworkConnectionManager
|
||||||
import com.tangem.datasource.files.AndroidFileReader
|
import com.tangem.datasource.files.AndroidFileReader
|
||||||
import com.tangem.domain.common.BlockchainNetwork
|
import com.tangem.domain.common.BlockchainNetwork
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
import com.tangem.domain.models.scan.CardDTO
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
|
import com.tangem.domain.userwallets.UserWalletIdBuilder
|
||||||
import com.tangem.tap.domain.tokens.converters.CurrencyConverter
|
import com.tangem.tap.domain.tokens.converters.CurrencyConverter
|
||||||
import com.tangem.tap.features.demo.DemoHelper
|
import com.tangem.tap.features.demo.DemoHelper
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import com.tangem.blockchain.common.Blockchain
|
||||||
import com.tangem.common.card.EllipticCurve
|
import com.tangem.common.card.EllipticCurve
|
||||||
import com.tangem.common.extensions.guard
|
import com.tangem.common.extensions.guard
|
||||||
import com.tangem.core.analytics.Analytics
|
import com.tangem.core.analytics.Analytics
|
||||||
|
import com.tangem.datasource.api.common.createNetworkLoggingInterceptor
|
||||||
import com.tangem.domain.common.extensions.toNetworkId
|
import com.tangem.domain.common.extensions.toNetworkId
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
import com.tangem.tap.common.analytics.events.WalletConnect
|
import com.tangem.tap.common.analytics.events.WalletConnect
|
||||||
|
|
@ -36,7 +37,6 @@ import okhttp3.Interceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
@ -56,8 +56,9 @@ class WalletConnectManager {
|
||||||
.addInterceptor(RetryInterceptor())
|
.addInterceptor(RetryInterceptor())
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val interceptor by lazy {
|
private val interceptor by lazy {
|
||||||
HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }
|
createNetworkLoggingInterceptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var sessions: MutableMap<Topic, WalletConnectActiveData> = mutableMapOf()
|
private var sessions: MutableMap<Topic, WalletConnectActiveData> = mutableMapOf()
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||||
import com.tangem.blockchain.blockchains.ethereum.EthereumUtils
|
import com.tangem.blockchain.blockchains.ethereum.EthereumUtils
|
||||||
import com.tangem.blockchain.blockchains.ethereum.EthereumUtils.Companion.toKeccak
|
import com.tangem.blockchain.blockchains.ethereum.EthereumUtils.Companion.toKeccak
|
||||||
import com.tangem.blockchain.common.*
|
import com.tangem.blockchain.common.*
|
||||||
|
import com.tangem.blockchain.common.transaction.Fee
|
||||||
import com.tangem.blockchain.extensions.Result
|
import com.tangem.blockchain.extensions.Result
|
||||||
import com.tangem.blockchain.extensions.SimpleResult
|
import com.tangem.blockchain.extensions.SimpleResult
|
||||||
import com.tangem.blockchain.extensions.hexToBigDecimal
|
import com.tangem.blockchain.extensions.hexToBigDecimal
|
||||||
|
|
@ -35,8 +36,8 @@ import com.tangem.tap.domain.walletconnect2.domain.models.binance.WcBinanceTrans
|
||||||
import com.tangem.tap.features.details.redux.walletconnect.*
|
import com.tangem.tap.features.details.redux.walletconnect.*
|
||||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialogData
|
import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialogData
|
||||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionRequestDialogData
|
import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionRequestDialogData
|
||||||
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import com.tangem.tap.tangemSdk
|
|
||||||
import com.tangem.tap.tangemSdkManager
|
import com.tangem.tap.tangemSdkManager
|
||||||
import com.trustwallet.walletconnect.models.ethereum.WCEthereumSignMessage.WCSignType.*
|
import com.trustwallet.walletconnect.models.ethereum.WCEthereumSignMessage.WCSignType.*
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
@ -76,7 +77,8 @@ class WalletConnectSdkHelper {
|
||||||
|
|
||||||
val transactionData = TransactionData(
|
val transactionData = TransactionData(
|
||||||
amount = Amount(value, wallet.blockchain),
|
amount = Amount(value, wallet.blockchain),
|
||||||
fee = Amount(fee, wallet.blockchain),
|
// TODO refactoring
|
||||||
|
fee = Fee.Common(Amount(fee, wallet.blockchain)),
|
||||||
sourceAddress = transaction.from,
|
sourceAddress = transaction.from,
|
||||||
destinationAddress = transaction.to!!,
|
destinationAddress = transaction.to!!,
|
||||||
extras = EthereumTransactionExtras(
|
extras = EthereumTransactionExtras(
|
||||||
|
|
@ -161,7 +163,10 @@ class WalletConnectSdkHelper {
|
||||||
private suspend fun sendTransaction(data: WcTransactionData, cardId: String?): String? {
|
private suspend fun sendTransaction(data: WcTransactionData, cardId: String?): String? {
|
||||||
val result = (data.walletManager as TransactionSender).send(
|
val result = (data.walletManager as TransactionSender).send(
|
||||||
transactionData = data.transaction,
|
transactionData = data.transaction,
|
||||||
signer = CommonSigner(tangemSdk, cardId),
|
signer = CommonSigner(
|
||||||
|
tangemSdk = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||||
|
cardId = cardId,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return when (result) {
|
return when (result) {
|
||||||
SimpleResult.Success -> {
|
SimpleResult.Success -> {
|
||||||
|
|
@ -182,7 +187,6 @@ class WalletConnectSdkHelper {
|
||||||
transactionData = data.transaction,
|
transactionData = data.transaction,
|
||||||
nonce = null,
|
nonce = null,
|
||||||
blockchain = data.walletManager.wallet.blockchain,
|
blockchain = data.walletManager.wallet.blockchain,
|
||||||
gasLimit = null,
|
|
||||||
) ?: return null
|
) ?: return null
|
||||||
|
|
||||||
val command = SignHashCommand(
|
val command = SignHashCommand(
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import com.tangem.blockchain.common.TransactionSender
|
||||||
import com.tangem.blockchain.common.TransactionSigner
|
import com.tangem.blockchain.common.TransactionSigner
|
||||||
import com.tangem.blockchain.common.WalletManager
|
import com.tangem.blockchain.common.WalletManager
|
||||||
import com.tangem.blockchain.common.toBlockchainSdkError
|
import com.tangem.blockchain.common.toBlockchainSdkError
|
||||||
|
import com.tangem.blockchain.common.transaction.Fee
|
||||||
|
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||||
import com.tangem.blockchain.extensions.Result
|
import com.tangem.blockchain.extensions.Result
|
||||||
import com.tangem.blockchain.extensions.SimpleResult
|
import com.tangem.blockchain.extensions.SimpleResult
|
||||||
import com.tangem.common.CompletionResult
|
import com.tangem.common.CompletionResult
|
||||||
|
|
@ -84,13 +86,13 @@ object DemoHelper {
|
||||||
|
|
||||||
class DemoTransactionSender(private val walletManager: WalletManager) : TransactionSender {
|
class DemoTransactionSender(private val walletManager: WalletManager) : TransactionSender {
|
||||||
|
|
||||||
override suspend fun getFee(amount: Amount, destination: String): Result<List<Amount>> {
|
override suspend fun getFee(amount: Amount, destination: String): Result<TransactionFee> {
|
||||||
val blockchain = walletManager.wallet.blockchain
|
val blockchain = walletManager.wallet.blockchain
|
||||||
return Result.Success(
|
return Result.Success(
|
||||||
listOf(
|
TransactionFee.Choosable(
|
||||||
Amount(0.0001.toBigDecimal(), blockchain),
|
minimum = Fee.Common(Amount(minimumFee, blockchain)),
|
||||||
Amount(0.0002.toBigDecimal(), blockchain),
|
normal = Fee.Common(Amount(normalFee, blockchain)),
|
||||||
Amount(0.0003.toBigDecimal(), blockchain),
|
priority = Fee.Common(Amount(priorityFee, blockchain)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -120,5 +122,9 @@ class DemoTransactionSender(private val walletManager: WalletManager) : Transact
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ID = DemoTransactionSender::class.java.simpleName
|
val ID = DemoTransactionSender::class.java.simpleName
|
||||||
|
|
||||||
|
private val minimumFee = 0.0001.toBigDecimal()
|
||||||
|
private val normalFee = 0.0002.toBigDecimal()
|
||||||
|
private val priorityFee = 0.0003.toBigDecimal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,6 +12,8 @@ import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||||
import com.tangem.domain.common.util.cardTypesResolver
|
import com.tangem.domain.common.util.cardTypesResolver
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||||
|
import com.tangem.domain.userwallets.UserWalletIdBuilder
|
||||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||||
import com.tangem.tap.*
|
import com.tangem.tap.*
|
||||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||||
|
|
@ -23,9 +25,6 @@ import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||||
import com.tangem.tap.common.redux.AppDialog
|
import com.tangem.tap.common.redux.AppDialog
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import com.tangem.tap.common.redux.global.GlobalAction
|
import com.tangem.tap.common.redux.global.GlobalAction
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletBuilder
|
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
|
|
||||||
import com.tangem.tap.domain.scanCard.ScanCardProcessor
|
|
||||||
import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
|
import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
|
||||||
import com.tangem.tap.domain.userWalletList.di.provideRuntimeImplementation
|
import com.tangem.tap.domain.userWalletList.di.provideRuntimeImplementation
|
||||||
import com.tangem.tap.domain.userWalletList.isLockedSync
|
import com.tangem.tap.domain.userWalletList.isLockedSync
|
||||||
|
|
@ -33,6 +32,7 @@ import com.tangem.tap.features.demo.DemoHelper
|
||||||
import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletMode
|
import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletMode
|
||||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
|
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import com.tangem.tap.tangemSdkManager
|
import com.tangem.tap.tangemSdkManager
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
@ -74,7 +74,8 @@ class DetailsMiddleware {
|
||||||
is DetailsAction.AccessCodeRecovery -> accessCodeRecoveryMiddleware.handle(state, action)
|
is DetailsAction.AccessCodeRecovery -> accessCodeRecoveryMiddleware.handle(state, action)
|
||||||
DetailsAction.ScanCard -> {
|
DetailsAction.ScanCard -> {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
ScanCardProcessor.scan(allowsRequestAccessCodeFromRepository = true)
|
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor)
|
||||||
|
.scan(allowsRequestAccessCodeFromRepository = true)
|
||||||
.doOnSuccess { scanResponse ->
|
.doOnSuccess { scanResponse ->
|
||||||
// if we use biometric, scanResponse in GlobalState is null, and crashes NPE on twin cards
|
// if we use biometric, scanResponse in GlobalState is null, and crashes NPE on twin cards
|
||||||
store.dispatch(GlobalAction.SaveScanResponse(scanResponse))
|
store.dispatch(GlobalAction.SaveScanResponse(scanResponse))
|
||||||
|
|
@ -371,9 +372,9 @@ class DetailsMiddleware {
|
||||||
Analytics.send(Settings.AppSettings.SaveAccessCodeSwitcherChanged(AnalyticsParam.OnOffState.On))
|
Analytics.send(Settings.AppSettings.SaveAccessCodeSwitcherChanged(AnalyticsParam.OnOffState.On))
|
||||||
|
|
||||||
preferencesStorage.shouldSaveAccessCodes = true
|
preferencesStorage.shouldSaveAccessCodes = true
|
||||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
store.state.daggerGraphState
|
||||||
useBiometricsForAccessCode = scanResponse?.card?.isAccessCodeSet == true,
|
.get(DaggerGraphState::cardSdkConfigRepository)
|
||||||
)
|
.setAccessCodeRequestPolicy(isBiometricsRequestPolicy = scanResponse?.card?.isAccessCodeSet == true)
|
||||||
|
|
||||||
return CompletionResult.Success(Unit)
|
return CompletionResult.Success(Unit)
|
||||||
}
|
}
|
||||||
|
|
@ -384,9 +385,9 @@ class DetailsMiddleware {
|
||||||
Analytics.send(Settings.AppSettings.SaveAccessCodeSwitcherChanged(AnalyticsParam.OnOffState.Off))
|
Analytics.send(Settings.AppSettings.SaveAccessCodeSwitcherChanged(AnalyticsParam.OnOffState.Off))
|
||||||
|
|
||||||
preferencesStorage.shouldSaveAccessCodes = false
|
preferencesStorage.shouldSaveAccessCodes = false
|
||||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
store.state.daggerGraphState
|
||||||
useBiometricsForAccessCode = false,
|
.get(DaggerGraphState::cardSdkConfigRepository)
|
||||||
)
|
.setAccessCodeRequestPolicy(isBiometricsRequestPolicy = false)
|
||||||
}
|
}
|
||||||
.doOnFailure { error ->
|
.doOnFailure { error ->
|
||||||
Timber.e(error, "Unable to delete saved access codes")
|
Timber.e(error, "Unable to delete saved access codes")
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.google.zxing.BarcodeFormat
|
||||||
import com.google.zxing.Result
|
import com.google.zxing.Result
|
||||||
import com.otaliastudios.cameraview.CameraView
|
import com.otaliastudios.cameraview.CameraView
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
|
|
@ -38,10 +39,19 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler {
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
if (!permissionIsGranted()) requestPermission()
|
if (!permissionIsGranted()) requestPermission()
|
||||||
|
|
||||||
scannerView = ZXingScannerView(activity)
|
scannerView = ZXingScannerView(activity).apply {
|
||||||
|
setFormats(listOf(BarcodeFormat.QR_CODE))
|
||||||
|
}
|
||||||
|
|
||||||
return scannerView
|
return scannerView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
scannerView?.setResultHandler(this)
|
||||||
|
scannerView?.startCamera()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
scannerView?.stopCamera()
|
scannerView?.stopCamera()
|
||||||
|
|
@ -52,12 +62,6 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler {
|
||||||
setFitSystemWindows(fit = false)
|
setFitSystemWindows(fit = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
scannerView?.setResultHandler(this)
|
|
||||||
scannerView?.startCamera()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleResult(result: Result) {
|
override fun handleResult(result: Result) {
|
||||||
store.dispatch(NavigationAction.PopBackTo())
|
store.dispatch(NavigationAction.PopBackTo())
|
||||||
setFitSystemWindows(fit = false)
|
setFitSystemWindows(fit = false)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.tap.features.home.redux
|
package com.tangem.tap.features.home.redux
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||||
import com.tangem.tap.common.analytics.events.Basic
|
import com.tangem.tap.common.analytics.events.Basic
|
||||||
import com.tangem.tap.common.entities.IndeterminateProgressButton
|
import com.tangem.tap.common.entities.IndeterminateProgressButton
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ import com.tangem.common.doOnResult
|
||||||
import com.tangem.common.doOnSuccess
|
import com.tangem.common.doOnSuccess
|
||||||
import com.tangem.common.extensions.guard
|
import com.tangem.common.extensions.guard
|
||||||
import com.tangem.core.analytics.Analytics
|
import com.tangem.core.analytics.Analytics
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.core.navigation.AppScreen
|
import com.tangem.core.navigation.AppScreen
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
import com.tangem.tap.*
|
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||||
import com.tangem.tap.common.analytics.events.Basic
|
import com.tangem.tap.common.analytics.events.Basic
|
||||||
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
||||||
import com.tangem.tap.common.analytics.events.Shop
|
import com.tangem.tap.common.analytics.events.Shop
|
||||||
|
|
@ -20,13 +20,16 @@ import com.tangem.tap.common.extensions.eraseContext
|
||||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import com.tangem.tap.common.redux.global.GlobalAction
|
import com.tangem.tap.common.redux.global.GlobalAction
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletBuilder
|
|
||||||
import com.tangem.tap.domain.scanCard.ScanCardProcessor
|
|
||||||
import com.tangem.tap.features.home.BELARUS_COUNTRY_CODE
|
import com.tangem.tap.features.home.BELARUS_COUNTRY_CODE
|
||||||
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
|
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
|
||||||
import com.tangem.tap.features.home.redux.HomeMiddleware.BUY_WALLET_URL
|
import com.tangem.tap.features.home.redux.HomeMiddleware.BUY_WALLET_URL
|
||||||
import com.tangem.tap.features.send.redux.states.ButtonState
|
import com.tangem.tap.features.send.redux.states.ButtonState
|
||||||
import com.tangem.tap.features.signin.redux.SignInAction
|
import com.tangem.tap.features.signin.redux.SignInAction
|
||||||
|
import com.tangem.tap.preferencesStorage
|
||||||
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
|
import com.tangem.tap.scope
|
||||||
|
import com.tangem.tap.store
|
||||||
|
import com.tangem.tap.userWalletsListManager
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.rekotlin.Action
|
import org.rekotlin.Action
|
||||||
|
|
@ -74,11 +77,11 @@ private fun handleHomeAction(action: Action) {
|
||||||
|
|
||||||
private fun readCard(analyticsEvent: AnalyticsEvent?) = scope.launch {
|
private fun readCard(analyticsEvent: AnalyticsEvent?) = scope.launch {
|
||||||
delay(timeMillis = 200)
|
delay(timeMillis = 200)
|
||||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes,
|
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
|
||||||
)
|
)
|
||||||
|
|
||||||
ScanCardProcessor.scan(
|
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan(
|
||||||
analyticsEvent = analyticsEvent,
|
analyticsEvent = analyticsEvent,
|
||||||
onProgressStateChange = { showProgress ->
|
onProgressStateChange = { showProgress ->
|
||||||
if (showProgress) {
|
if (showProgress) {
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@ import com.tangem.domain.common.util.cardTypesResolver
|
||||||
import com.tangem.domain.common.util.twinsIsTwinned
|
import com.tangem.domain.common.util.twinsIsTwinned
|
||||||
import com.tangem.domain.models.scan.ProductType
|
import com.tangem.domain.models.scan.ProductType
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||||
import com.tangem.tap.*
|
import com.tangem.tap.*
|
||||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||||
import com.tangem.tap.common.extensions.removeContext
|
import com.tangem.tap.common.extensions.removeContext
|
||||||
import com.tangem.tap.common.extensions.setContext
|
import com.tangem.tap.common.extensions.setContext
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletBuilder
|
|
||||||
import com.tangem.tap.features.saveWallet.redux.SaveWalletAction
|
import com.tangem.tap.features.saveWallet.redux.SaveWalletAction
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.domain.common.extensions.withMainContext
|
import com.tangem.domain.common.extensions.withMainContext
|
||||||
import com.tangem.domain.common.util.twinsIsTwinned
|
import com.tangem.domain.common.util.twinsIsTwinned
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
import com.tangem.domain.userwallets.UserWalletIdBuilder
|
||||||
import com.tangem.tap.*
|
import com.tangem.tap.*
|
||||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||||
import com.tangem.tap.common.analytics.events.Onboarding
|
import com.tangem.tap.common.analytics.events.Onboarding
|
||||||
|
|
@ -19,7 +20,6 @@ import com.tangem.tap.common.redux.AppState
|
||||||
import com.tangem.tap.common.redux.global.GlobalAction
|
import com.tangem.tap.common.redux.global.GlobalAction
|
||||||
import com.tangem.tap.domain.TapError
|
import com.tangem.tap.domain.TapError
|
||||||
import com.tangem.tap.domain.extensions.makePrimaryWalletManager
|
import com.tangem.tap.domain.extensions.makePrimaryWalletManager
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
|
|
||||||
import com.tangem.tap.domain.twins.TwinCardsManager
|
import com.tangem.tap.domain.twins.TwinCardsManager
|
||||||
import com.tangem.tap.domain.userWalletList.isLockedSync
|
import com.tangem.tap.domain.userWalletList.isLockedSync
|
||||||
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
|
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,12 @@ import com.tangem.core.analytics.Analytics
|
||||||
import com.tangem.core.navigation.ShareElement
|
import com.tangem.core.navigation.ShareElement
|
||||||
import com.tangem.core.ui.fragments.setStatusBarColor
|
import com.tangem.core.ui.fragments.setStatusBarColor
|
||||||
import com.tangem.datasource.asset.AssetReader
|
import com.tangem.datasource.asset.AssetReader
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
|
||||||
import com.tangem.domain.common.TwinCardNumber
|
import com.tangem.domain.common.TwinCardNumber
|
||||||
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
import com.tangem.domain.userwallets.Artwork
|
||||||
import com.tangem.sdk.ui.widget.leapfrogWidget.LeapfrogWidget
|
import com.tangem.sdk.ui.widget.leapfrogWidget.LeapfrogWidget
|
||||||
import com.tangem.tap.common.analytics.events.Onboarding
|
import com.tangem.tap.common.analytics.events.Onboarding
|
||||||
import com.tangem.tap.common.extensions.beginDelayedTransition
|
import com.tangem.tap.common.extensions.*
|
||||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
|
||||||
import com.tangem.tap.common.extensions.hide
|
|
||||||
import com.tangem.tap.common.extensions.show
|
|
||||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
|
||||||
import com.tangem.tap.common.toggleWidget.RefreshBalanceWidget
|
import com.tangem.tap.common.toggleWidget.RefreshBalanceWidget
|
||||||
import com.tangem.tap.common.transitions.InternalNoteLayoutTransition
|
import com.tangem.tap.common.transitions.InternalNoteLayoutTransition
|
||||||
import com.tangem.tap.domain.twins.TwinsCardWidget
|
import com.tangem.tap.domain.twins.TwinsCardWidget
|
||||||
|
|
@ -35,7 +32,6 @@ import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletM
|
||||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
|
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
|
||||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
|
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
|
||||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsStep
|
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsStep
|
||||||
import com.tangem.tap.features.wallet.redux.Artwork
|
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import com.tangem.wallet.databinding.LayoutOnboardingContainerTopBinding
|
import com.tangem.wallet.databinding.LayoutOnboardingContainerTopBinding
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import com.tangem.domain.common.extensions.withMainContext
|
||||||
import com.tangem.domain.common.util.cardTypesResolver
|
import com.tangem.domain.common.util.cardTypesResolver
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
import com.tangem.domain.models.scan.CardDTO
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
import com.tangem.domain.userwallets.Artwork
|
||||||
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
|
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
|
||||||
import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource
|
import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource
|
||||||
import com.tangem.operations.backup.BackupService
|
import com.tangem.operations.backup.BackupService
|
||||||
|
|
@ -30,10 +31,9 @@ import com.tangem.tap.features.home.redux.HomeAction
|
||||||
import com.tangem.tap.features.onboarding.OnboardingDialog
|
import com.tangem.tap.features.onboarding.OnboardingDialog
|
||||||
import com.tangem.tap.features.onboarding.OnboardingHelper
|
import com.tangem.tap.features.onboarding.OnboardingHelper
|
||||||
import com.tangem.tap.features.wallet.models.toCurrencies
|
import com.tangem.tap.features.wallet.models.toCurrencies
|
||||||
import com.tangem.tap.features.wallet.redux.Artwork
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.rekotlin.Action
|
import org.rekotlin.Action
|
||||||
import org.rekotlin.DispatchFunction
|
|
||||||
import org.rekotlin.Middleware
|
import org.rekotlin.Middleware
|
||||||
|
|
||||||
object OnboardingWalletMiddleware {
|
object OnboardingWalletMiddleware {
|
||||||
|
|
@ -44,8 +44,8 @@ private val onboardingWalletMiddleware: Middleware<AppState> = { dispatch, state
|
||||||
{ next ->
|
{ next ->
|
||||||
{ action ->
|
{ action ->
|
||||||
when (action) {
|
when (action) {
|
||||||
is OnboardingWallet2Action -> handleWallet2Action(action, state)
|
is OnboardingWallet2Action -> handleWallet2Action(action)
|
||||||
else -> handleWalletAction(action, state, dispatch)
|
else -> handleWalletAction(action)
|
||||||
}
|
}
|
||||||
next(action)
|
next(action)
|
||||||
}
|
}
|
||||||
|
|
@ -53,7 +53,7 @@ private val onboardingWalletMiddleware: Middleware<AppState> = { dispatch, state
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("LongMethod", "ComplexMethod")
|
@Suppress("LongMethod", "ComplexMethod")
|
||||||
private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch: DispatchFunction) {
|
private fun handleWalletAction(action: Action) {
|
||||||
if (action !is OnboardingWalletAction) return
|
if (action !is OnboardingWalletAction) return
|
||||||
|
|
||||||
val globalState = store.state.globalState
|
val globalState = store.state.globalState
|
||||||
|
|
@ -179,7 +179,7 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("LongMethod", "ComplexMethod")
|
@Suppress("LongMethod", "ComplexMethod")
|
||||||
private fun handleWallet2Action(action: OnboardingWallet2Action, state: () -> AppState?) {
|
private fun handleWallet2Action(action: OnboardingWallet2Action) {
|
||||||
val globalState = store.state.globalState
|
val globalState = store.state.globalState
|
||||||
val onboardingManager = globalState.onboardingState.onboardingManager
|
val onboardingManager = globalState.onboardingState.onboardingManager
|
||||||
|
|
||||||
|
|
@ -330,7 +330,9 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
||||||
is BackupAction.AddBackupCard -> {
|
is BackupAction.AddBackupCard -> {
|
||||||
backupService.addBackupCard { result ->
|
backupService.addBackupCard { result ->
|
||||||
backupService.skipCompatibilityChecks = false
|
backupService.skipCompatibilityChecks = false
|
||||||
tangemSdk.config.filter.cardIdFilter = null
|
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk
|
||||||
|
.config.filter.cardIdFilter = null
|
||||||
|
|
||||||
when (result) {
|
when (result) {
|
||||||
is CompletionResult.Success -> {
|
is CompletionResult.Success -> {
|
||||||
store.dispatchOnMain(BackupAction.AddBackupCard.Success)
|
store.dispatchOnMain(BackupAction.AddBackupCard.Success)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import com.tangem.common.flatMap
|
||||||
import com.tangem.core.analytics.Analytics
|
import com.tangem.core.analytics.Analytics
|
||||||
import com.tangem.core.navigation.AppScreen
|
import com.tangem.core.navigation.AppScreen
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
|
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||||
import com.tangem.tap.*
|
import com.tangem.tap.*
|
||||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||||
|
|
@ -18,10 +19,10 @@ import com.tangem.tap.common.extensions.dispatchOnMain
|
||||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import com.tangem.tap.common.redux.global.GlobalAction
|
import com.tangem.tap.common.redux.global.GlobalAction
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletBuilder
|
|
||||||
import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
|
import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
|
||||||
import com.tangem.tap.domain.userWalletList.isLockable
|
import com.tangem.tap.domain.userWalletList.isLockable
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.rekotlin.Middleware
|
import org.rekotlin.Middleware
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
@ -110,9 +111,10 @@ internal class SaveWalletMiddleware {
|
||||||
// Enable saving access codes only if this is the first time user save the wallet
|
// Enable saving access codes only if this is the first time user save the wallet
|
||||||
if (isFirstSavedWallet) {
|
if (isFirstSavedWallet) {
|
||||||
preferencesStorage.shouldSaveAccessCodes = true
|
preferencesStorage.shouldSaveAccessCodes = true
|
||||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository)
|
||||||
useBiometricsForAccessCode = userWallet.hasAccessCode,
|
.setAccessCodeRequestPolicy(
|
||||||
)
|
isBiometricsRequestPolicy = userWallet.hasAccessCode,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val savedUserWallet = userWalletsListManager.selectedUserWalletSync.guard {
|
val savedUserWallet = userWalletsListManager.selectedUserWalletSync.guard {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import com.tangem.Message
|
||||||
import com.tangem.blockchain.common.Amount
|
import com.tangem.blockchain.common.Amount
|
||||||
import com.tangem.blockchain.common.Blockchain
|
import com.tangem.blockchain.common.Blockchain
|
||||||
import com.tangem.blockchain.common.WalletManager
|
import com.tangem.blockchain.common.WalletManager
|
||||||
|
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||||
import com.tangem.common.core.TangemSdkError
|
import com.tangem.common.core.TangemSdkError
|
||||||
import com.tangem.tap.common.analytics.events.Token.Send.AddressEntered
|
import com.tangem.tap.common.analytics.events.Token.Send.AddressEntered
|
||||||
import com.tangem.tap.common.redux.StateDialog
|
import com.tangem.tap.common.redux.StateDialog
|
||||||
|
|
@ -114,7 +115,7 @@ sealed class FeeAction : SendScreenAction {
|
||||||
|
|
||||||
object RequestFee : FeeAction()
|
object RequestFee : FeeAction()
|
||||||
sealed class FeeCalculation : FeeAction() {
|
sealed class FeeCalculation : FeeAction() {
|
||||||
data class SetFeeResult(val fee: List<Amount>) : FeeCalculation()
|
data class SetFeeResult(val fee: TransactionFee) : FeeCalculation()
|
||||||
object ClearResult : FeeCalculation()
|
object ClearResult : FeeCalculation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ class AmountMiddleware {
|
||||||
}
|
}
|
||||||
|
|
||||||
val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend(inputCrypto))
|
val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend(inputCrypto))
|
||||||
val transactionErrors = walletManager.validateTransaction(amountToSend, sendState.feeState.currentFee)
|
val transactionErrors = walletManager.validateTransaction(amountToSend, sendState.feeState.currentFee?.amount)
|
||||||
val amountFieldErrors = filterErrorsForAmountField(transactionErrors)
|
val amountFieldErrors = filterErrorsForAmountField(transactionErrors)
|
||||||
if (amountFieldErrors.isEmpty()) {
|
if (amountFieldErrors.isEmpty()) {
|
||||||
dispatch(AmountAction.SetAmountError(null))
|
dispatch(AmountAction.SetAmountError(null))
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.features.send.redux.middlewares
|
||||||
import com.tangem.blockchain.common.Amount
|
import com.tangem.blockchain.common.Amount
|
||||||
import com.tangem.blockchain.common.BlockchainSdkError
|
import com.tangem.blockchain.common.BlockchainSdkError
|
||||||
import com.tangem.blockchain.common.TransactionSender
|
import com.tangem.blockchain.common.TransactionSender
|
||||||
|
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||||
import com.tangem.blockchain.extensions.Result
|
import com.tangem.blockchain.extensions.Result
|
||||||
import com.tangem.common.extensions.isZero
|
import com.tangem.common.extensions.isZero
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
|
|
@ -53,15 +54,18 @@ class RequestFeeMiddleware {
|
||||||
val result = feeResult.data
|
val result = feeResult.data
|
||||||
// val result = FeeMock.getFee(walletManager.wallet.blockchain)
|
// val result = FeeMock.getFee(walletManager.wallet.blockchain)
|
||||||
dispatch(FeeAction.FeeCalculation.SetFeeResult(result))
|
dispatch(FeeAction.FeeCalculation.SetFeeResult(result))
|
||||||
if (result.size == 1) {
|
when (result) {
|
||||||
val fee = result[0].value ?: BigDecimal.ZERO
|
is TransactionFee.Single -> {
|
||||||
if (fee.isZero()) {
|
val fee = result.normal.amount.value ?: BigDecimal.ZERO
|
||||||
dispatch(FeeAction.ChangeLayoutVisibility(main = false))
|
if (fee.isZero()) {
|
||||||
} else {
|
dispatch(FeeAction.ChangeLayoutVisibility(main = false))
|
||||||
dispatch(FeeAction.ChangeLayoutVisibility(main = true, chipGroup = false))
|
} else {
|
||||||
|
dispatch(FeeAction.ChangeLayoutVisibility(main = true, chipGroup = false))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is TransactionFee.Choosable -> {
|
||||||
|
dispatch(FeeAction.ChangeLayoutVisibility(main = true, chipGroup = true))
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
dispatch(FeeAction.ChangeLayoutVisibility(main = true, chipGroup = true))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Result.Failure -> {
|
is Result.Failure -> {
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,14 @@ import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider
|
||||||
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
|
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
|
||||||
import com.tangem.blockchain.blockchains.ton.TonTransactionExtras
|
import com.tangem.blockchain.blockchains.ton.TonTransactionExtras
|
||||||
import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder.XrpTransactionExtras
|
import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder.XrpTransactionExtras
|
||||||
import com.tangem.core.navigation.NavigationAction
|
|
||||||
import com.tangem.blockchain.common.*
|
import com.tangem.blockchain.common.*
|
||||||
|
import com.tangem.blockchain.common.transaction.Fee
|
||||||
import com.tangem.blockchain.extensions.SimpleResult
|
import com.tangem.blockchain.extensions.SimpleResult
|
||||||
import com.tangem.common.core.TangemSdkError
|
import com.tangem.common.core.TangemSdkError
|
||||||
import com.tangem.common.extensions.guard
|
import com.tangem.common.extensions.guard
|
||||||
import com.tangem.common.services.Result
|
import com.tangem.common.services.Result
|
||||||
import com.tangem.core.analytics.Analytics
|
import com.tangem.core.analytics.Analytics
|
||||||
|
import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||||
import com.tangem.domain.common.extensions.withMainContext
|
import com.tangem.domain.common.extensions.withMainContext
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
import com.tangem.domain.models.scan.CardDTO
|
||||||
|
|
@ -38,6 +39,7 @@ import com.tangem.tap.features.send.redux.FeeAction.RequestFee
|
||||||
import com.tangem.tap.features.send.redux.states.*
|
import com.tangem.tap.features.send.redux.states.*
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
@ -97,11 +99,11 @@ private fun verifyAndSendTransaction(
|
||||||
val card = appState.globalState.scanResponse?.card ?: return
|
val card = appState.globalState.scanResponse?.card ?: return
|
||||||
val destinationAddress = sendState.addressState.destinationWalletAddress ?: return
|
val destinationAddress = sendState.addressState.destinationWalletAddress ?: return
|
||||||
val typedAmount = sendState.amountState.amountToExtract ?: return
|
val typedAmount = sendState.amountState.amountToExtract ?: return
|
||||||
val feeAmount = sendState.feeState.currentFee ?: return
|
val fee = sendState.feeState.currentFee ?: return
|
||||||
|
|
||||||
val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend())
|
val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend())
|
||||||
|
|
||||||
val transactionErrors = walletManager.validateTransaction(amountToSend, feeAmount)
|
val transactionErrors = walletManager.validateTransaction(amountToSend, fee.amount)
|
||||||
when {
|
when {
|
||||||
transactionErrors.contains(TransactionError.TezosSendAll) -> {
|
transactionErrors.contains(TransactionError.TezosSendAll) -> {
|
||||||
val reduceAmount = walletManager.wallet.blockchain.minimalAmount()
|
val reduceAmount = walletManager.wallet.blockchain.minimalAmount()
|
||||||
|
|
@ -116,7 +118,7 @@ private fun verifyAndSendTransaction(
|
||||||
action = action,
|
action = action,
|
||||||
walletManager = walletManager,
|
walletManager = walletManager,
|
||||||
amountToSend = amountToSend,
|
amountToSend = amountToSend,
|
||||||
feeAmount = feeAmount,
|
fee = fee,
|
||||||
feeType = sendState.feeState.selectedFeeType,
|
feeType = sendState.feeState.selectedFeeType,
|
||||||
destinationAddress = destinationAddress,
|
destinationAddress = destinationAddress,
|
||||||
transactionExtras = sendState.transactionExtrasState,
|
transactionExtras = sendState.transactionExtrasState,
|
||||||
|
|
@ -135,7 +137,7 @@ private fun verifyAndSendTransaction(
|
||||||
action = action,
|
action = action,
|
||||||
walletManager = walletManager,
|
walletManager = walletManager,
|
||||||
amountToSend = amountToSend,
|
amountToSend = amountToSend,
|
||||||
feeAmount = feeAmount,
|
fee = fee,
|
||||||
feeType = sendState.feeState.selectedFeeType,
|
feeType = sendState.feeState.selectedFeeType,
|
||||||
destinationAddress = destinationAddress,
|
destinationAddress = destinationAddress,
|
||||||
transactionExtras = sendState.transactionExtrasState,
|
transactionExtras = sendState.transactionExtrasState,
|
||||||
|
|
@ -153,7 +155,7 @@ private fun sendTransaction(
|
||||||
action: SendActionUi.SendAmountToRecipient,
|
action: SendActionUi.SendAmountToRecipient,
|
||||||
walletManager: WalletManager,
|
walletManager: WalletManager,
|
||||||
amountToSend: Amount,
|
amountToSend: Amount,
|
||||||
feeAmount: Amount,
|
fee: Fee,
|
||||||
feeType: FeeType,
|
feeType: FeeType,
|
||||||
destinationAddress: String,
|
destinationAddress: String,
|
||||||
transactionExtras: TransactionExtrasState,
|
transactionExtras: TransactionExtrasState,
|
||||||
|
|
@ -163,7 +165,7 @@ private fun sendTransaction(
|
||||||
dispatch: (Action) -> Unit,
|
dispatch: (Action) -> Unit,
|
||||||
) {
|
) {
|
||||||
dispatch(SendAction.ChangeSendButtonState(ButtonState.PROGRESS))
|
dispatch(SendAction.ChangeSendButtonState(ButtonState.PROGRESS))
|
||||||
var txData = walletManager.createTransaction(amountToSend, feeAmount, destinationAddress)
|
var txData = walletManager.createTransaction(amountToSend, fee, destinationAddress)
|
||||||
|
|
||||||
transactionExtras.xlmMemo?.memo?.let { txData = txData.copy(extras = StellarTransactionExtras(it)) }
|
transactionExtras.xlmMemo?.memo?.let { txData = txData.copy(extras = StellarTransactionExtras(it)) }
|
||||||
transactionExtras.binanceMemo?.memo?.let { txData = txData.copy(extras = BinanceTransactionExtras(it.toString())) }
|
transactionExtras.binanceMemo?.memo?.let { txData = txData.copy(extras = BinanceTransactionExtras(it.toString())) }
|
||||||
|
|
@ -181,7 +183,7 @@ private fun sendTransaction(
|
||||||
updateFeedbackManagerInfo(
|
updateFeedbackManagerInfo(
|
||||||
walletManager = walletManager,
|
walletManager = walletManager,
|
||||||
amountToSend = amountToSend,
|
amountToSend = amountToSend,
|
||||||
feeAmount = feeAmount,
|
feeAmount = fee.amount,
|
||||||
destinationAddress = destinationAddress,
|
destinationAddress = destinationAddress,
|
||||||
)
|
)
|
||||||
dispatch(SendAction.Dialog.SendTransactionFails.BlockchainSdkError(error = error))
|
dispatch(SendAction.Dialog.SendTransactionFails.BlockchainSdkError(error = error))
|
||||||
|
|
@ -200,6 +202,7 @@ private fun sendTransaction(
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val tangemSdk = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk
|
||||||
val linkedTerminalState = tangemSdk.config.linkedTerminal
|
val linkedTerminalState = tangemSdk.config.linkedTerminal
|
||||||
if (card.isStart2Coin) {
|
if (card.isStart2Coin) {
|
||||||
tangemSdk.config.linkedTerminal = false
|
tangemSdk.config.linkedTerminal = false
|
||||||
|
|
@ -276,7 +279,7 @@ private fun sendTransaction(
|
||||||
updateFeedbackManagerInfo(
|
updateFeedbackManagerInfo(
|
||||||
walletManager = walletManager,
|
walletManager = walletManager,
|
||||||
amountToSend = amountToSend,
|
amountToSend = amountToSend,
|
||||||
feeAmount = feeAmount,
|
feeAmount = fee.amount,
|
||||||
destinationAddress = destinationAddress,
|
destinationAddress = destinationAddress,
|
||||||
)
|
)
|
||||||
val error = sendResult.error as? BlockchainSdkError ?: return@withMainContext
|
val error = sendResult.error as? BlockchainSdkError ?: return@withMainContext
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.tap.features.send.redux.reducers
|
package com.tangem.tap.features.send.redux.reducers
|
||||||
|
|
||||||
import com.tangem.blockchain.common.Amount
|
import com.tangem.blockchain.common.transaction.Fee
|
||||||
|
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||||
import com.tangem.tap.features.send.redux.FeeAction
|
import com.tangem.tap.features.send.redux.FeeAction
|
||||||
import com.tangem.tap.features.send.redux.FeeActionUi
|
import com.tangem.tap.features.send.redux.FeeActionUi
|
||||||
import com.tangem.tap.features.send.redux.SendScreenAction
|
import com.tangem.tap.features.send.redux.SendScreenAction
|
||||||
|
|
@ -13,6 +14,7 @@ import com.tangem.tap.features.wallet.redux.ProgressState
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
class FeeReducer : SendInternalReducer {
|
class FeeReducer : SendInternalReducer {
|
||||||
|
|
||||||
override fun handle(action: SendScreenAction, sendState: SendState): SendState = when (action) {
|
override fun handle(action: SendScreenAction, sendState: SendState): SendState = when (action) {
|
||||||
is FeeActionUi -> handleUiAction(action, sendState, sendState.feeState)
|
is FeeActionUi -> handleUiAction(action, sendState, sendState.feeState)
|
||||||
is FeeAction -> handleAction(action, sendState, sendState.feeState)
|
is FeeAction -> handleAction(action, sendState, sendState.feeState)
|
||||||
|
|
@ -25,7 +27,9 @@ class FeeReducer : SendInternalReducer {
|
||||||
state.copy(controlsLayoutIsVisible = !state.controlsLayoutIsVisible)
|
state.copy(controlsLayoutIsVisible = !state.controlsLayoutIsVisible)
|
||||||
}
|
}
|
||||||
is FeeActionUi.ChangeSelectedFee -> {
|
is FeeActionUi.ChangeSelectedFee -> {
|
||||||
val currentFee = createValueOfFeeAmount(action.feeType, state.feeList)
|
val currentFee = state.fees?.let {
|
||||||
|
createValueOfFeeAmount(action.feeType, it)
|
||||||
|
}
|
||||||
state.copy(
|
state.copy(
|
||||||
selectedFeeType = action.feeType,
|
selectedFeeType = action.feeType,
|
||||||
currentFee = currentFee,
|
currentFee = currentFee,
|
||||||
|
|
@ -50,34 +54,36 @@ class FeeReducer : SendInternalReducer {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is FeeAction.FeeCalculation.SetFeeResult -> {
|
is FeeAction.FeeCalculation.SetFeeResult -> {
|
||||||
val fees = action.fee
|
when (val fees = action.fee) {
|
||||||
if (fees.size == 1) {
|
is TransactionFee.Single -> {
|
||||||
val feeType = FeeType.SINGLE
|
val feeType = FeeType.SINGLE
|
||||||
val currentFee = createValueOfFeeAmount(feeType, fees)
|
val currentFee = createValueOfFeeAmount(feeType, fees)
|
||||||
|
|
||||||
state.copy(
|
state.copy(
|
||||||
selectedFeeType = feeType,
|
selectedFeeType = feeType,
|
||||||
feeList = fees,
|
fees = fees,
|
||||||
currentFee = currentFee,
|
currentFee = currentFee,
|
||||||
feeIsApproximate = isFeeApproximate(sendState),
|
feeIsApproximate = isFeeApproximate(sendState),
|
||||||
)
|
)
|
||||||
} else {
|
}
|
||||||
val feeType = getCurrentFeeType(state)
|
is TransactionFee.Choosable -> {
|
||||||
val currentFee = createValueOfFeeAmount(feeType, fees)
|
val feeType = getCurrentFeeType(state)
|
||||||
|
val currentFee = createValueOfFeeAmount(feeType, fees)
|
||||||
|
|
||||||
state.copy(
|
state.copy(
|
||||||
selectedFeeType = feeType,
|
selectedFeeType = feeType,
|
||||||
feeList = fees,
|
fees = fees,
|
||||||
currentFee = currentFee,
|
currentFee = currentFee,
|
||||||
feeIsApproximate = isFeeApproximate(sendState),
|
feeIsApproximate = isFeeApproximate(sendState),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}.copy(
|
}.copy(
|
||||||
progressState = ProgressState.Done,
|
progressState = ProgressState.Done,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
FeeAction.FeeCalculation.ClearResult -> {
|
FeeAction.FeeCalculation.ClearResult -> {
|
||||||
state.copy(
|
state.copy(
|
||||||
feeList = null,
|
fees = null,
|
||||||
currentFee = null,
|
currentFee = null,
|
||||||
progressState = ProgressState.Done,
|
progressState = ProgressState.Done,
|
||||||
)
|
)
|
||||||
|
|
@ -87,17 +93,18 @@ class FeeReducer : SendInternalReducer {
|
||||||
return updateLastState(sendState.copy(feeState = result), result)
|
return updateLastState(sendState.copy(feeState = result), result)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createValueOfFeeAmount(feeType: FeeType, list: List<Amount>?): Amount? {
|
private fun createValueOfFeeAmount(feeType: FeeType, transactionFee: TransactionFee): Fee {
|
||||||
if (list == null || list.isEmpty()) return null
|
return when (transactionFee) {
|
||||||
|
is TransactionFee.Single -> {
|
||||||
return if (list.size == 1) {
|
transactionFee.normal
|
||||||
list[0]
|
}
|
||||||
} else {
|
is TransactionFee.Choosable -> {
|
||||||
when (feeType) {
|
when (feeType) {
|
||||||
FeeType.SINGLE -> list[1]
|
FeeType.SINGLE -> transactionFee.normal
|
||||||
FeeType.LOW -> list[0]
|
FeeType.LOW -> transactionFee.minimum
|
||||||
FeeType.NORMAL -> list[1]
|
FeeType.NORMAL -> transactionFee.normal
|
||||||
FeeType.PRIORITY -> list[2]
|
FeeType.PRIORITY -> transactionFee.priority
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.tap.features.send.redux.states
|
package com.tangem.tap.features.send.redux.states
|
||||||
|
|
||||||
import com.tangem.blockchain.common.Amount
|
import com.tangem.blockchain.common.transaction.Fee
|
||||||
|
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
@ -23,8 +24,8 @@ fun FeeType.convertToAnalyticsFeeType(): AnalyticsParam.FeeType {
|
||||||
|
|
||||||
data class FeeState(
|
data class FeeState(
|
||||||
val selectedFeeType: FeeType = FeeType.NORMAL,
|
val selectedFeeType: FeeType = FeeType.NORMAL,
|
||||||
val feeList: List<Amount>? = null,
|
val fees: TransactionFee? = null,
|
||||||
val currentFee: Amount? = null,
|
val currentFee: Fee? = null,
|
||||||
val feeIsIncluded: Boolean = false,
|
val feeIsIncluded: Boolean = false,
|
||||||
val feeIsApproximate: Boolean = false,
|
val feeIsApproximate: Boolean = false,
|
||||||
val mainLayoutIsVisible: Boolean = false,
|
val mainLayoutIsVisible: Boolean = false,
|
||||||
|
|
@ -38,5 +39,5 @@ data class FeeState(
|
||||||
|
|
||||||
fun isReady(): Boolean = currentFee != null
|
fun isReady(): Boolean = currentFee != null
|
||||||
|
|
||||||
fun getCurrentFeeValue(): BigDecimal = currentFee?.value ?: BigDecimal.ZERO
|
fun getCurrentFeeValue(): BigDecimal = currentFee?.amount?.value ?: BigDecimal.ZERO
|
||||||
}
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.transition.TransitionInflater
|
import androidx.transition.TransitionInflater
|
||||||
|
import com.tangem.core.ui.components.SystemBarsEffect
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.tap.features.tokens.impl.presentation.ui.TokensListScreen
|
import com.tangem.tap.features.tokens.impl.presentation.ui.TokensListScreen
|
||||||
import com.tangem.tap.features.tokens.impl.presentation.viewmodels.TokensListViewModel
|
import com.tangem.tap.features.tokens.impl.presentation.viewmodels.TokensListViewModel
|
||||||
|
|
@ -40,6 +41,10 @@ internal class TokensListFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
TangemTheme {
|
TangemTheme {
|
||||||
|
val statusBarColor = TangemTheme.colors.background.secondary
|
||||||
|
SystemBarsEffect {
|
||||||
|
setSystemBarsColor(color = statusBarColor)
|
||||||
|
}
|
||||||
TokensListScreen(
|
TokensListScreen(
|
||||||
modifier = Modifier.systemBarsPadding(),
|
modifier = Modifier.systemBarsPadding(),
|
||||||
stateHolder = viewModel.uiState,
|
stateHolder = viewModel.uiState,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package com.tangem.tap.features.wallet.redux
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.tangem.blockchain.common.Amount
|
import com.tangem.blockchain.common.Amount
|
||||||
import com.tangem.blockchain.common.address.AddressType
|
import com.tangem.blockchain.common.address.AddressType
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.domain.common.BlockchainNetwork
|
import com.tangem.domain.common.BlockchainNetwork
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
import com.tangem.domain.models.scan.CardDTO
|
||||||
import com.tangem.domain.wallets.models.UserWallet
|
import com.tangem.domain.wallets.models.UserWallet
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package com.tangem.tap.features.wallet.redux
|
package com.tangem.tap.features.wallet.redux
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import com.tangem.blockchain.common.AmountType
|
import com.tangem.blockchain.common.AmountType
|
||||||
import com.tangem.blockchain.common.Blockchain
|
import com.tangem.blockchain.common.Blockchain
|
||||||
import com.tangem.blockchain.common.WalletManager
|
import com.tangem.blockchain.common.WalletManager
|
||||||
import com.tangem.domain.common.BlockchainNetwork
|
import com.tangem.domain.common.BlockchainNetwork
|
||||||
import com.tangem.domain.common.util.cardTypesResolver
|
import com.tangem.domain.common.util.cardTypesResolver
|
||||||
|
import com.tangem.domain.userwallets.Artwork
|
||||||
import com.tangem.tap.common.entities.Button
|
import com.tangem.tap.common.entities.Button
|
||||||
import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
||||||
import com.tangem.tap.common.toggleWidget.WidgetState
|
import com.tangem.tap.common.toggleWidget.WidgetState
|
||||||
|
|
@ -118,19 +118,4 @@ enum class ErrorType {
|
||||||
|
|
||||||
sealed class WalletMainButton(enabled: Boolean) : Button(enabled) {
|
sealed class WalletMainButton(enabled: Boolean) : Button(enabled) {
|
||||||
class SendButton(enabled: Boolean) : WalletMainButton(enabled)
|
class SendButton(enabled: Boolean) : WalletMainButton(enabled)
|
||||||
}
|
|
||||||
|
|
||||||
data class Artwork(
|
|
||||||
val artworkId: String,
|
|
||||||
val artwork: Bitmap? = null,
|
|
||||||
) {
|
|
||||||
companion object {
|
|
||||||
const val DEFAULT_IMG_URL = "https://app.tangem.com/cards/card_default.png"
|
|
||||||
const val SERGIO_CARD_URL = "https://app.tangem.com/cards/card_tg059.png"
|
|
||||||
const val MARTA_CARD_URL = "https://app.tangem.com/cards/card_tg083.png"
|
|
||||||
const val SERGIO_CARD_ID = "BC01"
|
|
||||||
const val MARTA_CARD_ID = "BC02"
|
|
||||||
const val TWIN_CARD_1 = "https://app.tangem.com/cards/card_tg085.png"
|
|
||||||
const val TWIN_CARD_2 = "https://app.tangem.com/cards/card_tg086.png"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -15,10 +15,10 @@ import com.tangem.tap.common.extensions.dispatchErrorNotification
|
||||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||||
import com.tangem.tap.common.redux.global.GlobalAction
|
import com.tangem.tap.common.redux.global.GlobalAction
|
||||||
import com.tangem.tap.domain.TapError
|
import com.tangem.tap.domain.TapError
|
||||||
import com.tangem.tap.domain.scanCard.ScanCardProcessor
|
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.features.wallet.redux.WalletState
|
import com.tangem.tap.features.wallet.redux.WalletState
|
||||||
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
||||||
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import com.tangem.tap.scope
|
import com.tangem.tap.scope
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import com.tangem.tap.userWalletsListManager
|
import com.tangem.tap.userWalletsListManager
|
||||||
|
|
@ -102,7 +102,8 @@ class MultiWalletMiddleware {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun scanAndUpdateCard(selectedUserWallet: UserWallet) = scope.launch(Dispatchers.Default) {
|
private fun scanAndUpdateCard(selectedUserWallet: UserWallet) = scope.launch(Dispatchers.Default) {
|
||||||
ScanCardProcessor.scan(selectedUserWallet.cardId, allowsRequestAccessCodeFromRepository = true)
|
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor)
|
||||||
|
.scan(cardId = selectedUserWallet.cardId, allowsRequestAccessCodeFromRepository = true)
|
||||||
.flatMap { scanResponse ->
|
.flatMap { scanResponse ->
|
||||||
userWalletsListManager.update(
|
userWalletsListManager.update(
|
||||||
userWalletId = selectedUserWallet.walletId,
|
userWalletId = selectedUserWallet.walletId,
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class TradeCryptoMiddleware {
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
exchangeManager.buyErc20TestnetTokens(
|
buyErc20TestnetTokens(
|
||||||
card = card,
|
card = card,
|
||||||
walletManager = walletManager,
|
walletManager = walletManager,
|
||||||
token = currency.token,
|
token = currency.token,
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import com.tangem.core.analytics.Analytics
|
||||||
import com.tangem.core.navigation.AppScreen
|
import com.tangem.core.navigation.AppScreen
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.datasource.connection.NetworkConnectionManager
|
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||||
|
import com.tangem.domain.userwallets.GetCardImageUseCase
|
||||||
import com.tangem.tap.*
|
import com.tangem.tap.*
|
||||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||||
import com.tangem.tap.common.analytics.events.Basic
|
import com.tangem.tap.common.analytics.events.Basic
|
||||||
|
|
@ -23,7 +24,6 @@ import com.tangem.tap.common.redux.global.GlobalAction
|
||||||
import com.tangem.tap.domain.TapError
|
import com.tangem.tap.domain.TapError
|
||||||
import com.tangem.tap.domain.model.WalletDataModel
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.domain.model.WalletStoreModel
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
import com.tangem.tap.domain.userWalletList.GetCardImageUseCase
|
|
||||||
import com.tangem.tap.domain.userWalletList.lockIfLockable
|
import com.tangem.tap.domain.userWalletList.lockIfLockable
|
||||||
import com.tangem.tap.features.demo.DemoHelper
|
import com.tangem.tap.features.demo.DemoHelper
|
||||||
import com.tangem.tap.features.home.redux.HomeAction
|
import com.tangem.tap.features.home.redux.HomeAction
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
package com.tangem.tap.features.wallet.redux.reducers
|
package com.tangem.tap.features.wallet.redux.reducers
|
||||||
|
|
||||||
import com.tangem.blockchain.common.Wallet
|
import com.tangem.blockchain.common.Wallet
|
||||||
|
import com.tangem.blockchain.common.address.AddressType
|
||||||
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
import com.tangem.domain.models.scan.CardDTO
|
||||||
|
import com.tangem.domain.userwallets.Artwork
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import com.tangem.tap.domain.TapError
|
import com.tangem.tap.domain.TapError
|
||||||
import com.tangem.tap.domain.model.WalletDataModel
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.domain.model.WalletStoreModel
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
import com.tangem.tap.features.wallet.redux.*
|
import com.tangem.tap.features.wallet.redux.ErrorType
|
||||||
|
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||||
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
|
import com.tangem.tap.features.wallet.redux.WalletState
|
||||||
import com.tangem.tap.proxy.AppStateHolder
|
import com.tangem.tap.proxy.AppStateHolder
|
||||||
import com.tangem.tap.userWalletsListManager
|
import com.tangem.tap.userWalletsListManager
|
||||||
import org.rekotlin.Action
|
import org.rekotlin.Action
|
||||||
|
|
@ -114,7 +119,7 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS
|
||||||
|
|
||||||
if (selectedUserWallet == action.userWalletId) {
|
if (selectedUserWallet == action.userWalletId) {
|
||||||
newState = newState.copy(
|
newState = newState.copy(
|
||||||
cardImage = Artwork(artworkId = action.url, artwork = newState.cardImage?.artwork),
|
cardImage = Artwork(artworkId = action.url),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +156,7 @@ fun Wallet.createAddressesData(): List<WalletDataModel.AddressData> {
|
||||||
getShareUri(it.value),
|
getShareUri(it.value),
|
||||||
getExploreUrl(it.value),
|
getExploreUrl(it.value),
|
||||||
)
|
)
|
||||||
if (it.type == blockchain.defaultAddressType()) {
|
if (it.type == AddressType.Default) {
|
||||||
listOfAddressData.add(0, addressData)
|
listOfAddressData.add(0, addressData)
|
||||||
} else {
|
} else {
|
||||||
listOfAddressData.add(addressData)
|
listOfAddressData.add(addressData)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import androidx.annotation.IdRes
|
||||||
import com.tangem.tap.common.extensions.hide
|
import com.tangem.tap.common.extensions.hide
|
||||||
import com.tangem.tap.common.extensions.show
|
import com.tangem.tap.common.extensions.show
|
||||||
import com.tangem.tap.domain.model.WalletDataModel
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedCryptoAmount
|
||||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
|
|
@ -102,8 +102,8 @@ class BalanceWidget(
|
||||||
groupBaseCurrency.show()
|
groupBaseCurrency.show()
|
||||||
tvCurrency.text = tokenWalletData?.currency?.currencySymbol
|
tvCurrency.text = tokenWalletData?.currency?.currencySymbol
|
||||||
tvBaseCurrency.text = data.currency.currencyName
|
tvBaseCurrency.text = data.currency.currencyName
|
||||||
tvAmount.text = if (showAmount) tokenWalletData?.getFormattedAmount() else ""
|
tvAmount.text = if (showAmount) tokenWalletData?.getFormattedCryptoAmount() else ""
|
||||||
tvBaseAmount.text = if (showAmount) data.getFormattedAmount() else ""
|
tvBaseAmount.text = if (showAmount) data.getFormattedCryptoAmount() else ""
|
||||||
if (showAmount) {
|
if (showAmount) {
|
||||||
tvFiatAmount.show()
|
tvFiatAmount.show()
|
||||||
tvFiatAmount.text = tokenWalletData?.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
tvFiatAmount.text = tokenWalletData?.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||||
|
|
@ -113,7 +113,7 @@ class BalanceWidget(
|
||||||
private fun showBalanceWithoutToken(data: WalletDataModel, showAmount: Boolean) = with(binding.lBalance) {
|
private fun showBalanceWithoutToken(data: WalletDataModel, showAmount: Boolean) = with(binding.lBalance) {
|
||||||
groupBaseCurrency.hide()
|
groupBaseCurrency.hide()
|
||||||
tvCurrency.text = data.currency.currencyName
|
tvCurrency.text = data.currency.currencyName
|
||||||
tvAmount.text = if (showAmount) data.getFormattedAmount() else ""
|
tvAmount.text = if (showAmount) data.getFormattedCryptoAmount() else ""
|
||||||
if (showAmount) {
|
if (showAmount) {
|
||||||
tvFiatAmount.show()
|
tvFiatAmount.show()
|
||||||
tvFiatAmount.text = data.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
tvFiatAmount.text = data.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,38 @@
|
||||||
package com.tangem.tap.features.wallet.ui
|
package com.tangem.tap.features.wallet.ui
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import com.tangem.blockchain.blockchains.bitcoin.BitcoinAddressType
|
|
||||||
import com.tangem.blockchain.blockchains.cardano.CardanoAddressType
|
|
||||||
import com.tangem.blockchain.common.Blockchain
|
import com.tangem.blockchain.common.Blockchain
|
||||||
import com.tangem.blockchain.common.address.AddressType
|
import com.tangem.blockchain.common.address.AddressType
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
|
|
||||||
object MultipleAddressUiHelper {
|
object MultipleAddressUiHelper {
|
||||||
fun typeToId(type: AddressType): Int {
|
|
||||||
return when (type) {
|
private val blockchainsSupportingSplit = listOf(
|
||||||
is BitcoinAddressType.Legacy -> R.id.chip_legacy
|
Blockchain.Bitcoin,
|
||||||
is BitcoinAddressType.Segwit -> R.id.chip_default
|
Blockchain.BitcoinTestnet,
|
||||||
is CardanoAddressType.Byron -> R.id.chip_legacy
|
Blockchain.Litecoin,
|
||||||
is CardanoAddressType.Shelley -> R.id.chip_default
|
Blockchain.BitcoinCash,
|
||||||
else -> View.NO_ID
|
Blockchain.CardanoShelley,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun typeToId(type: AddressType, blockchain: Blockchain): Int {
|
||||||
|
return if (blockchain in blockchainsSupportingSplit) {
|
||||||
|
if (type == AddressType.Legacy) {
|
||||||
|
R.id.chip_legacy
|
||||||
|
} else {
|
||||||
|
R.id.chip_default
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
View.NO_ID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun idToType(id: Int, blockchain: Blockchain?): AddressType? {
|
fun idToType(id: Int, blockchain: Blockchain): AddressType? {
|
||||||
return when (id) {
|
return when (blockchain) {
|
||||||
R.id.chip_default -> {
|
in blockchainsSupportingSplit -> {
|
||||||
when (blockchain) {
|
when (id) {
|
||||||
Blockchain.Bitcoin,
|
R.id.chip_default -> AddressType.Default
|
||||||
Blockchain.BitcoinTestnet,
|
R.id.chip_legacy -> AddressType.Legacy
|
||||||
Blockchain.Litecoin,
|
|
||||||
Blockchain.BitcoinCash,
|
|
||||||
-> BitcoinAddressType.Segwit
|
|
||||||
Blockchain.CardanoShelley -> CardanoAddressType.Shelley
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
R.id.chip_legacy -> {
|
|
||||||
when (blockchain) {
|
|
||||||
Blockchain.Bitcoin,
|
|
||||||
Blockchain.BitcoinTestnet,
|
|
||||||
Blockchain.Litecoin,
|
|
||||||
Blockchain.BitcoinCash,
|
|
||||||
-> BitcoinAddressType.Legacy
|
|
||||||
Blockchain.CardanoShelley -> CardanoAddressType.Byron
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ import com.tangem.tap.features.wallet.ui.images.load
|
||||||
import com.tangem.tap.features.wallet.ui.test.TestWallet
|
import com.tangem.tap.features.wallet.ui.test.TestWallet
|
||||||
import com.tangem.tap.features.wallet.ui.utils.assembleWarnings
|
import com.tangem.tap.features.wallet.ui.utils.assembleWarnings
|
||||||
import com.tangem.tap.features.wallet.ui.utils.getAvailableActions
|
import com.tangem.tap.features.wallet.ui.utils.getAvailableActions
|
||||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedCryptoAmount
|
||||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||||
import com.tangem.tap.features.wallet.ui.utils.isAvailableToBuy
|
import com.tangem.tap.features.wallet.ui.utils.isAvailableToBuy
|
||||||
import com.tangem.tap.features.wallet.ui.utils.isAvailableToSell
|
import com.tangem.tap.features.wallet.ui.utils.isAvailableToSell
|
||||||
|
|
@ -390,7 +390,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), SafeSt
|
||||||
chipGroupAddressType.show()
|
chipGroupAddressType.show()
|
||||||
chipGroupAddressType.fitChipsByGroupWidth()
|
chipGroupAddressType.fitChipsByGroupWidth()
|
||||||
|
|
||||||
val checkedId = MultipleAddressUiHelper.typeToId(selectedAddress.type)
|
val checkedId = MultipleAddressUiHelper.typeToId(selectedAddress.type, currency.blockchain)
|
||||||
if (checkedId != View.NO_ID) chipGroupAddressType.check(checkedId)
|
if (checkedId != View.NO_ID) chipGroupAddressType.check(checkedId)
|
||||||
|
|
||||||
chipGroupAddressType.setOnCheckedChangeListener { _, checkedId ->
|
chipGroupAddressType.setOnCheckedChangeListener { _, checkedId ->
|
||||||
|
|
@ -425,7 +425,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), SafeSt
|
||||||
lBalance.root.show()
|
lBalance.root.show()
|
||||||
lBalance.groupBalance.show()
|
lBalance.groupBalance.show()
|
||||||
lBalance.tvError.hide()
|
lBalance.tvError.hide()
|
||||||
lBalance.tvAmount.text = walletData.getFormattedAmount()
|
lBalance.tvAmount.text = walletData.getFormattedCryptoAmount()
|
||||||
lBalance.tvFiatAmount.text = walletData.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
lBalance.tvFiatAmount.text = walletData.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||||
lBalance.tvStatus.setLoadingStatus(R.string.wallet_balance_loading)
|
lBalance.tvStatus.setLoadingStatus(R.string.wallet_balance_loading)
|
||||||
}
|
}
|
||||||
|
|
@ -437,7 +437,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), SafeSt
|
||||||
lBalance.root.show()
|
lBalance.root.show()
|
||||||
lBalance.groupBalance.show()
|
lBalance.groupBalance.show()
|
||||||
lBalance.tvError.hide()
|
lBalance.tvError.hide()
|
||||||
lBalance.tvAmount.text = walletData.getFormattedAmount()
|
lBalance.tvAmount.text = walletData.getFormattedCryptoAmount()
|
||||||
lBalance.tvFiatAmount.text = walletData.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
lBalance.tvFiatAmount.text = walletData.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||||
when (status) {
|
when (status) {
|
||||||
is WalletDataModel.VerifiedOnline,
|
is WalletDataModel.VerifiedOnline,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import com.tangem.tap.common.extensions.show
|
||||||
import com.tangem.tap.domain.model.WalletDataModel
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.features.wallet.ui.images.load
|
import com.tangem.tap.features.wallet.ui.images.load
|
||||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedCryptoAmount
|
||||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatRate
|
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatRate
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
|
|
@ -85,7 +85,7 @@ class WalletAdapter : ListAdapter<WalletDataModel, WalletAdapter.WalletsViewHold
|
||||||
|
|
||||||
lContent.tvCurrency.text = wallet.currency.currencyName
|
lContent.tvCurrency.text = wallet.currency.currencyName
|
||||||
lContent.tvAmountFiat.text = wallet.getFormattedFiatAmount(fiatCurrency)
|
lContent.tvAmountFiat.text = wallet.getFormattedFiatAmount(fiatCurrency)
|
||||||
lContent.tvAmount.text = wallet.getFormattedAmount()
|
lContent.tvAmount.text = wallet.getFormattedCryptoAmount()
|
||||||
|
|
||||||
lContent.tvStatus.isVisible = statusMessage != null
|
lContent.tvStatus.isVisible = statusMessage != null
|
||||||
lContent.tvStatus.text = statusMessage
|
lContent.tvStatus.text = statusMessage
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import com.tangem.feature.swap.domain.SwapInteractor
|
||||||
import com.tangem.tap.common.entities.FiatCurrency
|
import com.tangem.tap.common.entities.FiatCurrency
|
||||||
import com.tangem.tap.common.extensions.toFiatRateString
|
import com.tangem.tap.common.extensions.toFiatRateString
|
||||||
import com.tangem.tap.common.extensions.toFiatValue
|
import com.tangem.tap.common.extensions.toFiatValue
|
||||||
import com.tangem.tap.common.extensions.toFormattedCurrencyString
|
import com.tangem.tap.common.extensions.toFormattedCryptoCurrencyString
|
||||||
import com.tangem.tap.common.extensions.toFormattedFiatValue
|
import com.tangem.tap.common.extensions.toFormattedFiatValue
|
||||||
import com.tangem.tap.domain.model.WalletDataModel
|
import com.tangem.tap.domain.model.WalletDataModel
|
||||||
import com.tangem.tap.domain.model.WalletStoreModel
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
|
|
@ -38,8 +38,8 @@ internal fun WalletDataModel.hasPendingTransactions(): Boolean {
|
||||||
return status.pendingTransactions.isEmpty()
|
return status.pendingTransactions.isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun WalletDataModel.getFormattedAmount(): String {
|
internal fun WalletDataModel.getFormattedCryptoAmount(): String {
|
||||||
return status.amount.toFormattedCurrencyString(
|
return status.amount.toFormattedCryptoCurrencyString(
|
||||||
decimals = currency.decimals,
|
decimals = currency.decimals,
|
||||||
currency = currency.currencySymbol,
|
currency = currency.currencySymbol,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,10 @@ class SingleWalletView : WalletView() {
|
||||||
(binding.lAddress.root as? ViewGroup)?.beginDelayedTransition()
|
(binding.lAddress.root as? ViewGroup)?.beginDelayedTransition()
|
||||||
chipGroupAddressType.show()
|
chipGroupAddressType.show()
|
||||||
chipGroupAddressType.fitChipsByGroupWidth()
|
chipGroupAddressType.fitChipsByGroupWidth()
|
||||||
val checkedId = MultipleAddressUiHelper.typeToId(primaryWallet.walletAddresses.selectedAddress.type)
|
val checkedId = MultipleAddressUiHelper.typeToId(
|
||||||
|
primaryWallet.walletAddresses.selectedAddress.type,
|
||||||
|
primaryWallet.currency.blockchain,
|
||||||
|
)
|
||||||
if (checkedId != View.NO_ID) chipGroupAddressType.check(checkedId)
|
if (checkedId != View.NO_ID) chipGroupAddressType.check(checkedId)
|
||||||
|
|
||||||
chipGroupAddressType.setOnCheckedChangeListener { group, checkedId ->
|
chipGroupAddressType.setOnCheckedChangeListener { group, checkedId ->
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import com.tangem.core.analytics.Analytics
|
||||||
import com.tangem.core.navigation.AppScreen
|
import com.tangem.core.navigation.AppScreen
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||||
|
import com.tangem.domain.userwallets.UserWalletIdBuilder
|
||||||
import com.tangem.domain.wallets.models.UserWallet
|
import com.tangem.domain.wallets.models.UserWallet
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
import com.tangem.tap.*
|
import com.tangem.tap.*
|
||||||
|
|
@ -18,10 +20,8 @@ import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||||
import com.tangem.tap.domain.model.WalletStoreModel
|
import com.tangem.tap.domain.model.WalletStoreModel
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletBuilder
|
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
|
|
||||||
import com.tangem.tap.domain.scanCard.ScanCardProcessor
|
|
||||||
import com.tangem.tap.domain.userWalletList.unlockIfLockable
|
import com.tangem.tap.domain.userWalletList.unlockIfLockable
|
||||||
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.firstOrNull
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
|
|
@ -126,14 +126,16 @@ internal class WalletSelectorMiddleware {
|
||||||
private fun addWallet() = scope.launch {
|
private fun addWallet() = scope.launch {
|
||||||
Analytics.send(MyWallets.Button.ScanNewCard())
|
Analytics.send(MyWallets.Button.ScanNewCard())
|
||||||
|
|
||||||
val prevUseBiometricsForAccessCode = tangemSdkManager.useBiometricsForAccessCode()
|
val cardSdkConfigRepository = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository)
|
||||||
|
|
||||||
|
val prevUseBiometricsForAccessCode = cardSdkConfigRepository.isBiometricsRequestPolicy()
|
||||||
|
|
||||||
// Update access code policy for access code saving when a card was scanned
|
// Update access code policy for access code saving when a card was scanned
|
||||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
cardSdkConfigRepository.setAccessCodeRequestPolicy(
|
||||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes,
|
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
|
||||||
)
|
)
|
||||||
|
|
||||||
ScanCardProcessor.scan(
|
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan(
|
||||||
analyticsEvent = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.MyWallets),
|
analyticsEvent = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.MyWallets),
|
||||||
onWalletNotCreated = {
|
onWalletNotCreated = {
|
||||||
// No need to rollback policy, continue with the policy set before the card scan
|
// No need to rollback policy, continue with the policy set before the card scan
|
||||||
|
|
@ -147,14 +149,14 @@ internal class WalletSelectorMiddleware {
|
||||||
saveUserWalletAndPopBackToWalletScreen(scanResponse)
|
saveUserWalletAndPopBackToWalletScreen(scanResponse)
|
||||||
.doOnFailure { error ->
|
.doOnFailure { error ->
|
||||||
// Rollback policy if card saving was failed
|
// Rollback policy if card saving was failed
|
||||||
tangemSdkManager.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
cardSdkConfigRepository.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
||||||
Timber.e(error, "Unable to save user wallet")
|
Timber.e(error, "Unable to save user wallet")
|
||||||
store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error))
|
store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFailure = { error ->
|
onFailure = { error ->
|
||||||
// Rollback policy if card scanning was failed
|
// Rollback policy if card scanning was failed
|
||||||
tangemSdkManager.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
cardSdkConfigRepository.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
||||||
Timber.e(error, "Unable to scan card")
|
Timber.e(error, "Unable to scan card")
|
||||||
store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error))
|
store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error))
|
||||||
},
|
},
|
||||||
|
|
@ -208,7 +210,7 @@ internal class WalletSelectorMiddleware {
|
||||||
private suspend fun unlockUserWalletWithScannedCard(userWallet: UserWallet): CompletionResult<Unit> {
|
private suspend fun unlockUserWalletWithScannedCard(userWallet: UserWallet): CompletionResult<Unit> {
|
||||||
Analytics.send(MyWallets.Button.WalletUnlockTapped())
|
Analytics.send(MyWallets.Button.WalletUnlockTapped())
|
||||||
tangemSdkManager.changeDisplayedCardIdNumbersCount(userWallet.scanResponse)
|
tangemSdkManager.changeDisplayedCardIdNumbersCount(userWallet.scanResponse)
|
||||||
return ScanCardProcessor.scan()
|
return store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan()
|
||||||
.map { scanResponse ->
|
.map { scanResponse ->
|
||||||
val scannedUserWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build()
|
val scannedUserWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build()
|
||||||
if (scannedUserWalletId == userWallet.walletId) {
|
if (scannedUserWalletId == userWallet.walletId) {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import com.tangem.common.flatMap
|
||||||
import com.tangem.core.navigation.AppScreen
|
import com.tangem.core.navigation.AppScreen
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||||
import com.tangem.tap.*
|
import com.tangem.tap.*
|
||||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||||
import com.tangem.tap.common.analytics.events.Basic
|
import com.tangem.tap.common.analytics.events.Basic
|
||||||
|
|
@ -15,11 +16,10 @@ import com.tangem.tap.common.extensions.dispatchOnMain
|
||||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletBuilder
|
|
||||||
import com.tangem.tap.domain.scanCard.ScanCardProcessor
|
|
||||||
import com.tangem.tap.domain.userWalletList.unlockIfLockable
|
import com.tangem.tap.domain.userWalletList.unlockIfLockable
|
||||||
import com.tangem.tap.features.intentHandler.handlers.WalletConnectLinkIntentHandler
|
import com.tangem.tap.features.intentHandler.handlers.WalletConnectLinkIntentHandler
|
||||||
import com.tangem.tap.features.signin.redux.SignInAction
|
import com.tangem.tap.features.signin.redux.SignInAction
|
||||||
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.rekotlin.Middleware
|
import org.rekotlin.Middleware
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
@ -100,10 +100,10 @@ internal class WelcomeMiddleware {
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend inline fun scanCardInternal(crossinline onCardScanned: suspend (ScanResponse) -> Unit) {
|
private suspend inline fun scanCardInternal(crossinline onCardScanned: suspend (ScanResponse) -> Unit) {
|
||||||
tangemSdkManager.setAccessCodeRequestPolicy(
|
store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
|
||||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes,
|
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
|
||||||
)
|
)
|
||||||
ScanCardProcessor.scan(
|
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan(
|
||||||
analyticsEvent = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.SignIn),
|
analyticsEvent = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.SignIn),
|
||||||
onSuccess = { scanResponse ->
|
onSuccess = { scanResponse ->
|
||||||
scope.launch { onCardScanned(scanResponse) }
|
scope.launch { onCardScanned(scanResponse) }
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
||||||
import com.tangem.tap.common.redux.global.GlobalAction
|
import com.tangem.tap.common.redux.global.GlobalAction
|
||||||
import com.tangem.tap.domain.TangemSigner
|
import com.tangem.tap.domain.TangemSigner
|
||||||
import com.tangem.tap.features.wallet.models.Currency
|
import com.tangem.tap.features.wallet.models.Currency
|
||||||
|
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import com.tangem.tap.tangemSdk
|
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -72,7 +72,7 @@ class CurrencyExchangeManager(
|
||||||
return when (action) {
|
return when (action) {
|
||||||
Action.Buy -> buyService
|
Action.Buy -> buyService
|
||||||
Action.Sell -> sellService
|
Action.Sell -> sellService
|
||||||
} as ExchangeUrlBuilder
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Action { Buy, Sell }
|
enum class Action { Buy, Sell }
|
||||||
|
|
@ -86,31 +86,26 @@ class CurrencyExchangeManager(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun CurrencyExchangeManager.buyErc20TestnetTokens(
|
suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletManager, token: Token) {
|
||||||
card: CardDTO,
|
|
||||||
walletManager: EthereumWalletManager,
|
|
||||||
token: Token,
|
|
||||||
) {
|
|
||||||
walletManager.safeUpdate()
|
walletManager.safeUpdate()
|
||||||
|
|
||||||
val amountToSend = Amount(walletManager.wallet.blockchain)
|
val amountToSend = Amount(walletManager.wallet.blockchain)
|
||||||
val destinationAddress = token.contractAddress
|
val destinationAddress = token.contractAddress
|
||||||
|
|
||||||
val feeResult =
|
val feeResult = walletManager.getFee(
|
||||||
walletManager.getFee(
|
amountToSend,
|
||||||
amountToSend,
|
destinationAddress,
|
||||||
destinationAddress,
|
) as? Result.Success ?: return
|
||||||
) as? Result.Success ?: return
|
val fee = feeResult.data.minimum
|
||||||
val fee = feeResult.data[0]
|
|
||||||
|
|
||||||
val coinValue = walletManager.wallet.amounts[AmountType.Coin]?.value ?: BigDecimal.ZERO
|
val coinValue = walletManager.wallet.amounts[AmountType.Coin]?.value ?: BigDecimal.ZERO
|
||||||
if (coinValue < fee.value) return
|
if (coinValue < fee.amount.value) return
|
||||||
|
|
||||||
val transaction = walletManager.createTransaction(amountToSend, fee, destinationAddress)
|
val transaction = walletManager.createTransaction(amountToSend, fee, destinationAddress)
|
||||||
|
|
||||||
val signer = TangemSigner(
|
val signer = TangemSigner(
|
||||||
card = card,
|
card = card,
|
||||||
tangemSdk = tangemSdk,
|
tangemSdk = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||||
initialMessage = Message(),
|
initialMessage = Message(),
|
||||||
) { signResponse ->
|
) { signResponse ->
|
||||||
store.dispatch(
|
store.dispatch(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.tangem.tap.proxy
|
package com.tangem.tap.proxy
|
||||||
|
|
||||||
import com.tangem.TangemSdk
|
|
||||||
import com.tangem.core.navigation.NavigationAction
|
import com.tangem.core.navigation.NavigationAction
|
||||||
import com.tangem.core.navigation.NavigationStateHolder
|
import com.tangem.core.navigation.NavigationStateHolder
|
||||||
import com.tangem.domain.models.scan.CardDTO
|
import com.tangem.domain.models.scan.CardDTO
|
||||||
|
|
@ -41,7 +40,6 @@ class AppStateHolder @Inject constructor() : WalletsStateHolder, NavigationState
|
||||||
var userTokensRepository: UserTokensRepository? = null
|
var userTokensRepository: UserTokensRepository? = null
|
||||||
var mainStore: Store<AppState>? = null
|
var mainStore: Store<AppState>? = null
|
||||||
var tangemSdkManager: TangemSdkManager? = null
|
var tangemSdkManager: TangemSdkManager? = null
|
||||||
var tangemSdk: TangemSdk? = null
|
|
||||||
var walletStoresManager: WalletStoresManager? = null
|
var walletStoresManager: WalletStoresManager? = null
|
||||||
var appFiatCurrency: FiatCurrency = FiatCurrency.Default
|
var appFiatCurrency: FiatCurrency = FiatCurrency.Default
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,15 @@ import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||||
import com.tangem.blockchain.blockchains.optimism.OptimismWalletManager
|
import com.tangem.blockchain.blockchains.optimism.OptimismWalletManager
|
||||||
import com.tangem.blockchain.common.*
|
import com.tangem.blockchain.common.*
|
||||||
|
import com.tangem.blockchain.common.transaction.Fee
|
||||||
|
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||||
import com.tangem.blockchain.extensions.Result
|
import com.tangem.blockchain.extensions.Result
|
||||||
import com.tangem.blockchain.extensions.SimpleResult
|
import com.tangem.blockchain.extensions.SimpleResult
|
||||||
import com.tangem.blockchain.extensions.isNetworkError
|
import com.tangem.blockchain.extensions.isNetworkError
|
||||||
import com.tangem.common.core.TangemSdkError
|
import com.tangem.common.core.TangemSdkError
|
||||||
import com.tangem.common.extensions.hexToBytes
|
import com.tangem.common.extensions.hexToBytes
|
||||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||||
|
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||||
import com.tangem.domain.common.BlockchainNetwork
|
import com.tangem.domain.common.BlockchainNetwork
|
||||||
import com.tangem.domain.common.extensions.fromNetworkId
|
import com.tangem.domain.common.extensions.fromNetworkId
|
||||||
import com.tangem.lib.crypto.TransactionManager
|
import com.tangem.lib.crypto.TransactionManager
|
||||||
|
|
@ -22,7 +25,6 @@ import com.tangem.tap.common.analytics.events.Basic
|
||||||
import com.tangem.tap.common.analytics.events.Basic.TransactionSent.MemoType
|
import com.tangem.tap.common.analytics.events.Basic.TransactionSent.MemoType
|
||||||
import com.tangem.tap.common.redux.global.GlobalAction
|
import com.tangem.tap.common.redux.global.GlobalAction
|
||||||
import com.tangem.tap.domain.TangemSigner
|
import com.tangem.tap.domain.TangemSigner
|
||||||
import com.tangem.tap.tangemSdk
|
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.math.MathContext
|
import java.math.MathContext
|
||||||
|
|
@ -32,6 +34,7 @@ import java.math.RoundingMode
|
||||||
class TransactionManagerImpl(
|
class TransactionManagerImpl(
|
||||||
private val appStateHolder: AppStateHolder,
|
private val appStateHolder: AppStateHolder,
|
||||||
private val analytics: AnalyticsEventHandler,
|
private val analytics: AnalyticsEventHandler,
|
||||||
|
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||||
) : TransactionManager {
|
) : TransactionManager {
|
||||||
|
|
||||||
override suspend fun sendApproveTransaction(
|
override suspend fun sendApproveTransaction(
|
||||||
|
|
@ -112,7 +115,7 @@ class TransactionManagerImpl(
|
||||||
): SendTxResult {
|
): SendTxResult {
|
||||||
val txData = walletManager.createTransaction(
|
val txData = walletManager.createTransaction(
|
||||||
amount = amount,
|
amount = amount,
|
||||||
fee = Amount(value = feeAmount, blockchain = blockchain),
|
fee = Fee.Common(Amount(value = feeAmount, blockchain = blockchain)),
|
||||||
destination = destinationAddress,
|
destination = destinationAddress,
|
||||||
).copy(hash = dataToSign, extras = createExtras(walletManager, gasLimit, dataToSign))
|
).copy(hash = dataToSign, extras = createExtras(walletManager, gasLimit, dataToSign))
|
||||||
|
|
||||||
|
|
@ -214,24 +217,37 @@ class TransactionManagerImpl(
|
||||||
return when (fee) {
|
return when (fee) {
|
||||||
is Result.Success -> {
|
is Result.Success -> {
|
||||||
// for not EVM blockchains set gasLimit ZERO for now
|
// for not EVM blockchains set gasLimit ZERO for now
|
||||||
val firstFee = fee.data.firstOrNull() ?: error("no fee found")
|
when (fee.data) {
|
||||||
val minFee = ProxyFee(
|
is TransactionFee.Single -> {
|
||||||
gasLimit = BigInteger.ZERO,
|
val fee = (fee.data as TransactionFee.Single).normal
|
||||||
fee = convertToProxyAmount(amount = firstFee),
|
val singleFee = ProxyFee(
|
||||||
)
|
gasLimit = BigInteger.ZERO,
|
||||||
val normalFee = ProxyFee(
|
fee = convertToProxyAmount(amount = fee.amount),
|
||||||
gasLimit = BigInteger.ZERO,
|
)
|
||||||
fee = convertToProxyAmount(fee.data.getOrNull(index = 1) ?: firstFee),
|
ProxyFees(
|
||||||
)
|
minFee = singleFee,
|
||||||
val priorityFee = ProxyFee(
|
normalFee = singleFee,
|
||||||
gasLimit = BigInteger.ZERO,
|
priorityFee = singleFee,
|
||||||
fee = convertToProxyAmount(fee.data.getOrNull(index = 2) ?: firstFee),
|
)
|
||||||
)
|
}
|
||||||
ProxyFees(
|
is TransactionFee.Choosable -> {
|
||||||
minFee = minFee,
|
val choosableFee = fee.data as TransactionFee.Choosable
|
||||||
normalFee = normalFee,
|
ProxyFees(
|
||||||
priorityFee = priorityFee,
|
minFee = ProxyFee(
|
||||||
)
|
gasLimit = BigInteger.ZERO,
|
||||||
|
fee = convertToProxyAmount(amount = choosableFee.minimum.amount),
|
||||||
|
),
|
||||||
|
normalFee = ProxyFee(
|
||||||
|
gasLimit = BigInteger.ZERO,
|
||||||
|
fee = convertToProxyAmount(amount = choosableFee.normal.amount),
|
||||||
|
),
|
||||||
|
priorityFee = ProxyFee(
|
||||||
|
gasLimit = BigInteger.ZERO,
|
||||||
|
fee = convertToProxyAmount(amount = choosableFee.priority.amount),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is Result.Failure -> {
|
is Result.Failure -> {
|
||||||
error(fee.error.message ?: fee.error.customMessage)
|
error(fee.error.message ?: fee.error.customMessage)
|
||||||
|
|
@ -280,19 +296,21 @@ class TransactionManagerImpl(
|
||||||
}
|
}
|
||||||
return when (fee) {
|
return when (fee) {
|
||||||
is Result.Success -> {
|
is Result.Success -> {
|
||||||
val minFee = fee.data.firstOrNull() ?: error("no fee found")
|
val choosableFee = fee.data
|
||||||
|
|
||||||
val minProxyFee = ProxyFee(
|
val minProxyFee = ProxyFee(
|
||||||
gasLimit = walletManager.gasLimit ?: BigInteger.ZERO,
|
gasLimit = (choosableFee.minimum as Fee.Ethereum).gasLimit,
|
||||||
fee = convertToProxyAmount(minFee),
|
fee = convertToProxyAmount(amount = choosableFee.minimum.amount),
|
||||||
)
|
)
|
||||||
val normalProxyFee = ProxyFee(
|
val normalProxyFee = ProxyFee(
|
||||||
gasLimit = walletManager.gasLimit ?: BigInteger.ZERO,
|
gasLimit = (choosableFee.normal as Fee.Ethereum).gasLimit,
|
||||||
fee = convertToProxyAmount(fee.data.getOrNull(index = 1) ?: minFee),
|
fee = convertToProxyAmount(amount = choosableFee.normal.amount),
|
||||||
)
|
)
|
||||||
val priorityProxyFee = ProxyFee(
|
val priorityProxyFee = ProxyFee(
|
||||||
gasLimit = walletManager.gasLimit ?: BigInteger.ZERO,
|
gasLimit = (choosableFee.priority as Fee.Ethereum).gasLimit,
|
||||||
fee = convertToProxyAmount(fee.data.lastOrNull() ?: minFee),
|
fee = convertToProxyAmount(amount = choosableFee.priority.amount),
|
||||||
)
|
)
|
||||||
|
|
||||||
ProxyFees(
|
ProxyFees(
|
||||||
minFee = minProxyFee,
|
minFee = minProxyFee,
|
||||||
normalFee = normalProxyFee,
|
normalFee = normalProxyFee,
|
||||||
|
|
@ -378,7 +396,7 @@ class TransactionManagerImpl(
|
||||||
val actualCard = requireNotNull(appStateHolder.getActualCard()) { "no card found" }
|
val actualCard = requireNotNull(appStateHolder.getActualCard()) { "no card found" }
|
||||||
return TangemSigner(
|
return TangemSigner(
|
||||||
card = actualCard,
|
card = actualCard,
|
||||||
tangemSdk = tangemSdk,
|
tangemSdk = cardSdkConfigRepository.sdk,
|
||||||
initialMessage = Message(),
|
initialMessage = Message(),
|
||||||
) { signResponse ->
|
) { signResponse ->
|
||||||
appStateHolder.mainStore?.dispatch(
|
appStateHolder.mainStore?.dispatch(
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import com.tangem.domain.common.BlockchainNetwork
|
||||||
import com.tangem.domain.common.extensions.fromNetworkId
|
import com.tangem.domain.common.extensions.fromNetworkId
|
||||||
import com.tangem.domain.common.extensions.toCoinId
|
import com.tangem.domain.common.extensions.toCoinId
|
||||||
import com.tangem.domain.common.extensions.toNetworkId
|
import com.tangem.domain.common.extensions.toNetworkId
|
||||||
|
import com.tangem.domain.userwallets.UserWalletIdBuilder
|
||||||
import com.tangem.lib.crypto.UserWalletManager
|
import com.tangem.lib.crypto.UserWalletManager
|
||||||
import com.tangem.lib.crypto.models.Currency
|
import com.tangem.lib.crypto.models.Currency
|
||||||
import com.tangem.lib.crypto.models.Currency.NativeToken
|
import com.tangem.lib.crypto.models.Currency.NativeToken
|
||||||
|
|
@ -17,7 +18,6 @@ import com.tangem.lib.crypto.models.Currency.NonNativeToken
|
||||||
import com.tangem.lib.crypto.models.ProxyAmount
|
import com.tangem.lib.crypto.models.ProxyAmount
|
||||||
import com.tangem.lib.crypto.models.ProxyFiatCurrency
|
import com.tangem.lib.crypto.models.ProxyFiatCurrency
|
||||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||||
import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
|
|
||||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||||
import com.tangem.tap.userWalletsListManager
|
import com.tangem.tap.userWalletsListManager
|
||||||
import com.tangem.tap.walletCurrenciesManager
|
import com.tangem.tap.walletCurrenciesManager
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.proxy.di
|
||||||
|
|
||||||
import androidx.compose.ui.text.intl.Locale
|
import androidx.compose.ui.text.intl.Locale
|
||||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||||
|
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||||
import com.tangem.domain.common.CardTypesResolver
|
import com.tangem.domain.common.CardTypesResolver
|
||||||
import com.tangem.domain.common.util.cardTypesResolver
|
import com.tangem.domain.common.util.cardTypesResolver
|
||||||
import com.tangem.feature.learn2earn.domain.api.Learn2earnDependencyProvider
|
import com.tangem.feature.learn2earn.domain.api.Learn2earnDependencyProvider
|
||||||
|
|
@ -43,8 +44,13 @@ class ProxyModule {
|
||||||
fun provideTransactionManager(
|
fun provideTransactionManager(
|
||||||
appStateHolder: AppStateHolder,
|
appStateHolder: AppStateHolder,
|
||||||
analytics: AnalyticsEventHandler,
|
analytics: AnalyticsEventHandler,
|
||||||
|
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||||
): TransactionManager {
|
): TransactionManager {
|
||||||
return TransactionManagerImpl(appStateHolder, analytics)
|
return TransactionManagerImpl(
|
||||||
|
appStateHolder = appStateHolder,
|
||||||
|
analytics = analytics,
|
||||||
|
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.tap.proxy.redux
|
package com.tangem.tap.proxy.redux
|
||||||
|
|
||||||
import com.tangem.domain.card.ScanCardUseCase
|
import com.tangem.domain.card.ScanCardUseCase
|
||||||
|
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||||
import com.tangem.features.tester.api.TesterRouter
|
import com.tangem.features.tester.api.TesterRouter
|
||||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||||
import com.tangem.features.wallet.navigation.WalletRouter
|
import com.tangem.features.wallet.navigation.WalletRouter
|
||||||
|
|
@ -15,5 +16,6 @@ sealed interface DaggerGraphAction : Action {
|
||||||
val walletRouter: WalletRouter,
|
val walletRouter: WalletRouter,
|
||||||
val walletConnectInteractor: WalletConnectInteractor,
|
val walletConnectInteractor: WalletConnectInteractor,
|
||||||
val tokenDetailsRouter: TokenDetailsRouter,
|
val tokenDetailsRouter: TokenDetailsRouter,
|
||||||
|
val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||||
) : DaggerGraphAction
|
) : DaggerGraphAction
|
||||||
}
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ object DaggerGraphReducer {
|
||||||
walletRouter = action.walletRouter,
|
walletRouter = action.walletRouter,
|
||||||
walletConnectInteractor = action.walletConnectInteractor,
|
walletConnectInteractor = action.walletConnectInteractor,
|
||||||
tokenDetailsRouter = action.tokenDetailsRouter,
|
tokenDetailsRouter = action.tokenDetailsRouter,
|
||||||
|
cardSdkConfigRepository = action.cardSdkConfigRepository,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ package com.tangem.tap.proxy.redux
|
||||||
|
|
||||||
import com.tangem.datasource.asset.AssetReader
|
import com.tangem.datasource.asset.AssetReader
|
||||||
import com.tangem.datasource.connection.NetworkConnectionManager
|
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||||
|
import com.tangem.domain.card.ScanCardProcessor
|
||||||
import com.tangem.domain.card.ScanCardUseCase
|
import com.tangem.domain.card.ScanCardUseCase
|
||||||
|
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||||
import com.tangem.features.tester.api.TesterRouter
|
import com.tangem.features.tester.api.TesterRouter
|
||||||
import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles
|
import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles
|
||||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||||
|
|
@ -27,6 +29,8 @@ data class DaggerGraphState(
|
||||||
val walletConnectInteractor: WalletConnectInteractor? = null,
|
val walletConnectInteractor: WalletConnectInteractor? = null,
|
||||||
val tokenDetailsFeatureToggles: TokenDetailsFeatureToggles? = null,
|
val tokenDetailsFeatureToggles: TokenDetailsFeatureToggles? = null,
|
||||||
val tokenDetailsRouter: TokenDetailsRouter? = null,
|
val tokenDetailsRouter: TokenDetailsRouter? = null,
|
||||||
|
val scanCardProcessor: ScanCardProcessor? = null,
|
||||||
|
val cardSdkConfigRepository: CardSdkConfigRepository? = null,
|
||||||
) : StateType {
|
) : StateType {
|
||||||
|
|
||||||
inline fun <reified T> get(getDependency: DaggerGraphState.() -> T?): T {
|
inline fun <reified T> get(getDependency: DaggerGraphState.() -> T?): T {
|
||||||
|
|
|
||||||
BIN
buildSrc/build/libs/buildSrc.jar
Normal file
BIN
buildSrc/build/libs/buildSrc.jar
Normal file
Binary file not shown.
|
|
@ -13,5 +13,7 @@ dependencies {
|
||||||
kapt(deps.hilt.kapt)
|
kapt(deps.hilt.kapt)
|
||||||
|
|
||||||
/** Core shouldn't depends on core, but in case with utils and logging its necessary */
|
/** Core shouldn't depends on core, but in case with utils and logging its necessary */
|
||||||
implementation(project(":core:utils"))
|
implementation(projects.core.utils)
|
||||||
|
|
||||||
|
implementation(projects.core.analytics.models)
|
||||||
}
|
}
|
||||||
1
core/analytics/models/.gitignore
vendored
Normal file
1
core/analytics/models/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
||||||
4
core/analytics/models/build.gradle.kts
Normal file
4
core/analytics/models/build.gradle.kts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
plugins {
|
||||||
|
alias(deps.plugins.kotlin.jvm)
|
||||||
|
id("configuration")
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.tangem.core.analytics
|
package com.tangem.core.analytics.models
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
@ -1,18 +1,9 @@
|
||||||
package com.tangem.core.analytics
|
package com.tangem.core.analytics
|
||||||
|
|
||||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
import com.tangem.core.analytics.api.*
|
||||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
import com.tangem.core.analytics.api.AnalyticsFilterHolder
|
|
||||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
|
||||||
import com.tangem.core.analytics.api.AnalyticsHandlerHolder
|
|
||||||
import com.tangem.core.analytics.api.ParamsInterceptor
|
|
||||||
import com.tangem.core.analytics.api.ParamsInterceptorHolder
|
|
||||||
import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler
|
import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler
|
||||||
import kotlinx.coroutines.CoroutineName
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.SupervisorJob
|
|
||||||
import kotlinx.coroutines.asCoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.core.analytics.api
|
package com.tangem.core.analytics.api
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.core.analytics.api
|
package com.tangem.core.analytics.api
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.tangem.core.analytics.api
|
package com.tangem.core.analytics.api
|
||||||
|
|
||||||
import com.tangem.core.analytics.AnalyticsEvent
|
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ dependencies {
|
||||||
implementation(deps.moshi)
|
implementation(deps.moshi)
|
||||||
implementation(deps.moshi.kotlin)
|
implementation(deps.moshi.kotlin)
|
||||||
implementation(deps.okHttp)
|
implementation(deps.okHttp)
|
||||||
implementation(deps.okHttp.logging)
|
implementation(deps.okHttp.prettyLogging)
|
||||||
implementation(deps.retrofit)
|
implementation(deps.retrofit)
|
||||||
implementation(deps.retrofit.moshi)
|
implementation(deps.retrofit.moshi)
|
||||||
implementation(deps.reactive.network)
|
implementation(deps.reactive.network)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
package com.tangem.datasource.api.common
|
package com.tangem.datasource.api.common
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.ihsanbal.logging.Level
|
||||||
|
import com.ihsanbal.logging.LoggingInterceptor
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
@ -22,7 +24,7 @@ fun createRetrofitInstance(
|
||||||
}
|
}
|
||||||
interceptors.forEach { okHttpBuilder.addInterceptor(it) }
|
interceptors.forEach { okHttpBuilder.addInterceptor(it) }
|
||||||
|
|
||||||
if (logEnabled) okHttpBuilder.addInterceptor(createHttpLoggingInterceptor())
|
if (logEnabled) okHttpBuilder.addInterceptor(createNetworkLoggingInterceptor())
|
||||||
|
|
||||||
return Retrofit.Builder()
|
return Retrofit.Builder()
|
||||||
.baseUrl(baseUrl)
|
.baseUrl(baseUrl)
|
||||||
|
|
@ -31,6 +33,9 @@ fun createRetrofitInstance(
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createHttpLoggingInterceptor(): HttpLoggingInterceptor = HttpLoggingInterceptor().apply {
|
fun createNetworkLoggingInterceptor(): Interceptor {
|
||||||
level = HttpLoggingInterceptor.Level.BODY
|
return LoggingInterceptor.Builder()
|
||||||
|
.setLevel(Level.BODY)
|
||||||
|
.log(Log.VERBOSE)
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.tangem.datasource.di
|
||||||
|
|
||||||
|
import com.tangem.datasource.local.cache.CacheKeysStore
|
||||||
|
import com.tangem.datasource.local.cache.RuntimeCacheKeysStore
|
||||||
|
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 CacheKeysStoreModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideCacheKeysStore(): CacheKeysStore {
|
||||||
|
return RuntimeCacheKeysStore()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -63,9 +63,7 @@ class NetworkModule {
|
||||||
@PromotionOneInch
|
@PromotionOneInch
|
||||||
fun providePromotionOneInchApi(authProvider: AuthProvider, @NetworkMoshi moshi: Moshi): PromotionApi {
|
fun providePromotionOneInchApi(authProvider: AuthProvider, @NetworkMoshi moshi: Moshi): PromotionApi {
|
||||||
val okClient = OkHttpClient.Builder()
|
val okClient = OkHttpClient.Builder()
|
||||||
.addHeaders(
|
.addHeaders(AuthenticationHeader(authProvider))
|
||||||
AuthenticationHeader(authProvider),
|
|
||||||
)
|
|
||||||
.allowLogging()
|
.allowLogging()
|
||||||
.callTimeout(API_ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
|
.callTimeout(API_ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
|
||||||
.connectTimeout(API_ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
|
.connectTimeout(API_ONE_INCH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
|
||||||
|
|
|
||||||
14
core/datasource/src/main/java/com/tangem/datasource/local/cache/CacheKeysStore.kt
vendored
Normal file
14
core/datasource/src/main/java/com/tangem/datasource/local/cache/CacheKeysStore.kt
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.tangem.datasource.local.cache
|
||||||
|
|
||||||
|
import com.tangem.datasource.local.cache.model.CacheKey
|
||||||
|
|
||||||
|
interface CacheKeysStore {
|
||||||
|
|
||||||
|
fun get(id: String): CacheKey?
|
||||||
|
|
||||||
|
fun addOrReplace(key: CacheKey)
|
||||||
|
|
||||||
|
fun remove(id: String)
|
||||||
|
|
||||||
|
fun clear()
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue