Updated on 2026-08-14

This commit is contained in:
Tangem 2023-12-04 16:46:41 +03:00
commit 512ab6d54d
206 changed files with 8933 additions and 630 deletions

View file

@ -14,6 +14,7 @@ import com.tangem.blockchain.common.BlockchainSdkConfig
import com.tangem.blockchain.common.WalletManagerFactory
import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.filter.OneTimeEventFilter
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
import com.tangem.data.source.preferences.PreferencesDataSource
import com.tangem.datasource.api.common.MoshiConverter
@ -216,6 +217,9 @@ internal class TapApplication : Application(), ImageLoaderFactory {
@Inject
lateinit var sendFeatureToggles: SendFeatureToggles
@Inject
lateinit var oneTimeEventFilter: OneTimeEventFilter
// endregion Injected
override fun onCreate() {
@ -353,6 +357,8 @@ internal class TapApplication : Application(), ImageLoaderFactory {
factory.addHandlerBuilder(AppsFlyerAnalyticsHandler.Builder())
factory.addHandlerBuilder(FirebaseAnalyticsHandler.Builder())
factory.addFilter(oneTimeEventFilter)
val buildData = AnalyticsHandlerBuilder.Data(
application = application,
config = config,

View file

@ -9,8 +9,8 @@ class AmplitudeAnalyticsHandler(
override fun id(): String = ID
override fun send(event: String, params: Map<String, String>) {
client.logEvent(event, params)
override fun send(eventId: String, params: Map<String, String>) {
client.logEvent(eventId, params)
}
companion object {

View file

@ -12,8 +12,8 @@ class AppsFlyerAnalyticsHandler(
override fun id(): String = ID
override fun send(event: String, params: Map<String, String>) {
client.logEvent(event, params)
override fun send(eventId: String, params: Map<String, String>) {
client.logEvent(eventId, params)
}
override fun send(event: AnalyticsEvent) {

View file

@ -14,8 +14,8 @@ class FirebaseAnalyticsHandler(
override fun id(): String = ID
override fun send(event: String, params: Map<String, String>) {
client.logEvent(event, params)
override fun send(eventId: String, params: Map<String, String>) {
client.logEvent(eventId, params)
}
override fun send(event: AnalyticsEvent) {

View file

@ -91,4 +91,16 @@ internal object SettingsDomainModule {
): UpdateBalanceHidingSettingsUseCase {
return UpdateBalanceHidingSettingsUseCase(balanceHidingRepository)
}
@Provides
@ViewModelScoped
fun provideSetWalletsScrollPreviewIsShown(settingsRepository: SettingsRepository): NeverToShowWalletsScrollPreview {
return NeverToShowWalletsScrollPreview(settingsRepository = settingsRepository)
}
@Provides
@ViewModelScoped
fun provideIsWalletsScrollPreviewEnabled(settingsRepository: SettingsRepository): IsWalletsScrollPreviewEnabled {
return IsWalletsScrollPreviewEnabled(settingsRepository = settingsRepository)
}
}

View file

@ -2,10 +2,7 @@ package com.tangem.tap.di.domain
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.tokens.*
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.MarketCryptoCurrencyRepository
import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.tokens.repository.*
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
@ -231,4 +228,10 @@ internal object TokensDomainModule {
): GetMissedAddressesCryptoCurrenciesUseCase {
return GetMissedAddressesCryptoCurrenciesUseCase(currenciesRepository = currenciesRepository)
}
@Provides
@ViewModelScoped
fun provideGetGlobalTokenListUseCase(tokensListRepository: TokensListRepository): GetGlobalTokenListUseCase {
return GetGlobalTokenListUseCase(repository = tokensListRepository)
}
}

View file

@ -1,6 +1,9 @@
package com.tangem.tap.di.domain
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.transaction.usecase.GetFeeUseCase
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
@ -15,10 +18,25 @@ internal object TransactionDomainModule {
@Provides
@ViewModelScoped
fun provideGetUseCase(
fun provideGetFeeUseCase(
walletManagersFacade: WalletManagersFacade,
dispatchers: CoroutineDispatcherProvider,
): GetFeeUseCase {
return GetFeeUseCase(walletManagersFacade, dispatchers)
}
@Provides
@ViewModelScoped
fun provideSendTransactionUseCase(
isDemoCardUseCase: IsDemoCardUseCase,
walletManagersFacade: WalletManagersFacade,
cardSdkConfigRepository: CardSdkConfigRepository,
): SendTransactionUseCase {
return SendTransactionUseCase(
isDemoCardUseCase = isDemoCardUseCase,
cardSdkConfigRepository = cardSdkConfigRepository,
walletManagersFacade = walletManagersFacade,
)
}
}

View file

@ -67,15 +67,17 @@ internal class BiometricUserWalletsListManager(
}
}
.map {
if (throwIfNotAllWalletsUnlocked && state.value.userWallets.any(UserWallet::isLocked)) {
Timber.e("Not all user wallets have been unlocked")
val userWallets = state.value.userWallets
if (throwIfNotAllWalletsUnlocked && userWallets.any(UserWallet::isLocked)) {
Timber.e("Some user wallets remain locked")
throw UserWalletsListError.NotAllUserWalletsUnlocked
}
val selectedUserWallet = selectedUserWalletSync
if (selectedUserWallet == null || selectedUserWallet.isLocked) {
Timber.e("Unable to find selected user wallet")
throw UserWalletsListError.NoUserWalletSelected
findAndSetUnlockedUserWallet(userWallets)
?: throw UserWalletsListError.NoUserWalletSelected
} else {
selectedUserWallet
}
@ -280,13 +282,14 @@ internal class BiometricUserWalletsListManager(
prevSelectedWalletId: UserWalletId?,
userWallets: List<UserWallet>,
): UserWalletId? {
val findUnlockedAndSet = {
userWallets.firstOrNull { !it.isLocked }
?.walletId
?.also { selectedUserWalletRepository.set(it) }
}
return prevSelectedWalletId
?: (selectedUserWalletRepository.get() ?: findAndSetUnlockedUserWallet(userWallets)?.walletId)
}
return prevSelectedWalletId ?: (selectedUserWalletRepository.get() ?: findUnlockedAndSet())
private fun findAndSetUnlockedUserWallet(userWallets: List<UserWallet>): UserWallet? {
return userWallets
.firstOrNull { !it.isLocked }
?.also { selectedUserWalletRepository.set(it.walletId) }
}
private fun changeSelectedUserWalletIdIfNeeded(walletsIdsToRemove: List<UserWalletId>) {

View file

@ -14,11 +14,11 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.components.SpacerH4
import com.tangem.core.ui.components.SpacerW32
import com.tangem.core.ui.components.TangemSwitch
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.features.details.ui.appsettings.AppSettingsItemsFactory
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Item
import com.tangem.core.ui.components.TangemSwitch
@Composable
internal fun SettingsSwitchItem(item: Item.Switch, modifier: Modifier = Modifier) {
@ -63,6 +63,7 @@ internal fun SettingsSwitchItem(item: Item.Switch, modifier: Modifier = Modifier
checked = item.isChecked,
enabled = item.isEnabled,
onCheckedChange = item.onCheckedChange,
checkedColor = TangemTheme.colors.icon.accent,
)
}
}

View file

@ -20,6 +20,8 @@ import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
import com.tangem.domain.tokens.TokenWithBlockchain
import com.tangem.domain.tokens.TokensAction
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.walletconnect.WalletConnectActions
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.operations.derivation.ExtendedPublicKeysMap
import com.tangem.tap.*
@ -90,13 +92,17 @@ object TokensMiddleware {
if (scanResponse.supportsHdWallet()) {
deriveMissingCoins(scanResponse = scanResponse, currencyList = currencyList) {
submitNewAdd(
userWalletId = action.userWallet.walletId,
userWallet = action.userWallet,
updatedScanResponse = it,
currencyList = currencyList,
)
}
} else {
submitNewAdd(userWalletId = action.userWallet.walletId, scanResponse, currencyList = currencyList)
submitNewAdd(
userWallet = action.userWallet,
updatedScanResponse = scanResponse,
currencyList = currencyList,
)
}
}
}
@ -375,16 +381,18 @@ object TokensMiddleware {
}
private fun submitNewAdd(
userWalletId: UserWalletId,
userWallet: UserWallet,
updatedScanResponse: ScanResponse,
currencyList: List<CryptoCurrency>,
) {
scope.launch {
userWalletsListManager.update(
userWalletId = userWalletId,
userWalletId = userWallet.walletId,
update = { it.copy(scanResponse = updatedScanResponse) },
).doOnSuccess {
addCryptoCurrenciesUseCase(userWalletId, currencyList)
addCryptoCurrenciesUseCase(userWallet.walletId, currencyList).onRight {
store.dispatch(action = WalletConnectActions.New.SetupUserChains(userWallet = userWallet))
}
}
}
store.dispatchOnMain(NavigationAction.PopBackTo())