diff --git a/build.gradle b/build.gradle index 6f173ef9ff..3cd1c511d2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,8 @@ buildscript { ext { // App version - versionName = '7.12.0' - versionCode = 132 + versionName = '7.12.1' + versionCode = 133 applicationId = "io.novafoundation.nova" releaseApplicationSuffix = "market" diff --git a/common/src/main/java/io/novafoundation/nova/common/domain/ExtendedLoadingState.kt b/common/src/main/java/io/novafoundation/nova/common/domain/ExtendedLoadingState.kt index d15ff520d6..683e12c5e2 100644 --- a/common/src/main/java/io/novafoundation/nova/common/domain/ExtendedLoadingState.kt +++ b/common/src/main/java/io/novafoundation/nova/common/domain/ExtendedLoadingState.kt @@ -82,3 +82,11 @@ inline fun ExtendedLoadingState.onNotLoaded(action: () -> Unit): Extended return this } + +inline fun ExtendedLoadingState.onError(action: (Throwable) -> Unit): ExtendedLoadingState { + if (this is ExtendedLoadingState.Error) { + action(exception) + } + + return this +} diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/nominationPools/repository/NominationPoolGlobalsRepository.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/nominationPools/repository/NominationPoolGlobalsRepository.kt index 2cda459284..39d2cfb680 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/nominationPools/repository/NominationPoolGlobalsRepository.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/nominationPools/repository/NominationPoolGlobalsRepository.kt @@ -1,6 +1,7 @@ package io.novafoundation.nova.feature_staking_impl.data.nominationPools.repository import io.novafoundation.nova.common.utils.orZero +import io.novafoundation.nova.feature_staking_api.domain.nominationPool.model.PoolId import io.novafoundation.nova.feature_staking_impl.data.nominationPools.datasource.KnownMaxUnlockingOverwrites import io.novafoundation.nova.feature_staking_impl.data.nominationPools.network.blockhain.api.counterForPoolMembers import io.novafoundation.nova.feature_staking_impl.data.nominationPools.network.blockhain.api.lastPoolId @@ -8,7 +9,6 @@ import io.novafoundation.nova.feature_staking_impl.data.nominationPools.network. import io.novafoundation.nova.feature_staking_impl.data.nominationPools.network.blockhain.api.maxPoolMembersPerPool import io.novafoundation.nova.feature_staking_impl.data.nominationPools.network.blockhain.api.minJoinBond import io.novafoundation.nova.feature_staking_impl.data.nominationPools.network.blockhain.api.nominationPools -import io.novafoundation.nova.feature_staking_api.domain.nominationPool.model.PoolId import io.novafoundation.nova.feature_staking_impl.data.repository.StakingConstantsRepository import io.novafoundation.nova.feature_wallet_api.data.network.blockhain.types.Balance import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId @@ -56,7 +56,7 @@ class RealNominationPoolGlobalsRepository( return localStorageDataSource.query(chainId) { val poolIdRaw = metadata.nominationPools.lastPoolId.query() - PoolId(poolIdRaw!!) + PoolId(poolIdRaw.orZero()) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/repository/StakingRepositoryImpl.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/repository/StakingRepositoryImpl.kt index f25a674296..b7d96a6ef9 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/repository/StakingRepositoryImpl.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/repository/StakingRepositoryImpl.kt @@ -66,7 +66,6 @@ import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.withContext import java.math.BigInteger -import kotlinx.coroutines.flow.map class StakingRepositoryImpl( private val accountStakingDao: AccountStakingDao, @@ -136,11 +135,17 @@ class StakingRepositoryImpl( binding = { instance, _ -> bindExposureOverview(instance) } ) - val eraStakersPaged = runtime.metadata.staking().storage("ErasStakersPaged").entries( - eraIndex, - keyExtractor = { (_: BigInteger, accountId: ByteArray, page: BigInteger) -> accountId.toHexString() to page.toInt() }, - binding = { instance, _ -> bindExposurePage(instance) } - ) + val atLeastOneNominatorPresent = eraStakersOverview.any { (_, exposureOverview) -> exposureOverview.nominatorCount > BigInteger.ZERO } + + val eraStakersPaged = if (atLeastOneNominatorPresent) { + runtime.metadata.staking().storage("ErasStakersPaged").entries( + eraIndex, + keyExtractor = { (_: BigInteger, accountId: ByteArray, page: BigInteger) -> accountId.toHexString() to page.toInt() }, + binding = { instance, _ -> bindExposurePage(instance) } + ) + } else { + emptyMap() + } mergeOverviewsAndPagedOthers(eraStakersOverview, eraStakersPaged) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/repository/VaraRepository.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/repository/VaraRepository.kt index 68698a3746..2e69c1e5d8 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/repository/VaraRepository.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/data/repository/VaraRepository.kt @@ -10,7 +10,7 @@ import io.novasama.substrate_sdk_android.wsrpc.executeAsync import io.novasama.substrate_sdk_android.wsrpc.mappers.nonNull import io.novasama.substrate_sdk_android.wsrpc.mappers.pojo import io.novasama.substrate_sdk_android.wsrpc.request.runtime.RuntimeRequest -import java.math.BigInteger +import java.math.BigDecimal interface VaraRepository { @@ -22,7 +22,9 @@ class RealVaraRepository( ) : VaraRepository { override suspend fun getVaraInflation(chainId: ChainId): Perbill { - return chainRegistry.getSocket(chainId).inflationInfo().inflation.asPerQuintill() + return chainRegistry.getSocket(chainId).inflationInfo().inflation + .toBigInteger() + .asPerQuintill() } private suspend fun SocketService.inflationInfo(): InflationInfo { @@ -34,5 +36,5 @@ class RealVaraRepository( params = emptyList() ) - private class InflationInfo(val inflation: BigInteger) + private class InflationInfo(val inflation: BigDecimal) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/pools/recommendation/NominationPoolRecommender.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/pools/recommendation/NominationPoolRecommender.kt index a3763104d9..cbee477d8b 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/pools/recommendation/NominationPoolRecommender.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/pools/recommendation/NominationPoolRecommender.kt @@ -6,5 +6,5 @@ interface NominationPoolRecommender { val recommendations: List - fun recommendedPool(): NominationPool + fun recommendedPool(): NominationPool? } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/pools/recommendation/NominationPoolRecommenderFactory.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/pools/recommendation/NominationPoolRecommenderFactory.kt index 26d7f0f3be..51d6adca1b 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/pools/recommendation/NominationPoolRecommenderFactory.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/nominationPools/pools/recommendation/NominationPoolRecommenderFactory.kt @@ -43,8 +43,8 @@ private class RealNominationPoolRecommender( override val recommendations = constructRecommendationList() - override fun recommendedPool(): NominationPool { - return recommendations.first() + override fun recommendedPool(): NominationPool? { + return recommendations.firstOrNull() } private fun constructRecommendationList(): List { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/ValidatorRecommender.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/ValidatorRecommender.kt index f019461729..b6e1029d18 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/ValidatorRecommender.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/ValidatorRecommender.kt @@ -2,6 +2,7 @@ package io.novafoundation.nova.feature_staking_impl.domain.recommendations import io.novafoundation.nova.common.utils.applyFilters import io.novafoundation.nova.feature_staking_api.domain.model.Validator +import io.novafoundation.nova.feature_staking_impl.domain.recommendations.settings.RecommendationFilter import io.novafoundation.nova.feature_staking_impl.domain.recommendations.settings.RecommendationSettings import io.novafoundation.nova.feature_staking_impl.domain.recommendations.settings.RecommendationSorting import kotlinx.coroutines.Dispatchers @@ -13,7 +14,7 @@ class ValidatorRecommender( ) { suspend fun recommendations(settings: RecommendationSettings) = withContext(Dispatchers.Default) { - val all = availableValidators.applyFilters(settings.allFilters) + val all = availableValidators.applyFiltersAdaptingToEmptyResult(settings.allFilters) .sortedWith(settings.sorting) val postprocessed = settings.postProcessors.fold(all) { acc, postProcessor -> @@ -37,4 +38,16 @@ class ValidatorRecommender( return (cappedNovaValidators + cappedOthers).sortedWith(sorting) } + + private fun List.applyFiltersAdaptingToEmptyResult(filters: List): List { + var filtered = applyFilters(filters) + + if (filtered.isEmpty()) { + val weakenedFilters = filters.filterNot { it.canIgnoreWhenNoApplicableCandidatesFound() } + + filtered = applyFilters(weakenedFilters) + } + + return filtered + } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/RecommendationSettings.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/RecommendationSettings.kt index 3b94901718..ebd728c889 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/RecommendationSettings.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/RecommendationSettings.kt @@ -4,7 +4,11 @@ import io.novafoundation.nova.common.utils.PalletBasedFilter import io.novafoundation.nova.common.utils.RuntimeDependent import io.novafoundation.nova.feature_staking_api.domain.model.Validator -typealias RecommendationFilter = PalletBasedFilter +interface RecommendationFilter : PalletBasedFilter { + + fun canIgnoreWhenNoApplicableCandidatesFound(): Boolean +} + typealias RecommendationSorting = Comparator interface RecommendationPostProcessor : RuntimeDependent { diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/HasIdentityFilter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/HasIdentityFilter.kt index 8ac2ad6825..8a2a05ea85 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/HasIdentityFilter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/HasIdentityFilter.kt @@ -12,6 +12,10 @@ object HasIdentityFilter : RecommendationFilter { return model.identity != null } + override fun canIgnoreWhenNoApplicableCandidatesFound(): Boolean { + return true + } + override fun availableIn(runtime: RuntimeSnapshot): Boolean { return runtime.metadata.hasModule(Modules.IDENTITY) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotBlockedFilter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotBlockedFilter.kt index 0703a1ebd8..e54d578eee 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotBlockedFilter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotBlockedFilter.kt @@ -5,5 +5,9 @@ import io.novafoundation.nova.feature_staking_impl.domain.recommendations.settin object NotBlockedFilter : RecommendationFilter { + override fun canIgnoreWhenNoApplicableCandidatesFound(): Boolean { + return false + } + override fun shouldInclude(model: Validator) = model.prefs?.blocked?.not() ?: false } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotOverSubscribedFilter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotOverSubscribedFilter.kt index 0011914783..77fb25ded3 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotOverSubscribedFilter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotOverSubscribedFilter.kt @@ -5,6 +5,10 @@ import io.novafoundation.nova.feature_staking_impl.domain.recommendations.settin object NotOverSubscribedFilter : RecommendationFilter { + override fun canIgnoreWhenNoApplicableCandidatesFound(): Boolean { + return true + } + override fun shouldInclude(model: Validator): Boolean { val isOversubscribed = model.electedInfo?.isOversubscribed diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotSlashedFilter.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotSlashedFilter.kt index e7b7daea74..4005020ac2 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotSlashedFilter.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/recommendations/settings/filters/NotSlashedFilter.kt @@ -5,6 +5,10 @@ import io.novafoundation.nova.feature_staking_impl.domain.recommendations.settin object NotSlashedFilter : RecommendationFilter { + override fun canIgnoreWhenNoApplicableCandidatesFound(): Boolean { + return true + } + override fun shouldInclude(model: Validator): Boolean { return !model.slashed } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/rewards/VaraRewardCalculator.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/rewards/VaraRewardCalculator.kt index bf1cbbfe19..5906daa578 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/rewards/VaraRewardCalculator.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/rewards/VaraRewardCalculator.kt @@ -10,6 +10,9 @@ class VaraRewardCalculator( ) : InflationBasedRewardCalculator(validators, totalIssuance) { override fun calculateYearlyInflation(stakedPortion: Double): Double { - return inflation.value + // When calculating era payout, Vara runtime simply divides yearly payout by number of eras in the year + // Which results in `inflation` to correspond to simple returns (APR) + // So, we adjust it to compound returns (APY) + return aprToApy(inflation.value) } } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/SingleStakingProperties.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/SingleStakingProperties.kt index 631d79edc6..5ce2ee3556 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/SingleStakingProperties.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/SingleStakingProperties.kt @@ -23,5 +23,5 @@ interface SingleStakingProperties { interface SingleStakingRecommendation { - suspend fun recommendedSelection(stake: Balance): StartMultiStakingSelection + suspend fun recommendedSelection(stake: Balance): StartMultiStakingSelection? } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/pools/NominationPoolRecommendation.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/pools/NominationPoolRecommendation.kt index 8959f53908..fce77ad74e 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/pools/NominationPoolRecommendation.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/pools/NominationPoolRecommendation.kt @@ -18,8 +18,8 @@ class NominationPoolRecommendation( nominationPoolRecommenderFactory.create(stakingOption, scope) } - override suspend fun recommendedSelection(stake: Balance): StartMultiStakingSelection { - val recommendedPool = recommendator.await().recommendedPool() + override suspend fun recommendedSelection(stake: Balance): StartMultiStakingSelection? { + val recommendedPool = recommendator.await().recommendedPool() ?: return null return NominationPoolSelection(recommendedPool, stakingOption, stake) } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/selectionType/AutomaticMultiStakingSelectionType.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/selectionType/AutomaticMultiStakingSelectionType.kt index 05a633e917..6ff97cf602 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/selectionType/AutomaticMultiStakingSelectionType.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupAmount/selectionType/AutomaticMultiStakingSelectionType.kt @@ -40,7 +40,8 @@ class AutomaticMultiStakingSelectionType( } override suspend fun updateSelectionFor(stake: Balance) { - val selection = selectionFor(stake) + val selection = selectionFor(stake) ?: return + val recommendableSelection = RecommendableMultiStakingSelection( source = SelectionTypeSource.Automatic, selection = selection @@ -49,7 +50,7 @@ class AutomaticMultiStakingSelectionType( selectionStore.updateSelection(recommendableSelection) } - private suspend fun selectionFor(stake: Balance): StartMultiStakingSelection { + private suspend fun selectionFor(stake: Balance): StartMultiStakingSelection? { val candidate = candidates.firstAllowingToStake(stake) ?: candidates.findWithMinimumStake() return candidate.recommendation.recommendedSelection(stake) diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupStakingType/SetupStakingTypeSelectionMixin.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupStakingType/SetupStakingTypeSelectionMixin.kt index 41a1f188d9..a063e2dc33 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupStakingType/SetupStakingTypeSelectionMixin.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/domain/staking/start/setupStakingType/SetupStakingTypeSelectionMixin.kt @@ -1,6 +1,5 @@ package io.novafoundation.nova.feature_staking_impl.domain.staking.start.setupStakingType -import androidx.lifecycle.viewModelScope import io.novafoundation.nova.feature_staking_api.domain.model.Validator import io.novafoundation.nova.feature_staking_impl.data.StakingOption import io.novafoundation.nova.feature_staking_impl.domain.nominationPools.model.NominationPool @@ -12,10 +11,10 @@ import io.novafoundation.nova.feature_staking_impl.domain.staking.start.common.s import io.novafoundation.nova.feature_staking_impl.domain.staking.start.setupAmount.SingleStakingPropertiesFactory import io.novafoundation.nova.feature_staking_impl.domain.staking.start.setupAmount.direct.DirectStakingSelection import io.novafoundation.nova.feature_staking_impl.domain.staking.start.setupAmount.pools.NominationPoolSelection -import java.math.BigInteger import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first +import java.math.BigInteger class SetupStakingTypeSelectionMixinFactory( private val currentSelectionStoreProvider: StartMultiStakingSelectionStoreProvider, @@ -68,10 +67,13 @@ class SetupStakingTypeSelectionMixin( .recommendation .recommendedSelection(selection.stake) + // Content is not recommended if recommendation does not exist + val contentRecommended = recommendedSelection?.isSettingsEquals(selection) ?: false + currentSelectionStoreProvider.getSelectionStore(scope) .updateSelection( RecommendableMultiStakingSelection( - SelectionTypeSource.Manual(contentRecommended = recommendedSelection.isSettingsEquals(selection)), + SelectionTypeSource.Manual(contentRecommended = contentRecommended), selection ) ) @@ -80,7 +82,7 @@ class SetupStakingTypeSelectionMixin( suspend fun selectRecommended(viewModelScope: CoroutineScope, stakingOption: StakingOption, amount: BigInteger) { val recommendedSelection = singleStakingPropertiesFactory.createProperties(scope, stakingOption) .recommendation - .recommendedSelection(amount) + .recommendedSelection(amount) ?: return val recommendableMultiStakingSelection = RecommendableMultiStakingSelection( source = SelectionTypeSource.Manual(contentRecommended = true), diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/pools/selectPool/SelectPoolViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/pools/selectPool/SelectPoolViewModel.kt index 3bce4de777..f73ebeec52 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/pools/selectPool/SelectPoolViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/pools/selectPool/SelectPoolViewModel.kt @@ -22,13 +22,13 @@ import io.novafoundation.nova.feature_staking_impl.presentation.pools.common.Poo import io.novafoundation.nova.feature_staking_impl.presentation.pools.common.SelectingPoolPayload import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.chainWithAsset -import java.math.BigInteger import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import java.math.BigInteger class SelectPoolViewModel( private val router: StakingRouter, @@ -68,7 +68,9 @@ class SelectPoolViewModel( val fillWithRecommendedEnabled = combine(nominationPoolRecommenderFlow, editableSelection) { recommender, selection -> val selectedPool = selection.selection.asPoolSelection()?.pool - recommender.recommendedPool().id != selectedPool?.id + val recommendedPool = recommender.recommendedPool() + + recommendedPool != null && recommendedPool.id != selectedPool?.id } .share() @@ -99,7 +101,7 @@ class SelectPoolViewModel( fun selectRecommended() { launch { - val recommendedPool = nominationPoolRecommenderFlow.first().recommendedPool() + val recommendedPool = nominationPoolRecommenderFlow.first().recommendedPool() ?: return@launch setupStakingTypeSelectionMixin.selectNominationPoolAndApply(recommendedPool, stakingOption()) router.finishSetupPoolFlow() } diff --git a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/start/landing/StartStakingLandingViewModel.kt b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/start/landing/StartStakingLandingViewModel.kt index e460f757c7..27bbd1c154 100644 --- a/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/start/landing/StartStakingLandingViewModel.kt +++ b/feature-staking-impl/src/main/java/io/novafoundation/nova/feature_staking_impl/presentation/staking/start/landing/StartStakingLandingViewModel.kt @@ -1,12 +1,14 @@ package io.novafoundation.nova.feature_staking_impl.presentation.staking.start.landing import android.graphics.Color +import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import io.novafoundation.nova.common.base.BaseViewModel import io.novafoundation.nova.common.data.network.AppLinksProvider import io.novafoundation.nova.common.domain.isLoading import io.novafoundation.nova.common.domain.mapLoading +import io.novafoundation.nova.common.domain.onError import io.novafoundation.nova.common.mixin.actionAwaitable.ActionAwaitableMixin import io.novafoundation.nova.common.mixin.actionAwaitable.confirmingAction import io.novafoundation.nova.common.mixin.api.Browserable @@ -15,23 +17,23 @@ import io.novafoundation.nova.common.resources.ContextManager import io.novafoundation.nova.common.resources.ResourceManager import io.novafoundation.nova.common.utils.Event import io.novafoundation.nova.common.utils.Perbill -import io.novafoundation.nova.common.utils.formatting.spannable.SpannableFormatter import io.novafoundation.nova.common.utils.clickableSpan import io.novafoundation.nova.common.utils.colorSpan import io.novafoundation.nova.common.utils.drawableSpan import io.novafoundation.nova.common.utils.flowOf import io.novafoundation.nova.common.utils.fontSpan import io.novafoundation.nova.common.utils.formatAsSpannable +import io.novafoundation.nova.common.utils.formatting.baseDurationFormatter import io.novafoundation.nova.common.utils.formatting.duration.BoundedDurationFormatter import io.novafoundation.nova.common.utils.formatting.duration.DayAndHourDurationFormatter import io.novafoundation.nova.common.utils.formatting.duration.DayDurationFormatter +import io.novafoundation.nova.common.utils.formatting.duration.DayDurationShortcut import io.novafoundation.nova.common.utils.formatting.duration.DurationFormatter import io.novafoundation.nova.common.utils.formatting.duration.HoursDurationFormatter import io.novafoundation.nova.common.utils.formatting.duration.ShortcutDurationFormatter -import io.novafoundation.nova.common.utils.formatting.baseDurationFormatter -import io.novafoundation.nova.common.utils.formatting.duration.DayDurationShortcut import io.novafoundation.nova.common.utils.formatting.duration.wrapInto import io.novafoundation.nova.common.utils.formatting.format +import io.novafoundation.nova.common.utils.formatting.spannable.SpannableFormatter import io.novafoundation.nova.common.utils.setEndSpan import io.novafoundation.nova.common.utils.setFullSpan import io.novafoundation.nova.common.utils.toSpannable @@ -41,20 +43,20 @@ import io.novafoundation.nova.common.validation.progressConsumer import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase import io.novafoundation.nova.feature_staking_impl.R import io.novafoundation.nova.feature_staking_impl.data.network.blockhain.updaters.StakingLandingInfoUpdateSystemFactory +import io.novafoundation.nova.feature_staking_impl.domain.model.PayoutType import io.novafoundation.nova.feature_staking_impl.domain.staking.start.common.StakingStartedDetectionService import io.novafoundation.nova.feature_staking_impl.domain.staking.start.common.awaitStakingStarted import io.novafoundation.nova.feature_staking_impl.domain.staking.start.landing.ParticipationInGovernance import io.novafoundation.nova.feature_staking_impl.domain.staking.start.landing.Payouts +import io.novafoundation.nova.feature_staking_impl.domain.staking.start.landing.StakingTypeDetailsCompoundInteractorFactory import io.novafoundation.nova.feature_staking_impl.domain.staking.start.landing.StartStakingCompoundData import io.novafoundation.nova.feature_staking_impl.domain.staking.start.landing.validations.StartStakingLandingValidationPayload import io.novafoundation.nova.feature_staking_impl.domain.staking.start.landing.validations.handleStartStakingLandingValidationFailure -import io.novafoundation.nova.feature_staking_impl.domain.staking.start.landing.StakingTypeDetailsCompoundInteractorFactory import io.novafoundation.nova.feature_staking_impl.presentation.StartMultiStakingRouter import io.novafoundation.nova.feature_staking_impl.presentation.staking.start.common.toStakingOptionIds import io.novafoundation.nova.feature_staking_impl.presentation.staking.start.landing.model.StakingConditionRVItem import io.novafoundation.nova.feature_staking_impl.presentation.staking.start.landing.model.StartStakingLandingPayload import io.novafoundation.nova.feature_staking_impl.presentation.staking.start.setupAmount.SetupAmountMultiStakingPayload -import io.novafoundation.nova.feature_staking_impl.domain.model.PayoutType import io.novafoundation.nova.feature_wallet_api.domain.model.Asset import io.novafoundation.nova.feature_wallet_api.presentation.formatters.formatPlanks import io.novafoundation.nova.feature_wallet_api.presentation.model.mapAmountToAmountModel @@ -63,15 +65,16 @@ import io.novafoundation.nova.runtime.ext.group import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry import io.novafoundation.nova.runtime.multiNetwork.asset import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain +import io.novasama.substrate_sdk_android.hash.isPositive import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import java.math.BigInteger -import io.novasama.substrate_sdk_android.hash.isPositive import kotlin.time.Duration class StartStakingInfoModel( @@ -131,7 +134,9 @@ class StartStakingLandingViewModel( moreInfo = createMoreInfoText(it.chain), buttonColor = themeColor ) - }.shareInBackground() + } + .onEach { it.onError { Log.e("StartStakingLandingViewModel", "Failed to load staking info", it) } } + .shareInBackground() private val availableBalance = startStakingInteractor.flatMapLatest { interactor -> interactor.observeAvailableBalance() diff --git a/gradle.properties b/gradle.properties index 4eaf4f784c..828c450395 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,6 +12,6 @@ # org.gradle.parallel=true #Fri Feb 16 12:00:34 MSK 2024 org.gradle.parallel=true -org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M" +org.gradle.jvmargs=-Xmx3096M -Dkotlin.daemon.jvm.options\="-Xmx3096M" android.useAndroidX=true android.enableJetifier=true diff --git a/runtime/build.gradle b/runtime/build.gradle index a055d684dc..f8e5ada18a 100644 --- a/runtime/build.gradle +++ b/runtime/build.gradle @@ -13,7 +13,7 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/novasamatech/nova-utils/master/chains/v19/chains_dev.json\"" + buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/novasamatech/nova-utils/master/chains/v20/chains_dev.json\"" buildConfigField "String", "EVM_ASSETS_URL", "\"https://raw.githubusercontent.com/novasamatech/nova-utils/master/assets/evm/v2/assets_dev.json\"" buildConfigField "String", "TEST_CHAINS_URL", "\"https://raw.githubusercontent.com/novasamatech/nova-utils/master/tests/chains_for_testBalance.json\"" @@ -31,7 +31,7 @@ android { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/novasamatech/nova-utils/master/chains/v19/chains.json\"" + buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/novasamatech/nova-utils/master/chains/v20/chains.json\"" buildConfigField "String", "EVM_ASSETS_URL", "\"https://raw.githubusercontent.com/novasamatech/nova-utils/master/assets/evm/v2/assets.json\"" } }