diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 0f0f3a0df3..23547755c9 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -137,6 +137,8 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac super.onCreate(savedInstanceState) + cardSdkLifecycleObserver.onCreate(context = this) + bootstrapMainStateUpdates(application) splashScreen.setKeepOnScreenCondition { isInitializing } @@ -146,8 +148,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac store.dispatch(NavigationAction.ActivityCreated(WeakReference(this))) - cardSdkLifecycleObserver.onCreate(context = this) - tangemSdkManager = injectedTangemSdkManager appStateHolder.tangemSdkManager = tangemSdkManager backupService = BackupService.init(cardSdkConfigRepository.sdk, this) diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt index fe1bb63d2a..f104a8ca09 100644 --- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt +++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt @@ -4,6 +4,7 @@ import com.tangem.blockchain.blockchains.cardano.CardanoUtils import com.tangem.blockchain.common.Blockchain import com.tangem.common.CompletionResult import com.tangem.common.card.EllipticCurve +import com.tangem.common.extensions.ByteArrayKey import com.tangem.common.extensions.guard import com.tangem.common.extensions.toMapKey import com.tangem.common.flatMap @@ -71,12 +72,22 @@ class DefaultCustomTokenInteractor( onSuccess: suspend (ScanResponse) -> Unit, ) { val config = CardConfig.createConfig(scanResponse.card) - val derivationDataList = currencyList.mapNotNull { - val curve = config.primaryCurve(it.blockchain) - curve?.let { getDerivations(curve, scanResponse, currencyList) } + val derivationDataList = currencyList.mapNotNull { currency -> + val curve = config.primaryCurve(currency.blockchain) + curve?.let { getDerivations(curve, scanResponse, currency) } } - val derivations = derivationDataList.associate(TokensMiddleware.DerivationData::derivations) + val derivations = buildMap> { + derivationDataList.forEach { + val current = this[it.derivations.first] + if (current != null) { + current.addAll(it.derivations.second) + current.distinct() + } else { + this[it.derivations.first] = it.derivations.second.toMutableList() + } + } + } if (derivations.isEmpty()) { onSuccess(scanResponse) return @@ -110,24 +121,22 @@ class DefaultCustomTokenInteractor( private fun getDerivations( curve: EllipticCurve, scanResponse: ScanResponse, - currencyList: List, + currency: Currency, ): TokensMiddleware.DerivationData? { val wallet = scanResponse.card.wallets.firstOrNull { it.curve == curve } ?: return null - val manageTokensCandidates = currencyList.map { it.blockchain }.distinct().filter { - it.getSupportedCurves().contains(curve) - }.mapNotNull { - it.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) - } + val supportedCurves = currency.blockchain.getSupportedCurves() + val path = currency.blockchain.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) + .takeIf { supportedCurves.contains(curve) } - val customTokensCandidates = currencyList.filter { - it.blockchain.getSupportedCurves().contains(curve) - }.mapNotNull { it.derivationPath }.map { DerivationPath(it) } + val customPath = currency.derivationPath?.let { + DerivationPath(it) + }.takeIf { supportedCurves.contains(curve) } - val bothCandidates = (manageTokensCandidates + customTokensCandidates).distinct().toMutableList() + val bothCandidates = listOfNotNull(path, customPath).distinct().toMutableList() if (bothCandidates.isEmpty()) return null - currencyList.find { it is Currency.Blockchain && it.blockchain == Blockchain.Cardano }?.let { currency -> + if (currency is Currency.Blockchain && currency.blockchain == Blockchain.Cardano) { currency.derivationPath?.let { bothCandidates.add(CardanoUtils.extendedDerivationPath(DerivationPath(it))) } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt index 7086d1408e..349a795f23 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt @@ -34,6 +34,14 @@ internal class AppSettingsFragment : ComposeFragment(), StoreSubscriber Unit, ) { val config = CardConfig.createConfig(scanResponse.card) - val derivationDataList = currencyList.mapNotNull { - val curve = config.primaryCurve(it.blockchain) - curve?.let { getLegacyDerivations(curve, scanResponse, currencyList) } + val derivationDataList = currencyList.mapNotNull { currency -> + val curve = config.primaryCurve(currency.blockchain) + curve?.let { getLegacyDerivations(curve, scanResponse, currency) } } - val derivations = derivationDataList.associate { it.derivations } + val derivations = buildMap> { + derivationDataList.forEach { + val current = this[it.derivations.first] + if (current != null) { + current.addAll(it.derivations.second) + current.distinct() + } else { + this[it.derivations.first] = it.derivations.second.toMutableList() + } + } + } + if (derivations.isEmpty()) { onSuccess(scanResponse) return @@ -204,9 +215,9 @@ object TokensMiddleware { onSuccess: (ScanResponse) -> Unit, ) { val config = CardConfig.createConfig(scanResponse.card) - val derivationDataList = currencyList.mapNotNull { - config.primaryCurve(blockchain = Blockchain.fromId(it.network.id.value)) - ?.let { curve -> getNewDerivations(curve, scanResponse, currencyList) } + val derivationDataList = currencyList.mapNotNull { currency -> + config.primaryCurve(blockchain = Blockchain.fromId(currency.network.id.value)) + ?.let { curve -> getNewDerivations(curve, scanResponse, currency) } } val derivations = derivationDataList.associate(DerivationData::derivations) if (derivations.isEmpty()) { @@ -249,24 +260,22 @@ object TokensMiddleware { private fun getLegacyDerivations( curve: EllipticCurve, scanResponse: ScanResponse, - currencyList: List, + currency: Currency, ): DerivationData? { val wallet = scanResponse.card.wallets.firstOrNull { it.curve == curve } ?: return null - val manageTokensCandidates = currencyList.map { it.blockchain }.distinct().filter { - it.getSupportedCurves().contains(curve) - }.mapNotNull { - it.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) - } + val supportedCurves = currency.blockchain.getSupportedCurves() + val path = currency.blockchain.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) + .takeIf { supportedCurves.contains(curve) } - val customTokensCandidates = currencyList.filter { - it.blockchain.getSupportedCurves().contains(curve) - }.mapNotNull { it.derivationPath }.map { DerivationPath(it) } + val customPath = currency.derivationPath?.let { + DerivationPath(it) + }.takeIf { supportedCurves.contains(curve) } - val bothCandidates = (manageTokensCandidates + customTokensCandidates).distinct().toMutableList() + val bothCandidates = listOfNotNull(path, customPath).distinct().toMutableList() if (bothCandidates.isEmpty()) return null - currencyList.find { it is Currency.Blockchain && it.blockchain == Blockchain.Cardano }?.let { currency -> + if (currency is Currency.Blockchain && currency.blockchain == Blockchain.Cardano) { currency.derivationPath?.let { bothCandidates.add(CardanoUtils.extendedDerivationPath(DerivationPath(it))) } @@ -286,30 +295,27 @@ object TokensMiddleware { private fun getNewDerivations( curve: EllipticCurve, scanResponse: ScanResponse, - currencyList: List, + currency: CryptoCurrency, ): DerivationData? { val wallet = scanResponse.card.wallets.firstOrNull { it.curve == curve } ?: return null - val manageTokensCandidates = currencyList - .map { Blockchain.fromId(it.network.id.value) } - .distinct() - .filter { it.getSupportedCurves().contains(curve) } - .mapNotNull { it.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) } + val blockchain = Blockchain.fromId(currency.network.id.value) + val supportedCurves = blockchain.getSupportedCurves() + val path = blockchain.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) + .takeIf { supportedCurves.contains(curve) } - val customTokensCandidates = currencyList - .filter { Blockchain.fromId(it.network.id.value).getSupportedCurves().contains(curve) } - .mapNotNull { it.network.derivationPath.value } - .map(::DerivationPath) + val customPath = currency.network.derivationPath.value?.let { + DerivationPath(it) + }.takeIf { supportedCurves.contains(curve) } - val bothCandidates = (manageTokensCandidates + customTokensCandidates).distinct().toMutableList() + val bothCandidates = listOfNotNull(path, customPath).distinct().toMutableList() if (bothCandidates.isEmpty()) return null - currencyList.find { it is CryptoCurrency.Coin && Blockchain.fromId(it.network.id.value) == Blockchain.Cardano } - ?.let { currency -> - currency.network.derivationPath.value?.let { - bothCandidates.add(CardanoUtils.extendedDerivationPath(DerivationPath(it))) - } + if (currency is CryptoCurrency.Coin && blockchain == Blockchain.Cardano) { + currency.network.derivationPath.value?.let { + bothCandidates.add(CardanoUtils.extendedDerivationPath(DerivationPath(it))) } + } val mapKeyOfWalletPublicKey = wallet.publicKey.toMapKey() val alreadyDerivedKeys: ExtendedPublicKeysMap = diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 0048c80636..f0bdd8f3f1 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -82,9 +82,6 @@ data class WalletState( get() = primaryWalletStore?.walletsData ?.firstOrNull { it.currency !is Currency.Blockchain } - val shouldShowDetails: Boolean = - primaryWalletData?.status !is WalletDataModel.Unreachable - fun getWalletManager(currency: Currency?): WalletManager? { if (currency?.blockchain == null) return null return getWalletStore(currency)?.walletManager diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index a8b503903d..67c74962d6 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -189,9 +189,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber Unit, ) { val config = CardConfig.createConfig(scanResponse.card) - val derivationDataList = currencyList.mapNotNull { - val curve = config.primaryCurve(it.blockchain) - curve?.let { getDerivations(curve, scanResponse, currencyList) } + val derivationDataList = currencyList.mapNotNull { currency -> + val curve = config.primaryCurve(currency.blockchain) + curve?.let { getDerivations(curve, scanResponse, currency) } + } + val derivations = buildMap> { + derivationDataList.forEach { + val current = this[it.derivations.first] + if (current != null) { + current.addAll(it.derivations.second) + current.distinct() + } else { + this[it.derivations.first] = it.derivations.second.toMutableList() + } + } } - val derivations = derivationDataList.associate { it.derivations } if (derivations.isEmpty()) { onSuccess(scanResponse) return @@ -159,23 +170,29 @@ class DerivationManagerImpl( private fun getDerivations( curve: EllipticCurve, scanResponse: ScanResponse, - currencyList: List, - ): DerivationData? { + currency: com.tangem.tap.features.wallet.models.Currency, + ): TokensMiddleware.DerivationData? { val wallet = scanResponse.card.wallets.firstOrNull { it.curve == curve } ?: return null - val manageTokensCandidates = currencyList.map { it.blockchain }.distinct().filter { - it.getSupportedCurves().contains(curve) - }.mapNotNull { - it.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) - } + val supportedCurves = currency.blockchain.getSupportedCurves() + val path = currency.blockchain.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) + .takeIf { supportedCurves.contains(curve) } - val customTokensCandidates = currencyList.filter { - it.blockchain.getSupportedCurves().contains(curve) - }.mapNotNull { it.derivationPath }.map { DerivationPath(it) } + val customPath = currency.derivationPath?.let { + DerivationPath(it) + }.takeIf { supportedCurves.contains(curve) } - val bothCandidates = (manageTokensCandidates + customTokensCandidates).distinct().toMutableList() + val bothCandidates = listOfNotNull(path, customPath).distinct().toMutableList() if (bothCandidates.isEmpty()) return null + if (currency is WalletModelCurrency.Blockchain && + currency.blockchain == Blockchain.Cardano + ) { + currency.derivationPath?.let { + bothCandidates.add(CardanoUtils.extendedDerivationPath(DerivationPath(it))) + } + } + val mapKeyOfWalletPublicKey = wallet.publicKey.toMapKey() val alreadyDerivedKeys: ExtendedPublicKeysMap = scanResponse.derivedKeys[mapKeyOfWalletPublicKey] ?: ExtendedPublicKeysMap(emptyMap()) @@ -184,16 +201,7 @@ class DerivationManagerImpl( val toDerive = bothCandidates.filterNot { alreadyDerivedPaths.contains(it) } if (toDerive.isEmpty()) return null - currencyList.find { it is WalletModelCurrency.Blockchain && it.blockchain == Blockchain.Cardano } - ?.let { currency -> - currency.derivationPath?.let { - bothCandidates.add(CardanoUtils.extendedDerivationPath(DerivationPath(it))) - } - } - - return DerivationData( - derivations = mapKeyOfWalletPublicKey to toDerive, - ) + return TokensMiddleware.DerivationData(derivations = mapKeyOfWalletPublicKey to toDerive) } /** diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json index 69ee462e61..25f17ea484 100644 --- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json @@ -5,7 +5,7 @@ }, { "name": "NEW_CARD_SCANNING_ENABLED", - "version": "4.11.0" + "version": "undefined" }, { "name": "REDESIGNED_WALLET_SCREEN_ENABLED", diff --git a/data/card/src/main/java/com/tangem/data/card/sdk/DefaultCardSdkProvider.kt b/data/card/src/main/java/com/tangem/data/card/sdk/DefaultCardSdkProvider.kt index c2c2a2dd19..1249de10d7 100644 --- a/data/card/src/main/java/com/tangem/data/card/sdk/DefaultCardSdkProvider.kt +++ b/data/card/src/main/java/com/tangem/data/card/sdk/DefaultCardSdkProvider.kt @@ -7,7 +7,6 @@ import com.tangem.common.CardFilter import com.tangem.common.card.FirmwareVersion import com.tangem.common.core.Config import com.tangem.sdk.extensions.initWithBiometrics -import java.lang.ref.WeakReference import javax.inject.Inject import javax.inject.Singleton @@ -20,17 +19,18 @@ import javax.inject.Singleton internal class DefaultCardSdkProvider @Inject constructor() : CardSdkProvider, CardSdkLifecycleObserver { override val sdk: TangemSdk - get() = requireNotNull(value = _sdk?.get()) { "Impossible to get the TangemSdk when activity is destroyed" } + get() = requireNotNull(value = _sdk) { "Impossible to get the TangemSdk when activity is destroyed" } - private var _sdk: WeakReference? = null + private var _sdk: TangemSdk? = null override fun onCreate(context: Context) { - _sdk = WeakReference(TangemSdk.initWithBiometrics(activity = context as FragmentActivity, config = config)) + _sdk = TangemSdk.initWithBiometrics(activity = context as FragmentActivity, config = config) } override fun onDestroy(context: Context) { // Commented out to prevent crash on getting sdk when it's null. // FIXME: We still should find the real cause and fix it properly. + // idea: pass everywhere DefaultCardSdkProvider instead sdk to reach lazy access to sdk property // _sdk = null } diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 9ccba53a4f..4c97997ed7 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -32,6 +32,7 @@ compose-navigation = "2.5.3" compose-accompanist = "0.30.1" compose-paging = "3.2.0" compose-reorderable = "0.9.6" +compoese-lifecycle-runtime = "2.6.1" # endregion Compose # region Other libraries @@ -80,9 +81,9 @@ okHttp-prettyLogging = "3.1.0" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_4.11-344" +tangemBlockchainSdk = "develop-350" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_4.11-294" +tangemCardSdk = "develop-297" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds # endregion Tangem @@ -132,7 +133,7 @@ androidx-paging-runtime = { module = "androidx.paging:paging-runtime", version.r lifecycle-common-java8 = { module = "androidx.lifecycle:lifecycle-common-java8", version.ref = "androidxLifecycle" } lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidxLifecycle" } lifecycle-viewModel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidxLifecycle" } -lifecycle-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidxLifecycle" } +lifecycle-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "compoese-lifecycle-runtime" } # region AndroidX # region Compose