Updated on 2026-08-14

This commit is contained in:
Tangem 2024-11-29 12:53:30 +03:00
commit 82c92f8180
639 changed files with 18827 additions and 2682 deletions

View file

@ -37,5 +37,7 @@ sealed class WalletConnectAction : Action {
data class PerformRequestedAction(val sessionRequest: WcPreparedRequest) : WalletConnectAction()
data class PairConnectErrorAction(val throwable: Throwable) : WalletConnectAction()
data object UnsupportedDappRequest : WalletConnectAction()
//endregion WalletConnect 2.0
}

View file

@ -78,6 +78,12 @@ class WalletConnectMiddleware {
val index = action.wcUri.indexOf("@")
when (action.wcUri[index + 1]) {
'2' -> walletConnectRepository.pair(uri = action.wcUri)
'1' -> {
store.dispatchOnMain(WalletConnectAction.UnsupportedDappRequest)
store.dispatchOnMain(
GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedWcVersion),
)
}
}
}
is WalletConnectAction.RejectRequest -> {

View file

@ -15,6 +15,7 @@ object WalletConnectReducer {
is WalletConnectAction.SessionEstablished,
is WalletConnectAction.SessionRejected,
is WalletConnectAction.PairConnectErrorAction,
is WalletConnectAction.UnsupportedDappRequest,
-> state.copy(loading = false)
is WalletConnectAction.SessionListUpdated -> state.copy(
wc2Sessions = action.sessions,

View file

@ -82,6 +82,7 @@ data class WalletForSession(
}
sealed class WalletConnectDialog : StateDialog {
data object UnsupportedWcVersion : WalletConnectDialog()
data class ClipboardOrScanQr(val clipboardUri: String) : WalletConnectDialog()
data object UnsupportedCard : WalletConnectDialog()
data class UnsupportedNetwork(val networks: List<String>? = null) : WalletConnectDialog()

View file

@ -1,6 +1,6 @@
package com.tangem.tap.features.home.featuretoggles
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
import javax.inject.Inject
class HomeFeatureToggles @Inject constructor(

View file

@ -0,0 +1,24 @@
package com.tangem.tap.features.intentHandler.handlers
import android.content.Intent
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.tap.common.analytics.events.Push
import com.tangem.tap.features.intentHandler.IntentHandler
internal class OnPushClickedIntentHandler(val analyticsEventHandler: AnalyticsEventHandler) : IntentHandler {
override fun handleIntent(intent: Intent?, isFromForeground: Boolean): Boolean {
val fromPush = intent?.extras?.getBoolean(IS_OPENED_FROM_PUSH) ?: false
return if (fromPush) {
analyticsEventHandler.send(Push.PushNotificationOpened)
true
} else {
false
}
}
companion object {
const val IS_OPENED_FROM_PUSH = "IS_OPENED_FROM_PUSH"
}
}

View file

@ -17,7 +17,6 @@ import com.tangem.domain.settings.IncrementAppLaunchCounterUseCase
import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase
import com.tangem.domain.staking.FetchStakingTokensUseCase
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
import com.tangem.tap.common.extensions.setContext
import com.tangem.tap.features.home.featuretoggles.HomeFeatureToggles
import com.tangem.tap.features.main.model.MainScreenState
@ -40,7 +39,6 @@ internal class MainViewModel @Inject constructor(
private val blockchainSDKFactory: BlockchainSDKFactory,
private val userWalletsListManager: UserWalletsListManager,
private val dispatchers: CoroutineDispatcherProvider,
stakingFeatureToggles: StakingFeatureToggles,
private val fetchStakingTokensUseCase: FetchStakingTokensUseCase,
private val apiConfigsManager: ApiConfigsManager,
homeFeatureToggles: HomeFeatureToggles,
@ -78,9 +76,7 @@ internal class MainViewModel @Inject constructor(
displayBalancesHidingStatusToast()
displayHiddenBalancesModalNotification()
if (stakingFeatureToggles.isStakingEnabled) {
fetchStakingTokens()
}
fetchStakingTokens()
deleteDeprecatedLogsUseCase()
}

View file

@ -16,6 +16,7 @@ import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.settings.usercountry.models.UserCountry
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.builder.UserWalletIdBuilder
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Onboarding
@ -23,8 +24,8 @@ import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.common.redux.global.GlobalState
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction
import com.tangem.tap.features.saveWallet.redux.SaveWalletAction
import com.tangem.tap.mainScope
import com.tangem.tap.proxy.redux.DaggerGraphState
@ -67,7 +68,10 @@ object OnboardingHelper {
fun whereToNavigate(scanResponse: ScanResponse): AppRoute {
if (store.inject(DaggerGraphState::onboardingV2FeatureToggles).isOnboardingV2Enabled) {
return AppRoute.Onboarding(scanResponse)
return AppRoute.Onboarding(
scanResponse = scanResponse,
startFromBackup = false,
)
}
return when (val type = scanResponse.productType) {
@ -88,6 +92,7 @@ object OnboardingHelper {
}
fun saveWallet(
alreadyCreatedWallet: UserWallet?,
scanResponse: ScanResponse,
accessCode: String? = null,
backupCardsIds: List<String>? = null,
@ -117,7 +122,7 @@ object OnboardingHelper {
// When should not save user wallets but device has biometry and save wallet screen has not been shown,
// then open save wallet screen
tangemSdkManager.checkCanUseBiometry() && settingsRepository.shouldShowSaveUserWalletScreen() -> {
proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError)
proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError, alreadyCreatedWallet)
delay(timeMillis = 1_200)
@ -131,7 +136,7 @@ object OnboardingHelper {
}
// If device has no biometry and save wallet screen has been shown, then go through old scenario
else -> {
proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError)
proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError, alreadyCreatedWallet)
}
}
}
@ -207,7 +212,9 @@ object OnboardingHelper {
fun handleTopUpAction(walletManager: WalletManager, scanResponse: ScanResponse, globalState: GlobalState) {
val blockchain = walletManager.wallet.blockchain
val cryptoCurrency = CryptoCurrencyFactory().createCoin(
val excludedBlockchains = store.inject(DaggerGraphState::excludedBlockchains)
val cryptoCurrency = CryptoCurrencyFactory(excludedBlockchains).createCoin(
blockchain = blockchain,
extraDerivationPath = null,
scanResponse = scanResponse,
@ -242,9 +249,10 @@ object OnboardingHelper {
scanResponse: ScanResponse,
backupCardsIds: List<String>?,
hasBackupError: Boolean,
alreadyCreatedWallet: UserWallet? = null,
) {
val walletNameGenerateUseCase = store.inject(DaggerGraphState::generateWalletNameUseCase)
val userWallet = UserWalletBuilder(scanResponse, walletNameGenerateUseCase)
val userWallet = alreadyCreatedWallet ?: UserWalletBuilder(scanResponse, walletNameGenerateUseCase)
.hasBackupError(hasBackupError)
.backupCardsIds(backupCardsIds?.toSet())
.build()

View file

@ -197,11 +197,11 @@ private fun handleWalletAction(action: Action) {
}
}
private fun handleFinishBackup(scanResponse: ScanResponse) {
private fun handleFinishBackup(scanResponse: ScanResponse, userWallet: UserWallet? = null) {
val backupState = store.state.onboardingWalletState.backupState
val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState)
val userWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build()
val userWalletId = userWallet?.walletId ?: UserWalletIdBuilder.scanResponse(scanResponse).build()
if (backupState.hasRing && userWalletId != null) {
scope.launch {
store.inject(DaggerGraphState::walletsRepository).setHasWalletsWithRing(userWalletId = userWalletId)
@ -209,6 +209,7 @@ private fun handleFinishBackup(scanResponse: ScanResponse) {
}
OnboardingHelper.saveWallet(
alreadyCreatedWallet = userWallet,
scanResponse = updatedScanResponse,
accessCode = backupState.accessCode,
backupCardsIds = backupState.backupCardIds,
@ -679,7 +680,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
Analytics.send(Onboarding.Finished())
store.state.globalState.onboardingState.onboardingManager?.finishActivation(notActivatedCardIds)
handleFinishBackup(requireNotNull(scanResponse))
handleFinishBackup(requireNotNull(scanResponse), userWallet)
delay(1000)
store.dispatchWithMain(BackupAction.BackupFinished(userWalletId = userWallet?.walletId))
}
@ -740,6 +741,7 @@ private suspend fun createUserWallet(scanResponse: ScanResponse, backupState: Ba
return requireNotNull(
value = UserWalletBuilder(scanResponse, walletNameGenerateUseCase)
.backupCardsIds(backupState.backupCardIds.toSet())
.hasBackupError(backupState.hasBackupError)
.build(),
lazyMessage = { "User wallet not created" },
)

View file

@ -272,6 +272,7 @@ class OnboardingWalletFragment :
onboardingManageTokensComponent = onboardingManageTokensComponentFactory.create(
context = onboardingComponentContext,
params = OnboardingManageTokensComponent.Params(userWalletId = userWalletId),
onDone = {},
)
}

View file

@ -5,11 +5,11 @@ import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.guard
import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.tap.*
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.MainScreen
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.extensions.dispatchWithMain
@ -110,7 +110,11 @@ internal class SaveWalletMiddleware {
// TODO: Remove after onboarding refactoring
Analytics.send(Onboarding.EnableBiometrics(AnalyticsParam.OnOffState.On))
} else {
Analytics.send(MainScreen.EnableBiometrics(AnalyticsParam.OnOffState.On))
Analytics.send(
MainScreenAnalyticsEvent.EnableBiometrics(
state = com.tangem.core.analytics.models.AnalyticsParam.OnOffState.On,
),
)
}
/*
@ -148,7 +152,11 @@ internal class SaveWalletMiddleware {
// TODO: Remove after onboarding refactoring
Analytics.send(Onboarding.EnableBiometrics(AnalyticsParam.OnOffState.Off))
} else {
Analytics.send(MainScreen.EnableBiometrics(AnalyticsParam.OnOffState.Off))
Analytics.send(
MainScreenAnalyticsEvent.EnableBiometrics(
com.tangem.core.analytics.models.AnalyticsParam.OnOffState.Off,
),
)
}
}

View file

@ -55,11 +55,15 @@ object TradeCryptoMiddleware {
private fun proceedBuyAction(state: () -> AppState?, action: TradeCryptoAction.Buy) {
val isOnrampEnabled = store.inject(DaggerGraphState::onrampFeatureToggles).isFeatureEnabled
if (isOnrampEnabled) proceedWithOnramp() else proceedWithLegacyBuyAction(state, action)
if (isOnrampEnabled) {
proceedWithOnramp(action.userWallet.walletId, action.cryptoCurrencyStatus.currency)
} else {
proceedWithLegacyBuyAction(state, action)
}
}
private fun proceedWithOnramp() {
store.dispatchNavigationAction { push(AppRoute.Onramp) }
private fun proceedWithOnramp(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency) {
store.dispatchNavigationAction { push(AppRoute.Onramp(userWalletId = userWalletId, currency = cryptoCurrency)) }
}
private fun proceedWithLegacyBuyAction(state: () -> AppState?, action: TradeCryptoAction.Buy) {